coltrane 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +21 -3
- data/README.md +0 -7
- data/Rakefile +5 -0
- data/bin/console +2 -0
- data/bin/opal +29 -0
- data/bin/opal-build +29 -0
- data/bin/opal-mspec +29 -0
- data/bin/opal-repl +29 -0
- data/bin/rackup +12 -0
- data/bin/sprockets +12 -0
- data/bin/tilt +12 -0
- data/coltrane.gemspec +1 -1
- data/config.ru +10 -0
- data/exe/coltrane +44 -13
- data/lib/cli.rb +7 -1
- data/lib/cli/bass_guitar.rb +1 -1
- data/lib/cli/chord.rb +11 -4
- data/lib/cli/config.rb +38 -0
- data/lib/cli/guitar.rb +8 -10
- data/lib/cli/guitar_chords.rb +122 -0
- data/lib/cli/notes.rb +3 -4
- data/lib/cli/piano.rb +1 -1
- data/lib/cli/representation.rb +6 -12
- data/lib/cli/scale.rb +4 -4
- data/lib/cli/text.rb +1 -1
- data/lib/cli/ukulele.rb +1 -1
- data/lib/coltrane.rb +35 -32
- data/lib/coltrane/chord_quality.rb +4 -3
- data/lib/coltrane/circle_of_fifths.rb +29 -0
- data/lib/coltrane/classic_scales.rb +36 -43
- data/lib/coltrane/diatonic_scale.rb +34 -0
- data/lib/coltrane/frequency.rb +1 -1
- data/lib/coltrane/interval.rb +14 -0
- data/lib/coltrane/interval_class.rb +6 -0
- data/lib/coltrane/interval_sequence.rb +0 -1
- data/lib/coltrane/key.rb +14 -0
- data/lib/coltrane/note.rb +37 -2
- data/lib/coltrane/note_set.rb +23 -2
- data/lib/coltrane/pitch.rb +65 -31
- data/lib/coltrane/pitch_class.rb +25 -12
- data/lib/coltrane/progression.rb +2 -2
- data/lib/coltrane/qualities.rb +257 -0
- data/lib/coltrane/roman_chord.rb +10 -10
- data/lib/coltrane/scale.rb +9 -3
- data/lib/coltrane/version.rb +1 -1
- data/lib/coltrane/voicing.rb +38 -0
- data/lib/coltrane_game/question.rb +6 -0
- data/lib/coltrane_instruments.rb +3 -0
- data/lib/coltrane_instruments/guitar.rb +5 -2
- data/lib/coltrane_instruments/guitar/base.rb +18 -3
- data/lib/coltrane_instruments/guitar/chord.rb +139 -12
- data/lib/coltrane_instruments/guitar/note.rb +16 -0
- data/lib/coltrane_instruments/guitar/string.rb +21 -0
- data/lib/coltrane_synth.rb +7 -0
- data/lib/coltrane_synth/base.rb +47 -0
- data/lib/coltrane_synth/synth.rb +24 -0
- data/lib/core_ext.rb +25 -7
- data/lib/os.rb +19 -0
- metadata +24 -9
- data/dist/coltrane +0 -0
- data/lib/coltrane/piano_representation.rb +0 -0
data/lib/coltrane/pitch_class.rb
CHANGED
@@ -12,6 +12,7 @@ module Coltrane
|
|
12
12
|
#
|
13
13
|
class PitchClass
|
14
14
|
attr_reader :integer
|
15
|
+
include Comparable
|
15
16
|
|
16
17
|
NOTATION = %w[C C# D D# E F F# G G# A A# B].freeze
|
17
18
|
|
@@ -19,14 +20,14 @@ module Coltrane
|
|
19
20
|
NOTATION.map { |n| new(n) }
|
20
21
|
end
|
21
22
|
|
22
|
-
def initialize(arg, frequency: nil)
|
23
|
+
def initialize(arg=nil, frequency: nil)
|
23
24
|
@integer = case arg
|
24
25
|
when String then NOTATION.index(arg)
|
25
|
-
when Frequency
|
26
|
-
when
|
27
|
-
when
|
26
|
+
when Frequency then frequency_to_integer(Frequency.new(arg))
|
27
|
+
when Numeric then (arg % 12)
|
28
|
+
when nil then frequency_to_integer(Frequency.new(frequency))
|
28
29
|
when PitchClass then arg.integer
|
29
|
-
else raise(
|
30
|
+
else raise(WrongArgumentsError)
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
@@ -55,27 +56,39 @@ module Coltrane
|
|
55
56
|
notation.match? /#|b/
|
56
57
|
end
|
57
58
|
|
59
|
+
def sharp?
|
60
|
+
notation.match? /#/
|
61
|
+
end
|
62
|
+
|
63
|
+
def flat?
|
64
|
+
notation.match? /b/
|
65
|
+
end
|
66
|
+
|
58
67
|
alias notation true_notation
|
59
68
|
alias to_s true_notation
|
60
69
|
|
61
70
|
def +(other)
|
62
71
|
case other
|
63
|
-
when Interval then
|
64
|
-
when Integer then
|
65
|
-
when PitchClass then
|
66
|
-
when Frequency then
|
72
|
+
when Interval then self.class[integer + other.semitones]
|
73
|
+
when Integer then self.class[integer + other]
|
74
|
+
when PitchClass then self.class[integer + other.integer]
|
75
|
+
when Frequency then self.class.new(frequency: frequency + other)
|
67
76
|
end
|
68
77
|
end
|
69
78
|
|
70
79
|
def -(other)
|
71
80
|
case other
|
72
|
-
when Interval then
|
73
|
-
when Integer then
|
81
|
+
when Interval then self.class[integer - other.semitones]
|
82
|
+
when Integer then self.class[integer - other]
|
74
83
|
when PitchClass then IntervalClass[frequency / other.frequency]
|
75
|
-
when Frequency then
|
84
|
+
when Frequency then self.class.new(frequency: frequency - other)
|
76
85
|
end
|
77
86
|
end
|
78
87
|
|
88
|
+
def <=>(other)
|
89
|
+
integer <=> other.integer
|
90
|
+
end
|
91
|
+
|
79
92
|
def fundamental_frequency
|
80
93
|
@fundamental_frequency ||=
|
81
94
|
Frequency[
|
data/lib/coltrane/progression.rb
CHANGED
@@ -13,7 +13,7 @@ module Coltrane
|
|
13
13
|
|
14
14
|
root_notes = NoteSet[*chords.map(&:root_note)]
|
15
15
|
|
16
|
-
scales = Scale.having_notes(*root_notes)
|
16
|
+
scales = Scale.having_notes(*root_notes)[:scales]
|
17
17
|
progressions = scales.reduce([]) do |memo, scale|
|
18
18
|
memo + [Progression.new(chords: chords, scale: scale)]
|
19
19
|
end
|
@@ -29,7 +29,7 @@ module Coltrane
|
|
29
29
|
'[notation:, [scale: || key:]] '\
|
30
30
|
end
|
31
31
|
|
32
|
-
@scale = scale ||
|
32
|
+
@scale = scale || Key[key]
|
33
33
|
@chords =
|
34
34
|
if !chords.nil?
|
35
35
|
chords
|
@@ -0,0 +1,257 @@
|
|
1
|
+
module Qualities
|
2
|
+
QUALITIES = {
|
3
|
+
"Perfect Unison" => {
|
4
|
+
"Minor Third" => {
|
5
|
+
"Diminished Fifth" => {
|
6
|
+
"name" => "dim",
|
7
|
+
"Diminished Seventh" => {
|
8
|
+
"name" => "dim7",
|
9
|
+
"Minor Ninth" => {
|
10
|
+
"name" => "dim9"
|
11
|
+
},
|
12
|
+
"Major Ninth" => {
|
13
|
+
"name" => "dim(b9)"
|
14
|
+
}
|
15
|
+
},
|
16
|
+
"Minor Seventh" => {
|
17
|
+
"name" => "m7b5",
|
18
|
+
"Minor Ninth" => {
|
19
|
+
"name" => "m7b5b9",
|
20
|
+
"Perfect Eleventh" => {
|
21
|
+
"name" => "m7b5b11",
|
22
|
+
"Major Thirteenth" => {
|
23
|
+
"name" => "m7b5b13"
|
24
|
+
}
|
25
|
+
}
|
26
|
+
},
|
27
|
+
"Major Ninth" => {
|
28
|
+
"name" => "m7b5(9)"
|
29
|
+
}
|
30
|
+
}
|
31
|
+
},
|
32
|
+
"Perfect Fifth" => {
|
33
|
+
"name" => "m",
|
34
|
+
"Major Sixth" => {
|
35
|
+
"name" => "m6"
|
36
|
+
},
|
37
|
+
"Minor Seventh" => {
|
38
|
+
"name" => "m7",
|
39
|
+
"Minor Ninth" => {
|
40
|
+
"name" => "m9",
|
41
|
+
"Perfect Eleventh" => {
|
42
|
+
"name" => "m11"
|
43
|
+
}
|
44
|
+
}
|
45
|
+
},
|
46
|
+
"Major Seventh" => {
|
47
|
+
"name" => "m(M7)",
|
48
|
+
"Major Ninth" => {
|
49
|
+
"name" => "m(M9)",
|
50
|
+
"Perfect Eleventh" => {
|
51
|
+
"name" => "m(M11)",
|
52
|
+
"Major Thirteenth" => {
|
53
|
+
"name" => "m(M13)"
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
},
|
60
|
+
"Major Third" => {
|
61
|
+
"Perfect Fifth" => {
|
62
|
+
"name" => "M",
|
63
|
+
"Major Sixth" => {
|
64
|
+
"name" => "M6",
|
65
|
+
"Major Ninth" => {
|
66
|
+
"name" => "6/9",
|
67
|
+
"Perfect Eleventh" => {
|
68
|
+
"name" => "6/9(add11)"
|
69
|
+
}
|
70
|
+
}
|
71
|
+
},
|
72
|
+
"Minor Seventh" => {
|
73
|
+
"name" => "7",
|
74
|
+
"Major Ninth" => {
|
75
|
+
"name" => "9",
|
76
|
+
"Perfect Eleventh" => {
|
77
|
+
"name" => "11",
|
78
|
+
"Major Thirteenth" => {
|
79
|
+
"name" => "13"
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
},
|
84
|
+
"Major Seventh" => {
|
85
|
+
"name" => "M7",
|
86
|
+
"Major Ninth" => {
|
87
|
+
"name" => "M9",
|
88
|
+
"Perfect Eleventh" => {
|
89
|
+
"name" => "M11",
|
90
|
+
"Major Thirteenth" => {
|
91
|
+
"name" => "M13"
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
},
|
97
|
+
"Augmented Fifth" => {
|
98
|
+
"name" => "+",
|
99
|
+
"Minor Seventh" => {
|
100
|
+
"name" => "+7",
|
101
|
+
"Major Ninth" => {
|
102
|
+
"name" => "+9",
|
103
|
+
"Perfect Eleventh" => {
|
104
|
+
"name" => "+11",
|
105
|
+
"Major Thirteenth" => {
|
106
|
+
"name" => "+13"
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
},
|
111
|
+
"Major Seventh" => {
|
112
|
+
"name" => "+M7",
|
113
|
+
"Major Ninth" => {
|
114
|
+
"name" => "+M9",
|
115
|
+
"Perfect Eleventh" => {
|
116
|
+
"name" => "+M11",
|
117
|
+
"Major Thirteenth" => {
|
118
|
+
"name" => "+M13"
|
119
|
+
}
|
120
|
+
}
|
121
|
+
}
|
122
|
+
}
|
123
|
+
}
|
124
|
+
},
|
125
|
+
"Major Second" => {
|
126
|
+
"Perfect Fifth" => {
|
127
|
+
"name" => "Msus2",
|
128
|
+
"Major Sixth" => {
|
129
|
+
"name" => "M6sus2",
|
130
|
+
"Major Ninth" => {
|
131
|
+
"name" => "6/9sus2",
|
132
|
+
"Perfect Eleventh" => {
|
133
|
+
"name" => "6/9(add11)sus2"
|
134
|
+
}
|
135
|
+
}
|
136
|
+
},
|
137
|
+
"Minor Seventh" => {
|
138
|
+
"name" => "7sus2",
|
139
|
+
"Major Ninth" => {
|
140
|
+
"name" => "9sus2",
|
141
|
+
"Perfect Eleventh" => {
|
142
|
+
"name" => "11sus2",
|
143
|
+
"Major Thirteenth" => {
|
144
|
+
"name" => "13sus2"
|
145
|
+
}
|
146
|
+
}
|
147
|
+
}
|
148
|
+
},
|
149
|
+
"Major Seventh" => {
|
150
|
+
"name" => "M7sus2",
|
151
|
+
"Major Ninth" => {
|
152
|
+
"name" => "M9sus2",
|
153
|
+
"Perfect Eleventh" => {
|
154
|
+
"name" => "M11sus2",
|
155
|
+
"Major Thirteenth" => {
|
156
|
+
"name" => "M13sus2"
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
}
|
161
|
+
},
|
162
|
+
"Augmented Fifth" => {
|
163
|
+
"name" => "+sus2",
|
164
|
+
"Minor Seventh" => {
|
165
|
+
"name" => "+7sus2",
|
166
|
+
"Major Ninth" => {
|
167
|
+
"name" => "+9sus2",
|
168
|
+
"Perfect Eleventh" => {
|
169
|
+
"name" => "+11sus2",
|
170
|
+
"Major Thirteenth" => {
|
171
|
+
"name" => "+13sus2"
|
172
|
+
}
|
173
|
+
}
|
174
|
+
}
|
175
|
+
},
|
176
|
+
"Major Seventh" => {
|
177
|
+
"name" => "+M7sus2",
|
178
|
+
"Major Ninth" => {
|
179
|
+
"name" => "+M9sus2",
|
180
|
+
"Perfect Eleventh" => {
|
181
|
+
"name" => "+M11sus2",
|
182
|
+
"Major Thirteenth" => {
|
183
|
+
"name" => "+M13sus2"
|
184
|
+
}
|
185
|
+
}
|
186
|
+
}
|
187
|
+
}
|
188
|
+
}
|
189
|
+
},
|
190
|
+
"Perfect Fourth" => {
|
191
|
+
"Perfect Fifth" => {
|
192
|
+
"name" => "Msus4",
|
193
|
+
"Major Sixth" => {
|
194
|
+
"name" => "M6sus4",
|
195
|
+
"Major Ninth" => {
|
196
|
+
"name" => "6/9sus4",
|
197
|
+
"Perfect Eleventh" => {
|
198
|
+
"name" => "6/9(add11)sus4"
|
199
|
+
}
|
200
|
+
}
|
201
|
+
},
|
202
|
+
"Minor Seventh" => {
|
203
|
+
"name" => "7sus4",
|
204
|
+
"Major Ninth" => {
|
205
|
+
"name" => "9sus4",
|
206
|
+
"Perfect Eleventh" => {
|
207
|
+
"name" => "11sus4",
|
208
|
+
"Major Thirteenth" => {
|
209
|
+
"name" => "13sus4"
|
210
|
+
}
|
211
|
+
}
|
212
|
+
}
|
213
|
+
},
|
214
|
+
"Major Seventh" => {
|
215
|
+
"name" => "M7sus4",
|
216
|
+
"Major Ninth" => {
|
217
|
+
"name" => "M9sus4",
|
218
|
+
"Perfect Eleventh" => {
|
219
|
+
"name" => "M11sus4",
|
220
|
+
"Major Thirteenth" => {
|
221
|
+
"name" => "M13sus4"
|
222
|
+
}
|
223
|
+
}
|
224
|
+
}
|
225
|
+
}
|
226
|
+
},
|
227
|
+
"Augmented Fifth" => {
|
228
|
+
"name" => "+sus4",
|
229
|
+
"Minor Seventh" => {
|
230
|
+
"name" => "+7sus4",
|
231
|
+
"Major Ninth" => {
|
232
|
+
"name" => "+9sus4",
|
233
|
+
"Perfect Eleventh" => {
|
234
|
+
"name" => "+11sus4",
|
235
|
+
"Major Thirteenth" => {
|
236
|
+
"name" => "+13sus4"
|
237
|
+
}
|
238
|
+
}
|
239
|
+
}
|
240
|
+
},
|
241
|
+
"Major Seventh" => {
|
242
|
+
"name" => "+M7sus4",
|
243
|
+
"Major Ninth" => {
|
244
|
+
"name" => "+M9sus4",
|
245
|
+
"Perfect Eleventh" => {
|
246
|
+
"name" => "+M11sus4",
|
247
|
+
"Major Thirteenth" => {
|
248
|
+
"name" => "+M13sus4"
|
249
|
+
}
|
250
|
+
}
|
251
|
+
}
|
252
|
+
}
|
253
|
+
}
|
254
|
+
}
|
255
|
+
}
|
256
|
+
}
|
257
|
+
end
|
data/lib/coltrane/roman_chord.rb
CHANGED
@@ -4,10 +4,7 @@ module Coltrane
|
|
4
4
|
# This class deals with chords in roman notation. Ex: IVº.
|
5
5
|
class RomanChord
|
6
6
|
DIGITS = %w[I II III IV V VI VII].freeze
|
7
|
-
NOTATION_REGEX = /
|
8
|
-
(?<degree>b?[ivIV]*)
|
9
|
-
(?<quality>.*)
|
10
|
-
/x
|
7
|
+
NOTATION_REGEX = /(b?[ivIV]*)(.*)/
|
11
8
|
|
12
9
|
NOTATION_SUBSTITUTIONS = [
|
13
10
|
%w[º dim],
|
@@ -21,7 +18,7 @@ module Coltrane
|
|
21
18
|
'[notation, [scale: || key:]] '\
|
22
19
|
'[chord:, [scale: || key:]] '\
|
23
20
|
end
|
24
|
-
@scale = scale ||
|
21
|
+
@scale = scale || Key[key]
|
25
22
|
if notation
|
26
23
|
@notation = notation
|
27
24
|
elsif chord
|
@@ -31,7 +28,7 @@ module Coltrane
|
|
31
28
|
|
32
29
|
def degree
|
33
30
|
return @scale.degree_of_note(root_note) unless @chord.nil?
|
34
|
-
d = regexed_notation[
|
31
|
+
d = regexed_notation[:degree]
|
35
32
|
@flats = d.count('b')
|
36
33
|
d = d.delete('b')
|
37
34
|
@degree ||= DIGITS.index(d.upcase) + 1
|
@@ -43,7 +40,7 @@ module Coltrane
|
|
43
40
|
end
|
44
41
|
|
45
42
|
def upcase?
|
46
|
-
!!(regexed_notation[
|
43
|
+
!!(regexed_notation[:degree][0].match /[[:upper:]]/)
|
47
44
|
end
|
48
45
|
|
49
46
|
def chord
|
@@ -61,8 +58,8 @@ module Coltrane
|
|
61
58
|
|
62
59
|
def quality_name
|
63
60
|
return @chord.quality.name unless @chord.nil?
|
64
|
-
q = normalize_quality_name(regexed_notation[
|
65
|
-
minor = 'm' if !q.match?
|
61
|
+
q = normalize_quality_name(regexed_notation[:quality])
|
62
|
+
minor = 'm' if (!q.match? /dim|m7b5/) && !upcase?
|
66
63
|
q = [minor, q].join
|
67
64
|
q.empty? ? 'M' : q
|
68
65
|
end
|
@@ -99,7 +96,10 @@ module Coltrane
|
|
99
96
|
private
|
100
97
|
|
101
98
|
def regexed_notation
|
102
|
-
@regexed_notation ||=
|
99
|
+
@regexed_notation ||= begin
|
100
|
+
matchdata = @notation.match(NOTATION_REGEX)
|
101
|
+
{ degree: matchdata[1], quality: matchdata[2] }
|
102
|
+
end
|
103
103
|
end
|
104
104
|
|
105
105
|
def normalize_quality_name(quality_name)
|
data/lib/coltrane/scale.rb
CHANGED
@@ -4,6 +4,10 @@ module Coltrane
|
|
4
4
|
# Musical scale creation and manipulation
|
5
5
|
class Scale
|
6
6
|
extend ClassicScales
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators :notes, :accidentals, :sharps, :flats
|
10
|
+
|
7
11
|
attr_reader :interval_sequence, :tone
|
8
12
|
|
9
13
|
def initialize(*distances, tone: 'C', mode: 1, name: nil, notes: nil)
|
@@ -13,8 +17,10 @@ module Coltrane
|
|
13
17
|
distances = distances.rotate(mode - 1)
|
14
18
|
@interval_sequence = IntervalSequence.new(distances: distances)
|
15
19
|
elsif notes
|
16
|
-
|
17
|
-
|
20
|
+
@notes = NoteSet[*notes]
|
21
|
+
@tone = @notes.first
|
22
|
+
ds = @notes.interval_sequence.distances
|
23
|
+
@interval_sequence = IntervalSequence.new(distances: ds)
|
18
24
|
else
|
19
25
|
raise WrongKeywordsError, '[*distances, tone: "C", mode: 1] || [notes:]'
|
20
26
|
end
|
@@ -79,7 +85,7 @@ module Coltrane
|
|
79
85
|
alias include? include_notes?
|
80
86
|
|
81
87
|
def notes
|
82
|
-
NoteSet[*degrees.map { |d| degree(d) }]
|
88
|
+
@notes ||= NoteSet[*degrees.map { |d| degree(d) }]
|
83
89
|
end
|
84
90
|
|
85
91
|
def interval(i)
|
data/lib/coltrane/version.rb
CHANGED