jmtk 0.0.3.3-java → 0.4-java

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.
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: