Skip to content

Instantly share code, notes, and snippets.

@matthewconstantine
Created August 12, 2008 04:52
Show Gist options
  • Save matthewconstantine/5006 to your computer and use it in GitHub Desktop.
Save matthewconstantine/5006 to your computer and use it in GitHub Desktop.
class Scale
def initialize(steps)
@steps = steps
end
# returns the number of half-steps from zero for any degree of a scale
def [](degree)
@steps[degree % @steps.length] + (12*(degree/@steps.length))
end
# finds the interval for any pitch in a scale
# or nil if the pitch doesn't exist in a scale
def index(pitch)
i = base_index(pitch)
return nil if i.nil?
i + (@steps.length*(pitch/12)) # => 6, 6, 43, 43, 43
end
def base_index(pitch) #probably needs a different name
@steps.index(pitch % 12)
end
# for a scale begining on tonic return the pitch of the next interval
def next(tonic, pitch, interval=1)
off = tonic % 12
self[self.index(pitch - off) + interval] + off
end
end
# Demonstration: (TextMate users hit cmd-ctrl-shift-e to play along)
# The steps of a major scale:
maj = Scale.new [0,2,4,5,7,9,11]
# The 6th degree is 11 half-steps from tonic
maj[6] # => 11
# and likewise, 11 half-notes is 6 degrees from tonic
maj.index(11) # => 6
# the Scale#[] is like an Array#[] except it extends the base pattern
(-6..6).collect {|x| maj[x] } # => [-10, -8, -7, -5, -3, -1, 0, 2, 4, 5, 7, 9, 11]
maj.index(11) # => 6
(0..12).map{|x|maj[44 + x]} # => [76, 77, 79, 81, 83, 84, 86, 88, 89, 91, 93, 95, 96]
# For a major scale with a tonic of 62(D4) find the next interval for pitch 76
# keep in mind 76 is assumed to be within the given scale
maj.next(62, 76) # => 78
maj.next(62, 76, 3) # => 81
maj.next(62, 76, -3) # => 71
# reference that sort of helps prove the maj.next statement
# borrowed from jvoorhis
C4 = 60
CS4 = 61
D4 = 62 # +0
DS4 = 63
E4 = 64 # +2
F4 = 65
FS4 = 66 # +4
G4 = 67 # +5
GS4 = 68
A4 = 69 # +7
AS4 = 70
B4 = 71 # +9
C5 = 72
CS5 = 73 # +11
D5 = 74 # +12
DS5 = 75
E5 = 76 #
F5 = 77
FS5 = 78 #
G5 = 79 #
GS5 = 80
A5 = 81 #
AS5 = 82
B5 = 83 #
C6 = 84
CS6 = 85 #
D6 = 86 #
DS6 = 87
E6 = 88
F6 = 89
FS6 = 90
G6 = 91
GS6 = 92
A6 = 93
AS6 = 94
B6 = 95
C7 = 96
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment