jmtk 0.0.3.3-java → 0.4-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +15 -0
  2. data/DEVELOPMENT_NOTES.md +20 -0
  3. data/INTRO.md +63 -31
  4. data/README.md +9 -3
  5. data/Rakefile +42 -42
  6. data/bin/jmtk +75 -32
  7. data/bin/mtk +75 -32
  8. data/examples/drum_pattern.rb +2 -2
  9. data/examples/dynamic_pattern.rb +1 -1
  10. data/examples/helpers/output_selector.rb +71 -0
  11. data/examples/notation.rb +5 -1
  12. data/examples/tone_row_melody.rb +1 -1
  13. data/lib/mtk.rb +1 -0
  14. data/lib/mtk/core/duration.rb +18 -3
  15. data/lib/mtk/core/intensity.rb +5 -3
  16. data/lib/mtk/core/interval.rb +21 -14
  17. data/lib/mtk/core/pitch.rb +2 -0
  18. data/lib/mtk/core/pitch_class.rb +6 -3
  19. data/lib/mtk/events/event.rb +2 -1
  20. data/lib/mtk/events/note.rb +1 -1
  21. data/lib/mtk/events/parameter.rb +1 -0
  22. data/lib/mtk/events/rest.rb +85 -0
  23. data/lib/mtk/events/timeline.rb +6 -2
  24. data/lib/mtk/io/jsound_input.rb +9 -3
  25. data/lib/mtk/io/midi_file.rb +38 -2
  26. data/lib/mtk/io/midi_input.rb +1 -1
  27. data/lib/mtk/io/midi_output.rb +95 -4
  28. data/lib/mtk/io/unimidi_input.rb +7 -3
  29. data/lib/mtk/lang/durations.rb +31 -26
  30. data/lib/mtk/lang/intensities.rb +29 -30
  31. data/lib/mtk/lang/intervals.rb +108 -41
  32. data/lib/mtk/lang/mtk_grammar.citrus +14 -4
  33. data/lib/mtk/lang/parser.rb +10 -5
  34. data/lib/mtk/lang/pitch_classes.rb +45 -17
  35. data/lib/mtk/lang/pitches.rb +169 -32
  36. data/lib/mtk/lang/tutorial.rb +279 -0
  37. data/lib/mtk/lang/tutorial_lesson.rb +87 -0
  38. data/lib/mtk/sequencers/event_builder.rb +29 -8
  39. data/spec/mtk/core/duration_spec.rb +14 -1
  40. data/spec/mtk/core/intensity_spec.rb +1 -1
  41. data/spec/mtk/events/event_spec.rb +10 -16
  42. data/spec/mtk/events/note_spec.rb +3 -3
  43. data/spec/mtk/events/rest_spec.rb +184 -0
  44. data/spec/mtk/events/timeline_spec.rb +5 -1
  45. data/spec/mtk/io/midi_file_spec.rb +13 -2
  46. data/spec/mtk/io/midi_output_spec.rb +42 -9
  47. data/spec/mtk/lang/durations_spec.rb +5 -5
  48. data/spec/mtk/lang/intensities_spec.rb +5 -5
  49. data/spec/mtk/lang/intervals_spec.rb +139 -13
  50. data/spec/mtk/lang/parser_spec.rb +65 -25
  51. data/spec/mtk/lang/pitch_classes_spec.rb +0 -11
  52. data/spec/mtk/lang/pitches_spec.rb +0 -15
  53. data/spec/mtk/patterns/chain_spec.rb +7 -7
  54. data/spec/mtk/patterns/for_each_spec.rb +2 -2
  55. data/spec/mtk/sequencers/event_builder_spec.rb +49 -17
  56. metadata +12 -22
@@ -48,15 +48,4 @@ describe MTK::Lang::PitchClasses do
48
48
  end
49
49
  end
50
50
 
51
- describe ".[]" do
52
- it "acts like PitchClass.[]" do
53
- for name in PitchClasses::PITCH_CLASS_NAMES
54
- PitchClasses[name].should == PitchClass[name]
55
- end
56
- end
57
-
58
- it "returns nil for arguments it doesn't understand" do
59
- PitchClasses[:invalid].should be_nil
60
- end
61
- end
62
51
  end
@@ -38,19 +38,4 @@ describe MTK::Lang::Pitches do
38
38
  end
39
39
  end
40
40
 
41
- describe ".[]" do
42
- it "acts like Pitch.from_s for the names in PITCH_NAMES, and also treats '_' like '-'" do
43
- for name in Pitches::PITCH_NAMES
44
- Pitches[name].should == Pitch.from_s(name.sub('_','-')) # the constant names need to use underscores, but Pitch.from_s doesn't understand that
45
- if name =~ /_/
46
- Pitches[name.sub('_','-')].should == Pitch.from_s(name.sub('_','-')) # make sure '-' works too
47
- end
48
- end
49
- end
50
-
51
- it "returns nil for arguments it doesn't understand" do
52
- Pitches[:invalid].should be_nil
53
- end
54
- end
55
-
56
41
  end
@@ -43,11 +43,11 @@ describe MTK::Patterns::Chain do
43
43
  end
44
44
 
45
45
  it 'combines 2 patterns, and returns #next until the last StopIteration of a nested Pattern occurs' do
46
- chain = CHAIN.new [Patterns.Sequence(C,D,E), Patterns.Sequence(w,h,q,i)]
46
+ chain = CHAIN.new [Patterns.Sequence(C,D,E), Patterns.Sequence(w,h,q,e)]
47
47
  chain.next.should == [C,w]
48
48
  chain.next.should == [D,h]
49
49
  chain.next.should == [E,q]
50
- chain.next.should == [C,i]
50
+ chain.next.should == [C,e]
51
51
  lambda{ chain.next }.should raise_error StopIteration
52
52
  end
53
53
 
@@ -56,18 +56,18 @@ describe MTK::Patterns::Chain do
56
56
 
57
57
 
58
58
  it 'combines Choice patterns with max_cycles' do
59
- chain = CHAIN.new [Patterns.Choice(i,s), Patterns.Choice(C,D,E)], max_cycles:100
59
+ chain = CHAIN.new [Patterns.Choice(e,s), Patterns.Choice(C,D,E)], max_cycles:100
60
60
  100.times do |time|
61
61
  attrs = chain.next
62
62
  attrs.length.should == 2
63
- (attrs[0]==i or attrs[0]==s).should be_true
63
+ (attrs[0]==e or attrs[0]==s).should be_true
64
64
  (attrs[1]==C or attrs[1]==D or attrs[1]==E).should be_true
65
65
  end
66
66
  lambda{ chain.next }.should raise_error StopIteration
67
67
  end
68
68
 
69
69
  it 'combines Choice patterns and emits a only single combination of attributes by default' do
70
- chain = CHAIN.new [Patterns.Choice(i,s), Patterns.Choice(C,D,E)]
70
+ chain = CHAIN.new [Patterns.Choice(e,s), Patterns.Choice(C,D,E)]
71
71
  chain.next
72
72
  lambda{ chain.next }.should raise_error StopIteration
73
73
  end
@@ -78,7 +78,7 @@ describe MTK::Patterns::Chain do
78
78
  end
79
79
 
80
80
  it 'throws StopIteration when any subpattern throws StopIteration with max_elements_exceeded' do
81
- chain = CHAIN.new [Patterns.Sequence(C,D,E,F,G), Patterns.Sequence(w,h,q,i, max_elements:3)]
81
+ chain = CHAIN.new [Patterns.Sequence(C,D,E,F,G), Patterns.Sequence(w,h,q,e, max_elements:3)]
82
82
  chain.next.should == [C,w]
83
83
  chain.next.should == [D,h]
84
84
  chain.next.should == [E,q]
@@ -100,7 +100,7 @@ describe MTK::Patterns::Chain do
100
100
  chain = CHAIN.new [C,q]
101
101
  chain.next
102
102
  chain.rewind
103
- lambda{ chain.next }.should_not raise_error StopIteration
103
+ lambda{ chain.next }.should_not raise_error
104
104
  lambda{ chain.next }.should raise_error StopIteration
105
105
  end
106
106
  end
@@ -83,11 +83,11 @@ describe MTK::Patterns::ForEach do
83
83
 
84
84
  it "evaluates nested variables" do
85
85
  # (C4 Bb Ab G)@( (C D C $):(q i i)*4:(mp mf) )
86
- foreach = FOREACH.new( [seq(G,A), chain(seq(C,D,var('$')),seq(q,i,s))] )
86
+ foreach = FOREACH.new( [seq(G,A), chain(seq(C,D,var('$')),seq(q,e,s))] )
87
87
  vals = []
88
88
  6.times{ vals << foreach.next }
89
89
  lambda{ foreach.next }.should raise_error StopIteration
90
- vals.should == [[C,q],[D,i],[G,s],[C,q],[D,i],[A,s]]
90
+ vals.should == [[C,q],[D,e],[G,s],[C,q],[D,e],[A,s]]
91
91
  end
92
92
 
93
93
  end
@@ -57,20 +57,26 @@ describe MTK::Sequencers::EventBuilder do
57
57
  event_builder.next.should == notes(C4)
58
58
  end
59
59
 
60
- it "defaults to intensity 'o' when no intensities are given" do
60
+ it "defaults to intensity 'f' when no intensities are given" do
61
61
  event_builder = EVENT_BUILDER.new [Patterns.PitchSequence(C4, D4, E4), Patterns.DurationCycle(2)]
62
- event_builder.next.should == [Note(C4, o, 2)]
63
- event_builder.next.should == [Note(D4, o, 2)]
64
- event_builder.next.should == [Note(E4, o, 2)]
62
+ event_builder.next.should == [Note(C4, f, 2)]
63
+ event_builder.next.should == [Note(D4, f, 2)]
64
+ event_builder.next.should == [Note(E4, f, 2)]
65
65
  end
66
66
 
67
67
  it "defaults to duration 1 when no durations are given" do
68
- event_builder = EVENT_BUILDER.new [Patterns.PitchSequence(C4, D4, E4), Patterns.IntensityCycle(p,o)]
68
+ event_builder = EVENT_BUILDER.new [Patterns.PitchSequence(C4, D4, E4), Patterns.IntensityCycle(p,f)]
69
69
  event_builder.next.should == [Note(C4, p, 1)]
70
- event_builder.next.should == [Note(D4, o, 1)]
70
+ event_builder.next.should == [Note(D4, f, 1)]
71
71
  event_builder.next.should == [Note(E4, p, 1)]
72
72
  end
73
73
 
74
+ it "builds notes from pitch class sets, selecting the first pitches nearest to the default pitch" do
75
+ pitch_class_sequence = MTK::Patterns::Sequence.new([PitchClassSet(C,G)])
76
+ event_builder = EVENT_BUILDER.new [pitch_class_sequence], :default_pitch => D3
77
+ event_builder.next.should == notes(C3,G3)
78
+ end
79
+
74
80
  it "builds notes from pitch class sets, selecting the nearest pitch classes to the previous/default pitch" do
75
81
  pitch_class_sequence = MTK::Patterns::Sequence.new([PitchClassSet(C,G),PitchClassSet(B,Eb),PitchClassSet(D,C)])
76
82
  event_builder = EVENT_BUILDER.new [pitch_class_sequence], :default_pitch => D3
@@ -108,17 +114,17 @@ describe MTK::Sequencers::EventBuilder do
108
114
  end
109
115
 
110
116
  it "iterates through the pitch, intensity, and duration list in parallel to emit Notes" do
111
- event_builder = EVENT_BUILDER.new [Patterns.PitchCycle(C4, D4, E4), Patterns.IntensityCycle(p, o), Patterns.DurationCycle(1,2,3,4)]
117
+ event_builder = EVENT_BUILDER.new [Patterns.PitchCycle(C4, D4, E4), Patterns.IntensityCycle(p, f), Patterns.DurationCycle(1,2,3,4)]
112
118
  event_builder.next.should == [Note(C4, p, 1)]
113
- event_builder.next.should == [Note(D4, o, 2)]
119
+ event_builder.next.should == [Note(D4, f, 2)]
114
120
  event_builder.next.should == [Note(E4, p, 3)]
115
- event_builder.next.should == [Note(C4, o, 4)]
121
+ event_builder.next.should == [Note(C4, f, 4)]
116
122
  event_builder.next.should == [Note(D4, p, 1)]
117
- event_builder.next.should == [Note(E4, o, 2)]
123
+ event_builder.next.should == [Note(E4, f, 2)]
118
124
  end
119
125
 
120
126
  it "returns nil (for a rest) when it encounters a nil value" do
121
- event_builder = EVENT_BUILDER.new [Patterns.PitchCycle(C4, D4, E4, F4, nil), Patterns.IntensityCycle(mp, mf, o, nil), Patterns.DurationCycle(1, 2, nil)]
127
+ event_builder = EVENT_BUILDER.new [Patterns.PitchCycle(C4, D4, E4, F4, nil), Patterns.IntensityCycle(mp, mf, f, nil), Patterns.DurationCycle(1, 2, nil)]
122
128
  event_builder.next.should == [Note(C4, mp, 1)]
123
129
  event_builder.next.should == [Note(D4, mf, 2)]
124
130
  event_builder.next.should be_nil
@@ -166,10 +172,10 @@ describe MTK::Sequencers::EventBuilder do
166
172
  end
167
173
 
168
174
  it "uses the default_pitch when no pitch pattern is provided" do
169
- event_builder = EVENT_BUILDER.new [Patterns.Cycle( mp, mf, o )], :default_pitch => G3
175
+ event_builder = EVENT_BUILDER.new [Patterns.Cycle( mp, mf, f )], :default_pitch => G3
170
176
  event_builder.next.should == [Note(G3,mp,1)]
171
177
  event_builder.next.should == [Note(G3,mf,1)]
172
- event_builder.next.should == [Note(G3,o,1)]
178
+ event_builder.next.should == [Note(G3,f,1)]
173
179
  end
174
180
 
175
181
  it "handles chains of sequences" do
@@ -204,8 +210,8 @@ describe MTK::Sequencers::EventBuilder do
204
210
  end
205
211
 
206
212
  it "adds chained durations together" do
207
- event_builder = EVENT_BUILDER.new( [Patterns.Chain(h,q,i,s)] )
208
- event_builder.next[0].duration.should == h+q+i+s
213
+ event_builder = EVENT_BUILDER.new( [Patterns.Chain(h,q,e,s)] )
214
+ event_builder.next[0].duration.should == h+q+e+s
209
215
  end
210
216
 
211
217
  it "averages chained intensities together" do
@@ -215,11 +221,11 @@ describe MTK::Sequencers::EventBuilder do
215
221
 
216
222
  it "defaults the intensity to the previous intensity" do
217
223
  event_builder = EVENT_BUILDER.new(
218
- [Patterns.Sequence(Patterns.Chain(C4,ppp,q), Patterns.Chain(D4,i), Patterns.Chain(E4,ff,h), Patterns.Chain(F4,i))]
224
+ [Patterns.Sequence(Patterns.Chain(C4,ppp,q), Patterns.Chain(D4,e), Patterns.Chain(E4,ff,h), Patterns.Chain(F4,e))]
219
225
  )
220
226
  notes = []
221
227
  4.times{ notes += event_builder.next }
222
- notes.should == [Note(C4,ppp,q), Note(D4,ppp,i), Note(E4,ff,h), Note(F4,ff,i)]
228
+ notes.should == [Note(C4,ppp,q), Note(D4,ppp,e), Note(E4,ff,h), Note(F4,ff,e)]
223
229
  end
224
230
 
225
231
  it "defaults the duration to the previous duration" do
@@ -230,6 +236,32 @@ describe MTK::Sequencers::EventBuilder do
230
236
  4.times{ notes += event_builder.next }
231
237
  notes.should == [Note(C4,ppp,h), Note(D4,mp,h), Note(E4,ff,s), Note(F4,mf,s)]
232
238
  end
239
+
240
+ it "uses the previous pitch class in the chain to determine the octave of the current pitch class" do
241
+ event_builder = EVENT_BUILDER.new([Patterns.Chain(C4,E,G)])
242
+ event_builder.next.should == [Note(C4),Note(E4),Note(G4)]
243
+ end
244
+
245
+ it "returns a Rest event when the duration is negative" do
246
+ event_builder = EVENT_BUILDER.new([Patterns.Chain(C4,-q)])
247
+ event_builder.next.should == [Rest(q)]
248
+ end
249
+
250
+ it "doesn't uses the absolute value of the previous rest when generating the next event" do
251
+ event_builder = EVENT_BUILDER.new([Patterns.Sequence(Patterns.Chain(C4,q), -q, D4)])
252
+ event_builder.next.should == [Note(C4,q)]
253
+ event_builder.next.should == [Rest(q)]
254
+ event_builder.next.should == [Note(D4,q)]
255
+ end
256
+
257
+ it "makes all event chained to a rest be a rest" do
258
+ event_builder = EVENT_BUILDER.new(
259
+ [Patterns.Sequence(Patterns.Chain(C4,q), Patterns.Chain(-q, Patterns.Sequence(D4,E4)))]
260
+ )
261
+ event_builder.next.should == [Note(C4,q)]
262
+ event_builder.next.should == [Rest(q)]
263
+ event_builder.next.should == [Rest(q)]
264
+ end
233
265
  end
234
266
 
235
267
  describe "#rewind" do
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jmtk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3.3
5
- prerelease:
4
+ version: '0.4'
6
5
  platform: java
7
6
  authors:
8
7
  - Adam Murray
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-06-13 00:00:00.000000000 Z
11
+ date: 2013-08-05 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: citrus
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: midilib
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: gamelan
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
@@ -62,7 +55,6 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: jsound
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ~>
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ~>
76
67
  - !ruby/object:Gem::Version
@@ -95,6 +86,7 @@ files:
95
86
  - examples/drum_pattern.rb
96
87
  - examples/dynamic_pattern.rb
97
88
  - examples/gets_and_play.rb
89
+ - examples/helpers/output_selector.rb
98
90
  - examples/notation.rb
99
91
  - examples/play_midi.rb
100
92
  - examples/print_midi.rb
@@ -110,6 +102,7 @@ files:
110
102
  - lib/mtk/events/event.rb
111
103
  - lib/mtk/events/note.rb
112
104
  - lib/mtk/events/parameter.rb
105
+ - lib/mtk/events/rest.rb
113
106
  - lib/mtk/events/timeline.rb
114
107
  - lib/mtk/groups/chord.rb
115
108
  - lib/mtk/groups/collection.rb
@@ -134,6 +127,8 @@ files:
134
127
  - lib/mtk/lang/pitch_classes.rb
135
128
  - lib/mtk/lang/pitches.rb
136
129
  - lib/mtk/lang/pseudo_constants.rb
130
+ - lib/mtk/lang/tutorial.rb
131
+ - lib/mtk/lang/tutorial_lesson.rb
137
132
  - lib/mtk/lang/variable.rb
138
133
  - lib/mtk/numeric_extensions.rb
139
134
  - lib/mtk/patterns/chain.rb
@@ -159,6 +154,7 @@ files:
159
154
  - spec/mtk/events/event_spec.rb
160
155
  - spec/mtk/events/note_spec.rb
161
156
  - spec/mtk/events/parameter_spec.rb
157
+ - spec/mtk/events/rest_spec.rb
162
158
  - spec/mtk/events/timeline_spec.rb
163
159
  - spec/mtk/groups/chord_spec.rb
164
160
  - spec/mtk/groups/collection_spec.rb
@@ -193,34 +189,28 @@ files:
193
189
  - spec/spec_helper.rb
194
190
  - spec/test.mid
195
191
  homepage: http://github.com/adamjmurray/mtk
196
- licenses: []
192
+ licenses:
193
+ - BSD
194
+ metadata: {}
197
195
  post_install_message:
198
196
  rdoc_options: []
199
197
  require_paths:
200
198
  - lib
201
199
  required_ruby_version: !ruby/object:Gem::Requirement
202
- none: false
203
200
  requirements:
204
201
  - - ! '>='
205
202
  - !ruby/object:Gem::Version
206
203
  version: '0'
207
- segments:
208
- - 0
209
- hash: 1626364894868064054
210
204
  required_rubygems_version: !ruby/object:Gem::Requirement
211
- none: false
212
205
  requirements:
213
206
  - - ! '>='
214
207
  - !ruby/object:Gem::Version
215
208
  version: '0'
216
- segments:
217
- - 0
218
- hash: 1626364894868064054
219
209
  requirements: []
220
210
  rubyforge_project:
221
- rubygems_version: 1.8.25
211
+ rubygems_version: 2.0.6
222
212
  signing_key:
223
- specification_version: 3
213
+ specification_version: 4
224
214
  summary: Music Tool Kit for Ruby
225
215
  test_files: []
226
216
  has_rdoc: