-
-
Save amiika/66b3ce4ace5ac60b64bca2f6c03a0064 to your computer and use it in GitHub Desktop.
Strumming guitar chords in Sonic Pi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Guitar Strumming - by Emlyn (modified by amiika) | |
# This tries to work out the guitar (or ukulele etc.) fingering for arbitrary chords (and tuning). | |
# It seems to work reasonably well for basic chords, but is quite naive and probably makes many mistakes. | |
# Ideas, bug reports, fixes etc. gratefully received, just comment below, or tweet @emlyn77. | |
# Feel free to make use of this code as you like (with attribution if you feel like it, but you don't have to). | |
# Thanks to @Project_Hell_CK for fixing the tuning, and spotting that it gets chord(:f, :major) not quite right. | |
define :next_note do |n, c| | |
# Make sure n is a number | |
n = note(n) | |
# Get distances to each note in chord, add smallest to base note | |
n + (c.map {|x| (note(x) - n) % 12}).min | |
end | |
ukulele = [:g, :c, :e, :a] | |
guitar_standard = [:e2, :a2, :d3, :g3, :b3, :e4] | |
# Return ring representing the chord chrd, as played on a guitar with given tuning | |
define :guitar do |chrd, tuning=guitar_standard| | |
# For each string, get the next higher note that is in the chord | |
c = tuning.map {|n| next_note(n, chrd)}.ring | |
# We want the lowest note to be the root of the chord | |
root = note(chrd[0]) | |
first_root = c.take_while {|n| (n - root) % 12 != 0}.count | |
# Drop up to half the lowest strings to make that the case if possible | |
if first_root > 0 and first_root < tuning.count / 2 | |
c = (ring :r) * first_root + c.drop(first_root) | |
end | |
# Display chord fingering | |
#puts c.zip(tuning).map {|n, s| if n == :r then 'x' else (n - note(s)) end}.join, c | |
c | |
end | |
#! Removed thread ... works better on my machine. | |
# Strum a chord with a certain delay between strings | |
define :strum do |c, d=0.05, vol=0.25, pan=0| | |
play_pattern_timed c, d, amp: vol, pan: pan | |
end | |
# Function that transforms progression arrays to rings (easier to maintain) | |
define :fromProgression do |pname, pkey, pscale| | |
progs = { | |
gypsy: [:i, :vi, :ii, :v, :i, :vi, :ii, :v], | |
swing: [:i,:i,:iv,:iv,:v,:v,:i,:i,:iv,:vii,:iii,:vi,:ii,:v,:i,:v], | |
simple: [:i,:iv, :v], | |
basic: [:i, :vi, :ii, :v], | |
blues: [:i,:i,:i,:i,:iv,:iv,:i,:i,:v,:iv,:i,:v], | |
jazzy: [:vi, :iv, :ii, :iii] | |
} | |
progs[pname].map do |deg| | |
chord_degree deg, pkey, pscale | |
end.ring | |
end | |
use_debug false | |
use_bpm 130 | |
use_octave -1 | |
# New way of gettin chords | |
# Check out scale from help | |
chords = fromProgression :gypsy, :c, :major | |
#chords = fromProgression :basic, :a, :gong | |
#strumming = ring("DD.DD.DU..DU") | |
# Custom progression rings works too with sonic pi: chord or chord_degree | |
#chords = ring((guitar chord :a, :m), (guitar chord :c, :M), (guitar chord :d, :M), (ring :r, :r, 53, 57, 60, 65), | |
# (guitar chord :a, :m), (guitar chord :c, :M), (guitar chord :e, :M), (guitar chord :e, '7')) | |
# Strumming as a ring makes it more interesting | |
strumming = ring("UD..D.","uD..D.","UD..D.","uD..D.",".D..U.",".D..d.",".D..d.","UD.UD*") | |
print chords | |
live_loop :guit do | |
with_fx :reverb do | |
with_fx :lpf, cutoff: 130 do | |
with_synth :pluck do | |
tick | |
strumming.look.split(//).each do |s| | |
if s == 'D' # Down stroke | |
strum chords.look, 0.02, 0.4 | |
elsif s == 'U' # Up stroke | |
strum chords.look.reverse, 0.02, 0.4 | |
elsif s == 'd' | |
strum chords.look, 0.02, 0.3, -1 | |
elsif s == 'u' | |
strum chords.look.reverse, 0.02, 0.3, -1 | |
end | |
if s == '*' | |
sleep 0.15 | |
else | |
sleep 0.25 | |
end | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment