mtk 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +9 -0
- data/INTRO.md +73 -0
- data/LICENSE.txt +27 -0
- data/README.md +93 -18
- data/Rakefile +13 -1
- data/examples/crescendo.rb +20 -0
- data/examples/dynamic_pattern.rb +39 -0
- data/examples/play_midi.rb +19 -0
- data/examples/print_midi.rb +13 -0
- data/examples/random_tone_row.rb +18 -0
- data/examples/tone_row_melody.rb +21 -0
- data/lib/mtk/_constants/durations.rb +80 -0
- data/lib/mtk/_constants/intensities.rb +81 -0
- data/lib/mtk/{constants → _constants}/intervals.rb +10 -1
- data/lib/mtk/_constants/pitch_classes.rb +35 -0
- data/lib/mtk/_constants/pitches.rb +49 -0
- data/lib/mtk/{numeric_extensions.rb → _numeric_extensions.rb} +0 -0
- data/lib/mtk/event.rb +14 -5
- data/lib/mtk/helper/collection.rb +114 -0
- data/lib/mtk/helper/event_builder.rb +85 -0
- data/lib/mtk/{constants → helper}/pseudo_constants.rb +7 -6
- data/lib/mtk/lang/grammar.rb +17 -0
- data/lib/mtk/lang/mtk_grammar.citrus +60 -0
- data/lib/mtk/midi/file.rb +10 -15
- data/lib/mtk/midi/jsound_input.rb +68 -0
- data/lib/mtk/midi/jsound_output.rb +80 -0
- data/lib/mtk/note.rb +22 -3
- data/lib/mtk/pattern/abstract_pattern.rb +132 -0
- data/lib/mtk/pattern/choice.rb +25 -9
- data/lib/mtk/pattern/cycle.rb +51 -0
- data/lib/mtk/pattern/enumerator.rb +26 -0
- data/lib/mtk/pattern/function.rb +46 -0
- data/lib/mtk/pattern/lines.rb +60 -0
- data/lib/mtk/pattern/palindrome.rb +42 -0
- data/lib/mtk/pattern/sequence.rb +15 -50
- data/lib/mtk/pitch.rb +45 -6
- data/lib/mtk/pitch_class.rb +36 -35
- data/lib/mtk/pitch_class_set.rb +46 -14
- data/lib/mtk/pitch_set.rb +20 -31
- data/lib/mtk/sequencer/abstract_sequencer.rb +85 -0
- data/lib/mtk/sequencer/rhythmic_sequencer.rb +29 -0
- data/lib/mtk/sequencer/step_sequencer.rb +26 -0
- data/lib/mtk/timeline.rb +75 -22
- data/lib/mtk/transform/invertible.rb +15 -0
- data/lib/mtk/{util → transform}/mappable.rb +6 -2
- data/lib/mtk/transform/set_theory_operations.rb +34 -0
- data/lib/mtk/transform/transposable.rb +14 -0
- data/lib/mtk.rb +56 -22
- data/spec/mtk/_constants/durations_spec.rb +118 -0
- data/spec/mtk/{constants/dynamics_spec.rb → _constants/intensities_spec.rb} +48 -17
- data/spec/mtk/{constants → _constants}/intervals_spec.rb +21 -0
- data/spec/mtk/_constants/pitch_classes_spec.rb +58 -0
- data/spec/mtk/_constants/pitches_spec.rb +52 -0
- data/spec/mtk/{numeric_extensions_spec.rb → _numeric_extensions_spec.rb} +0 -0
- data/spec/mtk/event_spec.rb +19 -0
- data/spec/mtk/helper/collection_spec.rb +291 -0
- data/spec/mtk/helper/event_builder_spec.rb +92 -0
- data/spec/mtk/helper/pseudo_constants_spec.rb +20 -0
- data/spec/mtk/lang/grammar_spec.rb +100 -0
- data/spec/mtk/midi/file_spec.rb +41 -6
- data/spec/mtk/note_spec.rb +53 -3
- data/spec/mtk/pattern/abstract_pattern_spec.rb +45 -0
- data/spec/mtk/pattern/choice_spec.rb +89 -3
- data/spec/mtk/pattern/cycle_spec.rb +133 -0
- data/spec/mtk/pattern/function_spec.rb +133 -0
- data/spec/mtk/pattern/lines_spec.rb +93 -0
- data/spec/mtk/pattern/note_cycle_spec.rb.bak +116 -0
- data/spec/mtk/pattern/palindrome_spec.rb +124 -0
- data/spec/mtk/pattern/pitch_cycle_spec.rb.bak +47 -0
- data/spec/mtk/pattern/pitch_sequence_spec.rb.bak +37 -0
- data/spec/mtk/pattern/sequence_spec.rb +128 -31
- data/spec/mtk/pitch_class_set_spec.rb +240 -7
- data/spec/mtk/pitch_class_spec.rb +84 -18
- data/spec/mtk/pitch_set_spec.rb +45 -10
- data/spec/mtk/pitch_spec.rb +59 -0
- data/spec/mtk/sequencer/abstract_sequencer_spec.rb +159 -0
- data/spec/mtk/sequencer/rhythmic_sequencer_spec.rb +49 -0
- data/spec/mtk/sequencer/step_sequencer_spec.rb +71 -0
- data/spec/mtk/timeline_spec.rb +118 -15
- data/spec/spec_helper.rb +4 -3
- metadata +59 -22
- data/lib/mtk/chord.rb +0 -47
- data/lib/mtk/constants/dynamics.rb +0 -56
- data/lib/mtk/constants/pitch_classes.rb +0 -18
- data/lib/mtk/constants/pitches.rb +0 -24
- data/lib/mtk/pattern/note_sequence.rb +0 -60
- data/lib/mtk/pattern/pitch_sequence.rb +0 -22
- data/lib/mtk/patterns.rb +0 -4
- data/spec/mtk/chord_spec.rb +0 -74
- data/spec/mtk/constants/pitch_classes_spec.rb +0 -35
- data/spec/mtk/constants/pitches_spec.rb +0 -23
- data/spec/mtk/pattern/note_sequence_spec.rb +0 -121
- data/spec/mtk/pattern/pitch_sequence_spec.rb +0 -47
data/spec/mtk/timeline_spec.rb
CHANGED
@@ -8,6 +8,15 @@ describe MTK::Timeline do
|
|
8
8
|
let(:timeline_hash) { { 0 => [note1], 1 => [note1, note2] } }
|
9
9
|
let(:timeline) { Timeline.from_hash(timeline_raw_data) }
|
10
10
|
|
11
|
+
let(:unquantized_data) { { 0.0 => [note1], 0.7 => [note1], 1.24 => [note1], 1.25 => [note1] } }
|
12
|
+
let(:unquantized_timeline) { Timeline.from_hash(unquantized_data) }
|
13
|
+
let(:quantization_interval) { 0.5 }
|
14
|
+
let(:quantized_data) { { 0.0 => [note1], 0.5 => [note1], 1.0 => [note1], 1.5 => [note1] } }
|
15
|
+
|
16
|
+
let(:shifted_data) { { 5 => [note1], 6 => [note1, note2] } }
|
17
|
+
let(:reverse_shifted_data) { { -5 => [note1], -4 => [note1, note2] } }
|
18
|
+
let(:shift_amount) { 5 }
|
19
|
+
|
11
20
|
it "is Enumerable" do
|
12
21
|
Timeline.new.should be_a Enumerable
|
13
22
|
end
|
@@ -35,7 +44,9 @@ describe MTK::Timeline do
|
|
35
44
|
end
|
36
45
|
|
37
46
|
describe "from_a" do
|
38
|
-
it "creates a timeline from an Enumerable"
|
47
|
+
it "creates a timeline from an Enumerable" do
|
48
|
+
Timeline.from_a(timeline_hash.to_a).should == timeline
|
49
|
+
end
|
39
50
|
end
|
40
51
|
|
41
52
|
describe "#to_hash" do
|
@@ -51,7 +62,9 @@ describe MTK::Timeline do
|
|
51
62
|
end
|
52
63
|
|
53
64
|
describe "#merge" do
|
54
|
-
it "merges all the time,event pairs in the given Enumerable into this Timeline"
|
65
|
+
it "merges all the time,event pairs in the given Enumerable into this Timeline" do
|
66
|
+
timeline.merge({ 3 => note2 }).should == Timeline.from_hash( timeline_raw_data.merge({ 3 => note2 }) )
|
67
|
+
end
|
55
68
|
end
|
56
69
|
|
57
70
|
describe "#empty?" do
|
@@ -98,7 +111,10 @@ describe MTK::Timeline do
|
|
98
111
|
timeline[5].should == [note1, note2]
|
99
112
|
end
|
100
113
|
|
101
|
-
it "accepts
|
114
|
+
it "accepts a list of events as its second argument" do
|
115
|
+
timeline.add 5, [note1, note2]
|
116
|
+
timeline[5].should == [note1, note2]
|
117
|
+
end
|
102
118
|
end
|
103
119
|
|
104
120
|
describe "#delete" do
|
@@ -142,24 +158,16 @@ describe MTK::Timeline do
|
|
142
158
|
end
|
143
159
|
|
144
160
|
describe "#each" do
|
145
|
-
it "yields each |time,single_event| pair" do
|
146
|
-
yielded = []
|
147
|
-
timeline.each{|t,e| yielded << [t,e] }
|
148
|
-
yielded.should == [ [0,note1], [1,note1], [1,note2] ]
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
describe "#each_time" do
|
153
161
|
it "yields each |time,event_list| pair" do
|
154
162
|
yielded = []
|
155
|
-
timeline.
|
163
|
+
timeline.each{|time,events| yielded << [time,events] }
|
156
164
|
yielded.should == [ [0,[note1]], [1,[note1,note2]] ]
|
157
165
|
end
|
158
166
|
end
|
159
167
|
|
160
168
|
describe "#map" do
|
161
169
|
it "returns a new Timeline where each [time,event] pair is replaced by the result of block" do
|
162
|
-
mapped = timeline.map{|time,
|
170
|
+
mapped = timeline.map{|time,events| [time+1, events.map{|e| e.transpose(time+2) }] }
|
163
171
|
mapped.should == { 1 => [note1.transpose(2)], 2 => [note1.transpose(3), note2.transpose(3)] }
|
164
172
|
end
|
165
173
|
|
@@ -171,7 +179,7 @@ describe MTK::Timeline do
|
|
171
179
|
|
172
180
|
describe "#map!" do
|
173
181
|
it "maps the Timeline in place" do
|
174
|
-
timeline.map! {|time,
|
182
|
+
timeline.map! {|time,events| [time+1, events.map{|e| e.transpose(time+2) }] }
|
175
183
|
timeline.should == { 1 => [note1.transpose(2)], 2 => [note1.transpose(3), note2.transpose(3)] }
|
176
184
|
end
|
177
185
|
end
|
@@ -203,7 +211,86 @@ describe MTK::Timeline do
|
|
203
211
|
timeline.should == timeline_hash
|
204
212
|
end
|
205
213
|
end
|
206
|
-
|
214
|
+
|
215
|
+
describe "#quantize" do
|
216
|
+
it "maps all times to the nearest multiple of the given interval" do
|
217
|
+
unquantized_timeline.quantize(quantization_interval).should == quantized_data
|
218
|
+
end
|
219
|
+
it "returns a new Timeline and does not modify the original" do
|
220
|
+
unquantized_timeline.quantize(quantization_interval)
|
221
|
+
unquantized_timeline.should == unquantized_data
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe "#quantize!" do
|
226
|
+
it "maps all times to the nearest multiple of the given interval" do
|
227
|
+
unquantized_timeline.quantize!(quantization_interval).should == quantized_data
|
228
|
+
end
|
229
|
+
|
230
|
+
it "modifies the Timeline in place" do
|
231
|
+
unquantized_timeline.quantize!(quantization_interval)
|
232
|
+
unquantized_timeline.should == quantized_data
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe "#shift" do
|
237
|
+
it "shifts all times by the given amount" do
|
238
|
+
timeline.shift(shift_amount).should == shifted_data
|
239
|
+
end
|
240
|
+
|
241
|
+
it "goes back in time for negative arguments" do
|
242
|
+
timeline.shift(-shift_amount).should == reverse_shifted_data
|
243
|
+
end
|
244
|
+
|
245
|
+
it "returns an instance of the same type" do
|
246
|
+
timeline.shift(shift_amount).should be_a timeline.class
|
247
|
+
end
|
248
|
+
|
249
|
+
it "returns a new Timeline and does not modify the original" do
|
250
|
+
timeline.shift(shift_amount).should_not equal timeline
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
describe "#shift!" do
|
255
|
+
it "shifts all times by the given amount" do
|
256
|
+
timeline.shift!(shift_amount).should == shifted_data
|
257
|
+
end
|
258
|
+
|
259
|
+
it "goes back in time for negative arguments" do
|
260
|
+
timeline.shift!(-shift_amount).should == reverse_shifted_data
|
261
|
+
end
|
262
|
+
|
263
|
+
it "modifies the timeline in place" do
|
264
|
+
timeline.shift!(shift_amount).should equal timeline
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
describe "#shift_to" do
|
269
|
+
it "shifts so the start is at the given time" do
|
270
|
+
Timeline.from_hash(shifted_data).shift_to(0).should == timeline
|
271
|
+
Timeline.from_hash(reverse_shifted_data).shift_to(0).should == timeline
|
272
|
+
end
|
273
|
+
|
274
|
+
it "returns an instance of the same type" do
|
275
|
+
timeline.shift_to(shift_amount).should be_a timeline.class
|
276
|
+
end
|
277
|
+
|
278
|
+
it "returns a new Timeline and does not modify the original" do
|
279
|
+
timeline.shift_to(shift_amount).should_not equal timeline
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
describe "#shift_to!" do
|
284
|
+
it "shifts so the start is at the given time" do
|
285
|
+
Timeline.from_hash(shifted_data).shift_to!(0).should == timeline
|
286
|
+
Timeline.from_hash(reverse_shifted_data).shift_to!(0).should == timeline
|
287
|
+
end
|
288
|
+
|
289
|
+
it "modifies the timeline in place" do
|
290
|
+
timeline.shift_to!(shift_amount).should equal timeline
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
207
294
|
describe "#flatten" do
|
208
295
|
it "flattens nested timelines so that all nested subtimes are converted to absolute times in a single timeline" do
|
209
296
|
timeline[10] = Timeline.from_hash({ 0 => note2, 1 => note1 })
|
@@ -230,5 +317,21 @@ describe MTK::Timeline do
|
|
230
317
|
timeline.clone.should_not equal(timeline)
|
231
318
|
end
|
232
319
|
end
|
320
|
+
|
321
|
+
describe ".quantize_time" do
|
322
|
+
it "takes a time and an interval, and returns the nearest multiple of the interval to the time" do
|
323
|
+
Timeline.quantize_time(23,10).should == 20
|
324
|
+
Timeline.quantize_time(27,10).should == 30
|
325
|
+
Timeline.quantize_time(30,10).should == 30
|
326
|
+
end
|
327
|
+
|
328
|
+
it "rounds up when exactly between 2 intervals" do
|
329
|
+
Timeline.quantize_time(25,10).should == 30
|
330
|
+
end
|
331
|
+
|
332
|
+
it "handles fractional intervals" do
|
333
|
+
Timeline.quantize_time(13,2.5).should == 12.5
|
334
|
+
end
|
335
|
+
end
|
233
336
|
end
|
234
337
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: mtk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Adam Murray
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-07-09 00:00:00 Z
|
14
14
|
dependencies: []
|
15
15
|
|
16
16
|
description:
|
@@ -23,49 +23,86 @@ extra_rdoc_files: []
|
|
23
23
|
|
24
24
|
files:
|
25
25
|
- Rakefile
|
26
|
+
- INTRO.md
|
26
27
|
- README.md
|
27
|
-
-
|
28
|
-
-
|
29
|
-
- lib/mtk/
|
30
|
-
- lib/mtk/
|
31
|
-
- lib/mtk/
|
32
|
-
- lib/mtk/
|
28
|
+
- LICENSE.txt
|
29
|
+
- .yardopts
|
30
|
+
- lib/mtk/_constants/durations.rb
|
31
|
+
- lib/mtk/_constants/intensities.rb
|
32
|
+
- lib/mtk/_constants/intervals.rb
|
33
|
+
- lib/mtk/_constants/pitch_classes.rb
|
34
|
+
- lib/mtk/_constants/pitches.rb
|
35
|
+
- lib/mtk/_numeric_extensions.rb
|
33
36
|
- lib/mtk/event.rb
|
37
|
+
- lib/mtk/helper/collection.rb
|
38
|
+
- lib/mtk/helper/event_builder.rb
|
39
|
+
- lib/mtk/helper/pseudo_constants.rb
|
40
|
+
- lib/mtk/lang/grammar.rb
|
41
|
+
- lib/mtk/lang/mtk_grammar.citrus
|
34
42
|
- lib/mtk/midi/file.rb
|
43
|
+
- lib/mtk/midi/jsound_input.rb
|
44
|
+
- lib/mtk/midi/jsound_output.rb
|
35
45
|
- lib/mtk/note.rb
|
36
|
-
- lib/mtk/
|
46
|
+
- lib/mtk/pattern/abstract_pattern.rb
|
37
47
|
- lib/mtk/pattern/choice.rb
|
38
|
-
- lib/mtk/pattern/
|
39
|
-
- lib/mtk/pattern/
|
48
|
+
- lib/mtk/pattern/cycle.rb
|
49
|
+
- lib/mtk/pattern/enumerator.rb
|
50
|
+
- lib/mtk/pattern/function.rb
|
51
|
+
- lib/mtk/pattern/lines.rb
|
52
|
+
- lib/mtk/pattern/palindrome.rb
|
40
53
|
- lib/mtk/pattern/sequence.rb
|
41
|
-
- lib/mtk/patterns.rb
|
42
54
|
- lib/mtk/pitch.rb
|
43
55
|
- lib/mtk/pitch_class.rb
|
44
56
|
- lib/mtk/pitch_class_set.rb
|
45
57
|
- lib/mtk/pitch_set.rb
|
58
|
+
- lib/mtk/sequencer/abstract_sequencer.rb
|
59
|
+
- lib/mtk/sequencer/rhythmic_sequencer.rb
|
60
|
+
- lib/mtk/sequencer/step_sequencer.rb
|
46
61
|
- lib/mtk/timeline.rb
|
47
|
-
- lib/mtk/
|
62
|
+
- lib/mtk/transform/invertible.rb
|
63
|
+
- lib/mtk/transform/mappable.rb
|
64
|
+
- lib/mtk/transform/set_theory_operations.rb
|
65
|
+
- lib/mtk/transform/transposable.rb
|
48
66
|
- lib/mtk.rb
|
49
|
-
- spec/mtk/
|
50
|
-
- spec/mtk/
|
51
|
-
- spec/mtk/
|
52
|
-
- spec/mtk/
|
53
|
-
- spec/mtk/
|
67
|
+
- spec/mtk/_constants/durations_spec.rb
|
68
|
+
- spec/mtk/_constants/intensities_spec.rb
|
69
|
+
- spec/mtk/_constants/intervals_spec.rb
|
70
|
+
- spec/mtk/_constants/pitch_classes_spec.rb
|
71
|
+
- spec/mtk/_constants/pitches_spec.rb
|
72
|
+
- spec/mtk/_numeric_extensions_spec.rb
|
54
73
|
- spec/mtk/event_spec.rb
|
74
|
+
- spec/mtk/helper/collection_spec.rb
|
75
|
+
- spec/mtk/helper/event_builder_spec.rb
|
76
|
+
- spec/mtk/helper/pseudo_constants_spec.rb
|
77
|
+
- spec/mtk/lang/grammar_spec.rb
|
55
78
|
- spec/mtk/midi/file_spec.rb
|
56
79
|
- spec/mtk/note_spec.rb
|
57
|
-
- spec/mtk/
|
80
|
+
- spec/mtk/pattern/abstract_pattern_spec.rb
|
58
81
|
- spec/mtk/pattern/choice_spec.rb
|
59
|
-
- spec/mtk/pattern/
|
60
|
-
- spec/mtk/pattern/
|
82
|
+
- spec/mtk/pattern/cycle_spec.rb
|
83
|
+
- spec/mtk/pattern/function_spec.rb
|
84
|
+
- spec/mtk/pattern/lines_spec.rb
|
85
|
+
- spec/mtk/pattern/note_cycle_spec.rb.bak
|
86
|
+
- spec/mtk/pattern/palindrome_spec.rb
|
87
|
+
- spec/mtk/pattern/pitch_cycle_spec.rb.bak
|
88
|
+
- spec/mtk/pattern/pitch_sequence_spec.rb.bak
|
61
89
|
- spec/mtk/pattern/sequence_spec.rb
|
62
90
|
- spec/mtk/pitch_class_set_spec.rb
|
63
91
|
- spec/mtk/pitch_class_spec.rb
|
64
92
|
- spec/mtk/pitch_set_spec.rb
|
65
93
|
- spec/mtk/pitch_spec.rb
|
94
|
+
- spec/mtk/sequencer/abstract_sequencer_spec.rb
|
95
|
+
- spec/mtk/sequencer/rhythmic_sequencer_spec.rb
|
96
|
+
- spec/mtk/sequencer/step_sequencer_spec.rb
|
66
97
|
- spec/mtk/timeline_spec.rb
|
67
98
|
- spec/spec_helper.rb
|
68
99
|
- spec/test.mid
|
100
|
+
- examples/crescendo.rb
|
101
|
+
- examples/dynamic_pattern.rb
|
102
|
+
- examples/play_midi.rb
|
103
|
+
- examples/print_midi.rb
|
104
|
+
- examples/random_tone_row.rb
|
105
|
+
- examples/tone_row_melody.rb
|
69
106
|
homepage: http://github.com/adamjmurray/mtk
|
70
107
|
licenses: []
|
71
108
|
|
@@ -92,6 +129,6 @@ rubyforge_project:
|
|
92
129
|
rubygems_version: 1.8.5
|
93
130
|
signing_key:
|
94
131
|
specification_version: 3
|
95
|
-
summary:
|
132
|
+
summary: Music ToolKit for Ruby
|
96
133
|
test_files: []
|
97
134
|
|
data/lib/mtk/chord.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
module MTK
|
2
|
-
|
3
|
-
# A multi-pitch, note-like {Event} defined by a {PitchSet}, intensity, and duration
|
4
|
-
class Chord < Event
|
5
|
-
|
6
|
-
# the {PitchSet} of the chord
|
7
|
-
attr_reader :pitch_set
|
8
|
-
|
9
|
-
def initialize(pitches, intensity, duration)
|
10
|
-
@pitch_set = if pitches.is_a? PitchSet
|
11
|
-
pitches
|
12
|
-
else
|
13
|
-
PitchSet.new(pitches)
|
14
|
-
end
|
15
|
-
super(intensity, duration)
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.from_hash(hash)
|
19
|
-
new hash[:pitch_set], hash[:intensity], hash[:duration]
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_hash
|
23
|
-
super.merge({ :pitch_set => @pitch_set })
|
24
|
-
end
|
25
|
-
|
26
|
-
def pitches
|
27
|
-
@pitch_set.pitches
|
28
|
-
end
|
29
|
-
|
30
|
-
def transpose(interval)
|
31
|
-
self.class.new(@pitch_set + interval, @intensity, @duration)
|
32
|
-
end
|
33
|
-
|
34
|
-
def == other
|
35
|
-
super and other.respond_to? :pitch_set and @pitch_set == other.pitch_set
|
36
|
-
end
|
37
|
-
|
38
|
-
def to_s
|
39
|
-
"Chord(#{pitch_set}, #{super})"
|
40
|
-
end
|
41
|
-
|
42
|
-
def inspect
|
43
|
-
"Chord(#{pitch_set}, #{super})"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
module MTK
|
2
|
-
|
3
|
-
# Defines values for standard dynamic symbols.
|
4
|
-
#
|
5
|
-
# These can be thought of like constants, but in order to distinguish 'f' (forte) from the {PitchClass} 'F'
|
6
|
-
# it was necessary to use lower-case names and therefore define them as "pseudo constant" methods.
|
7
|
-
# The methods are available either throught the module (MTK::Dynamics::f) or via mixin (include MTK::Dynamics; f)
|
8
|
-
#
|
9
|
-
# These values are intensities in the range 0.0 - 1.0, so they can be easily scaled (unlike MIDI velocities).
|
10
|
-
#
|
11
|
-
# @note Including this module shadows Ruby's built-in p() method.
|
12
|
-
# If you include this module, you can access the built-in p() method via Kernel.p()
|
13
|
-
#
|
14
|
-
# @see Note
|
15
|
-
module Dynamics
|
16
|
-
extend MTK::PseudoConstants
|
17
|
-
|
18
|
-
# NOTE: the yard doc macros here only fill in [$2] with the actual value when generating docs under Ruby 1.9+
|
19
|
-
|
20
|
-
# pianississimo
|
21
|
-
# @macro [attach] dynamics.define_constant
|
22
|
-
# @attribute [r]
|
23
|
-
# @return [$2] intensity value for $1
|
24
|
-
define_constant 'ppp', 0.125
|
25
|
-
|
26
|
-
# pianissimo
|
27
|
-
define_constant 'pp', 0.25
|
28
|
-
|
29
|
-
# piano
|
30
|
-
# @note Including this module shadows Ruby's built-in p() method.
|
31
|
-
# If you include this module, you can access the built-in p() method via Kernel.p()
|
32
|
-
define_constant 'p', 0.375
|
33
|
-
|
34
|
-
# mezzo-piano
|
35
|
-
define_constant 'mp', 0.5
|
36
|
-
|
37
|
-
# mezzo-forte
|
38
|
-
define_constant 'mf', 0.625
|
39
|
-
|
40
|
-
# forte
|
41
|
-
define_constant 'f', 0.75
|
42
|
-
|
43
|
-
# fortissimo
|
44
|
-
define_constant 'ff', 0.875
|
45
|
-
|
46
|
-
# fortississimo
|
47
|
-
define_constant 'fff', 1.0
|
48
|
-
|
49
|
-
def self.[](name)
|
50
|
-
send name
|
51
|
-
rescue
|
52
|
-
nil
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module MTK
|
2
|
-
|
3
|
-
# Defines a constant for each {PitchClass} in the Western chromatic scale.
|
4
|
-
|
5
|
-
module PitchClasses
|
6
|
-
|
7
|
-
# An array of all pitch class constants defined in this module
|
8
|
-
PITCH_CLASSES = []
|
9
|
-
|
10
|
-
for name in PitchClass::NAMES
|
11
|
-
pc = PitchClass.from_name name
|
12
|
-
PITCH_CLASSES << pc
|
13
|
-
const_set name, pc
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module MTK
|
2
|
-
|
3
|
-
# Defines a constants for each {Pitch} in the standard MIDI range using scientific pitch notation.
|
4
|
-
#
|
5
|
-
# See http://en.wikipedia.org/wiki/Scientific_pitch_notation
|
6
|
-
#
|
7
|
-
# Note that because the character '#' cannot be used in the name of a constant,
|
8
|
-
# The "black key" pitches are all named as flats with 'b' (for example, Gb3 or Cb4)
|
9
|
-
|
10
|
-
module Pitches
|
11
|
-
|
12
|
-
# An array of all the pitch constants defined in this module
|
13
|
-
PITCHES = []
|
14
|
-
|
15
|
-
128.times do |note_number|
|
16
|
-
pitch = Pitch.from_i( note_number )
|
17
|
-
PITCHES << pitch
|
18
|
-
octave_str = pitch.octave.to_s.sub(/-/,'_') # '_1' for -1
|
19
|
-
const_set "#{pitch.pitch_class}#{octave_str}", pitch
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
@@ -1,60 +0,0 @@
|
|
1
|
-
module MTK
|
2
|
-
module Pattern
|
3
|
-
|
4
|
-
# A {Sequence} of {Note}s
|
5
|
-
class NoteSequence
|
6
|
-
|
7
|
-
attr_reader :pitch_sequence, :intensity_sequence, :duration_sequence
|
8
|
-
|
9
|
-
attr_accessor :pitch, :intensity, :duration
|
10
|
-
|
11
|
-
def initialize(pitches, intensities=nil, durations=nil, defaults={})
|
12
|
-
@pitch_sequence = PitchSequence.new(pitches)
|
13
|
-
@intensity_sequence = Sequence.new(intensities)
|
14
|
-
@duration_sequence = Sequence.new(durations)
|
15
|
-
@default = {:pitch => Pitches::C4, :intensity => Dynamics::mf, :duration => 1}.merge defaults
|
16
|
-
reset
|
17
|
-
end
|
18
|
-
|
19
|
-
def pitches
|
20
|
-
@pitch_sequence.elements
|
21
|
-
end
|
22
|
-
|
23
|
-
def intensities
|
24
|
-
@intensity_sequence.elements
|
25
|
-
end
|
26
|
-
|
27
|
-
def durations
|
28
|
-
@duration_sequence.elements
|
29
|
-
end
|
30
|
-
|
31
|
-
# reset the Sequence to the beginning
|
32
|
-
def reset
|
33
|
-
@pitch_sequence.reset
|
34
|
-
@intensity_sequence.reset
|
35
|
-
@duration_sequence.reset
|
36
|
-
|
37
|
-
@pitch = @default[:pitch]
|
38
|
-
@intensity = @default[:intensity]
|
39
|
-
@duration = @default[:duration]
|
40
|
-
end
|
41
|
-
|
42
|
-
# return next {Note} in sequence
|
43
|
-
def next
|
44
|
-
@pitch = @pitch_sequence.next || @pitch
|
45
|
-
@intensity = @intensity_sequence.next || @intensity
|
46
|
-
@duration = @duration_sequence.next || @duration
|
47
|
-
|
48
|
-
|
49
|
-
case @pitch
|
50
|
-
when PitchSet,Array then Chord.new(@pitch, @intensity, @duration)
|
51
|
-
else Note.new(@pitch, @intensity, @duration)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module MTK
|
2
|
-
module Pattern
|
3
|
-
|
4
|
-
# A {Sequence} of pitch-related elements, which may be {Pitch}es, {PitchClass}es, {PitchSet}s, or {Intervals} (Numeric)
|
5
|
-
class PitchSequence < Sequence
|
6
|
-
|
7
|
-
protected
|
8
|
-
|
9
|
-
# extend value_of to handle intervals and PitchClasses
|
10
|
-
def value_of element
|
11
|
-
element = super # eval Procs
|
12
|
-
case element
|
13
|
-
when Numeric then @value + element if @value # add interval
|
14
|
-
when PitchClass then @value.nearest(element) if @value
|
15
|
-
else element
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
end
|
data/lib/mtk/patterns.rb
DELETED
data/spec/mtk/chord_spec.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe MTK::Chord do
|
4
|
-
|
5
|
-
let(:pitch_set) { PitchSet.new [C4, E4, G4] }
|
6
|
-
let(:intensity) { mf }
|
7
|
-
let(:duration) { 2.5 }
|
8
|
-
let(:chord) { Chord.new(pitch_set, intensity, duration) }
|
9
|
-
|
10
|
-
it "can be constructed with a PitchSet" do
|
11
|
-
pitch_set = PitchSet.new([C4])
|
12
|
-
Chord.new( pitch_set, intensity, duration ).pitch_set.should == pitch_set
|
13
|
-
end
|
14
|
-
|
15
|
-
it "can be constructed with an Array of Pitches" do
|
16
|
-
Chord.new( [C4], intensity, duration ).pitch_set.should == PitchSet.new([C4])
|
17
|
-
end
|
18
|
-
|
19
|
-
describe "#pitch_set" do
|
20
|
-
it "is the pitch_set used to create the Chord" do
|
21
|
-
chord.pitch_set.should == pitch_set
|
22
|
-
end
|
23
|
-
|
24
|
-
it "is a read-only attribute" do
|
25
|
-
lambda{ chord.pitch_set = PitchSet.new }.should raise_error
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "#pitches" do
|
30
|
-
it "is the list of pitches in the pitch_set" do
|
31
|
-
chord.pitches.should == chord.pitch_set.pitches
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
describe "from_hash" do
|
36
|
-
it "constructs a Chord using a hash" do
|
37
|
-
Chord.from_hash({ :pitch_set => pitch_set, :intensity => intensity, :duration => duration }).should == chord
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe "#to_hash" do
|
42
|
-
it "is a hash containing all the attributes of the Chord" do
|
43
|
-
chord.to_hash.should == { :pitch_set => pitch_set, :intensity => intensity, :duration => duration }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe '#transpose' do
|
48
|
-
it 'adds the given interval to the @pitch_set' do
|
49
|
-
(chord.transpose 2.semitones).should == Chord.new(pitch_set+2, intensity, duration)
|
50
|
-
end
|
51
|
-
it 'does not affect the immutability of the Chord' do
|
52
|
-
(chord.transpose 2.semitones).should_not == chord
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
describe "#==" do
|
57
|
-
it "is true when the pitch_sets, intensities, and durations are equal" do
|
58
|
-
chord.should == Chord.new(pitch_set, intensity, duration)
|
59
|
-
end
|
60
|
-
|
61
|
-
it "is false when the pitch_sets are not equal" do
|
62
|
-
chord.should_not == Chord.new(pitch_set + 1, intensity, duration)
|
63
|
-
end
|
64
|
-
|
65
|
-
it "is false when the intensities are not equal" do
|
66
|
-
chord.should_not == Chord.new(pitch_set, intensity * 0.5, duration)
|
67
|
-
end
|
68
|
-
|
69
|
-
it "is false when the durations are not equal" do
|
70
|
-
chord.should_not == Chord.new(pitch_set, intensity, duration * 2)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe MTK::PitchClasses do
|
4
|
-
let(:cases) {
|
5
|
-
[
|
6
|
-
[PitchClasses::C, 'C', 0],
|
7
|
-
[PitchClasses::Db, 'Db', 1],
|
8
|
-
[PitchClasses::D, 'D', 2],
|
9
|
-
[PitchClasses::Eb, 'Eb', 3],
|
10
|
-
[PitchClasses::E, 'E', 4],
|
11
|
-
[PitchClasses::F, 'F', 5],
|
12
|
-
[PitchClasses::Gb, 'Gb', 6],
|
13
|
-
[PitchClasses::G, 'G', 7],
|
14
|
-
[PitchClasses::Ab, 'Ab', 8],
|
15
|
-
[PitchClasses::A, 'A', 9],
|
16
|
-
[PitchClasses::Bb, 'Bb', 10],
|
17
|
-
[PitchClasses::B, 'B', 11],
|
18
|
-
]
|
19
|
-
}
|
20
|
-
|
21
|
-
it "defines constants for the 12 pitch classes in the twelve-tone octave" do
|
22
|
-
cases.length.should == 12
|
23
|
-
cases.each do |const, name, int_value|
|
24
|
-
const.name.should == name
|
25
|
-
const.to_i.should == int_value
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "PITCH_CLASSES" do
|
30
|
-
it "contains the 12 pitch class constants" do
|
31
|
-
PitchClasses::PITCH_CLASSES.length.should == 12
|
32
|
-
PitchClasses::PITCH_CLASSES.should == cases.map{ |const,_,__| const }
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|