musicality 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +47 -0
  8. data/Rakefile +65 -0
  9. data/bin/midify +78 -0
  10. data/examples/hip.rb +32 -0
  11. data/examples/missed_connection.rb +26 -0
  12. data/examples/song1.rb +33 -0
  13. data/examples/song2.rb +32 -0
  14. data/lib/musicality/errors.rb +9 -0
  15. data/lib/musicality/notation/conversion/change_conversion.rb +19 -0
  16. data/lib/musicality/notation/conversion/measure_note_map.rb +40 -0
  17. data/lib/musicality/notation/conversion/measured_score_conversion.rb +70 -0
  18. data/lib/musicality/notation/conversion/measured_score_converter.rb +95 -0
  19. data/lib/musicality/notation/conversion/note_time_converter.rb +68 -0
  20. data/lib/musicality/notation/conversion/tempo_conversion.rb +25 -0
  21. data/lib/musicality/notation/conversion/unmeasured_score_conversion.rb +47 -0
  22. data/lib/musicality/notation/conversion/unmeasured_score_converter.rb +64 -0
  23. data/lib/musicality/notation/model/articulations.rb +13 -0
  24. data/lib/musicality/notation/model/change.rb +62 -0
  25. data/lib/musicality/notation/model/dynamics.rb +12 -0
  26. data/lib/musicality/notation/model/link.rb +73 -0
  27. data/lib/musicality/notation/model/meter.rb +54 -0
  28. data/lib/musicality/notation/model/meters.rb +9 -0
  29. data/lib/musicality/notation/model/note.rb +120 -0
  30. data/lib/musicality/notation/model/part.rb +54 -0
  31. data/lib/musicality/notation/model/pitch.rb +163 -0
  32. data/lib/musicality/notation/model/pitches.rb +21 -0
  33. data/lib/musicality/notation/model/program.rb +53 -0
  34. data/lib/musicality/notation/model/score.rb +132 -0
  35. data/lib/musicality/notation/packing/change_packing.rb +46 -0
  36. data/lib/musicality/notation/packing/part_packing.rb +31 -0
  37. data/lib/musicality/notation/packing/program_packing.rb +16 -0
  38. data/lib/musicality/notation/packing/score_packing.rb +108 -0
  39. data/lib/musicality/notation/parsing/articulation_parsing.rb +264 -0
  40. data/lib/musicality/notation/parsing/articulation_parsing.treetop +59 -0
  41. data/lib/musicality/notation/parsing/convenience_methods.rb +74 -0
  42. data/lib/musicality/notation/parsing/duration_nodes.rb +21 -0
  43. data/lib/musicality/notation/parsing/duration_parsing.rb +205 -0
  44. data/lib/musicality/notation/parsing/duration_parsing.treetop +25 -0
  45. data/lib/musicality/notation/parsing/link_nodes.rb +35 -0
  46. data/lib/musicality/notation/parsing/link_parsing.rb +270 -0
  47. data/lib/musicality/notation/parsing/link_parsing.treetop +33 -0
  48. data/lib/musicality/notation/parsing/meter_parsing.rb +190 -0
  49. data/lib/musicality/notation/parsing/meter_parsing.treetop +29 -0
  50. data/lib/musicality/notation/parsing/note_node.rb +40 -0
  51. data/lib/musicality/notation/parsing/note_parsing.rb +229 -0
  52. data/lib/musicality/notation/parsing/note_parsing.treetop +28 -0
  53. data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.rb +289 -0
  54. data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.treetop +29 -0
  55. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +64 -0
  56. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.treetop +17 -0
  57. data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.rb +86 -0
  58. data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.treetop +20 -0
  59. data/lib/musicality/notation/parsing/numbers/positive_float_parsing.rb +503 -0
  60. data/lib/musicality/notation/parsing/numbers/positive_float_parsing.treetop +33 -0
  61. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.rb +95 -0
  62. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.treetop +19 -0
  63. data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.rb +84 -0
  64. data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.treetop +19 -0
  65. data/lib/musicality/notation/parsing/parseable.rb +30 -0
  66. data/lib/musicality/notation/parsing/pitch_node.rb +23 -0
  67. data/lib/musicality/notation/parsing/pitch_parsing.rb +448 -0
  68. data/lib/musicality/notation/parsing/pitch_parsing.treetop +52 -0
  69. data/lib/musicality/notation/parsing/segment_parsing.rb +141 -0
  70. data/lib/musicality/notation/parsing/segment_parsing.treetop +23 -0
  71. data/lib/musicality/notation/util/interpolation.rb +16 -0
  72. data/lib/musicality/notation/util/piecewise_function.rb +122 -0
  73. data/lib/musicality/notation/util/value_computer.rb +170 -0
  74. data/lib/musicality/performance/conversion/glissando_converter.rb +34 -0
  75. data/lib/musicality/performance/conversion/note_sequence_extractor.rb +98 -0
  76. data/lib/musicality/performance/conversion/portamento_converter.rb +24 -0
  77. data/lib/musicality/performance/conversion/score_collator.rb +126 -0
  78. data/lib/musicality/performance/midi/midi_events.rb +34 -0
  79. data/lib/musicality/performance/midi/midi_util.rb +31 -0
  80. data/lib/musicality/performance/midi/part_sequencer.rb +123 -0
  81. data/lib/musicality/performance/midi/score_sequencer.rb +45 -0
  82. data/lib/musicality/performance/model/note_attacks.rb +19 -0
  83. data/lib/musicality/performance/model/note_sequence.rb +111 -0
  84. data/lib/musicality/performance/util/note_linker.rb +28 -0
  85. data/lib/musicality/performance/util/optimization.rb +31 -0
  86. data/lib/musicality/validatable.rb +38 -0
  87. data/lib/musicality/version.rb +3 -0
  88. data/lib/musicality.rb +81 -0
  89. data/musicality.gemspec +30 -0
  90. data/spec/musicality_spec.rb +7 -0
  91. data/spec/notation/conversion/change_conversion_spec.rb +40 -0
  92. data/spec/notation/conversion/measure_note_map_spec.rb +73 -0
  93. data/spec/notation/conversion/measured_score_conversion_spec.rb +141 -0
  94. data/spec/notation/conversion/measured_score_converter_spec.rb +329 -0
  95. data/spec/notation/conversion/note_time_converter_spec.rb +81 -0
  96. data/spec/notation/conversion/tempo_conversion_spec.rb +40 -0
  97. data/spec/notation/conversion/unmeasured_score_conversion_spec.rb +71 -0
  98. data/spec/notation/conversion/unmeasured_score_converter_spec.rb +116 -0
  99. data/spec/notation/model/change_spec.rb +90 -0
  100. data/spec/notation/model/link_spec.rb +83 -0
  101. data/spec/notation/model/meter_spec.rb +97 -0
  102. data/spec/notation/model/note_spec.rb +183 -0
  103. data/spec/notation/model/part_spec.rb +69 -0
  104. data/spec/notation/model/pitch_spec.rb +180 -0
  105. data/spec/notation/model/program_spec.rb +50 -0
  106. data/spec/notation/model/score_spec.rb +211 -0
  107. data/spec/notation/packing/change_packing_spec.rb +153 -0
  108. data/spec/notation/packing/part_packing_spec.rb +66 -0
  109. data/spec/notation/packing/program_packing_spec.rb +33 -0
  110. data/spec/notation/packing/score_packing_spec.rb +301 -0
  111. data/spec/notation/parsing/articulation_parsing_spec.rb +23 -0
  112. data/spec/notation/parsing/convenience_methods_spec.rb +99 -0
  113. data/spec/notation/parsing/duration_nodes_spec.rb +83 -0
  114. data/spec/notation/parsing/duration_parsing_spec.rb +70 -0
  115. data/spec/notation/parsing/link_nodes_spec.rb +30 -0
  116. data/spec/notation/parsing/link_parsing_spec.rb +13 -0
  117. data/spec/notation/parsing/meter_parsing_spec.rb +23 -0
  118. data/spec/notation/parsing/note_node_spec.rb +87 -0
  119. data/spec/notation/parsing/note_parsing_spec.rb +46 -0
  120. data/spec/notation/parsing/numbers/nonnegative_float_spec.rb +28 -0
  121. data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +11 -0
  122. data/spec/notation/parsing/numbers/nonnegative_rational_spec.rb +11 -0
  123. data/spec/notation/parsing/numbers/positive_float_spec.rb +28 -0
  124. data/spec/notation/parsing/numbers/positive_integer_spec.rb +28 -0
  125. data/spec/notation/parsing/numbers/positive_rational_spec.rb +28 -0
  126. data/spec/notation/parsing/pitch_node_spec.rb +38 -0
  127. data/spec/notation/parsing/pitch_parsing_spec.rb +14 -0
  128. data/spec/notation/parsing/segment_parsing_spec.rb +27 -0
  129. data/spec/notation/util/value_computer_spec.rb +146 -0
  130. data/spec/performance/conversion/glissando_converter_spec.rb +93 -0
  131. data/spec/performance/conversion/note_sequence_extractor_spec.rb +230 -0
  132. data/spec/performance/conversion/portamento_converter_spec.rb +91 -0
  133. data/spec/performance/conversion/score_collator_spec.rb +183 -0
  134. data/spec/performance/midi/midi_util_spec.rb +110 -0
  135. data/spec/performance/midi/part_sequencer_spec.rb +40 -0
  136. data/spec/performance/midi/score_sequencer_spec.rb +50 -0
  137. data/spec/performance/model/note_sequence_spec.rb +147 -0
  138. data/spec/performance/util/note_linker_spec.rb +68 -0
  139. data/spec/performance/util/optimization_spec.rb +73 -0
  140. data/spec/spec_helper.rb +43 -0
  141. metadata +323 -0
@@ -0,0 +1,19 @@
1
+ module Musicality
2
+ module Parsing
3
+
4
+ grammar PositiveRational
5
+ include PositiveInteger
6
+
7
+ rule positive_rational
8
+ positive_integer "/" positive_integer {
9
+ def to_r
10
+ text_value.to_r
11
+ end
12
+
13
+ alias :to_num :to_r
14
+ }
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ module Musicality
2
+
3
+ # to use, include Parseable and define PARSER constant that has #parse method.
4
+ module Parseable
5
+ DEFAULT_SPLIT_PATTERN = " "
6
+
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+ def parser
13
+ self.const_get(:PARSER)
14
+ end
15
+
16
+ def convert node
17
+ node.send(self.const_get(:CONVERSION_METHOD))
18
+ end
19
+
20
+ def parse str
21
+ convert(parser.parse(str))
22
+ end
23
+
24
+ def split_parse str, pattern=" "
25
+ str.split(pattern).map {|x| convert(parser.parse(x)) }
26
+ end
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,23 @@
1
+ module Musicality
2
+ module Parsing
3
+ class PitchNode < Treetop::Runtime::SyntaxNode
4
+ def to_pitch
5
+
6
+ sem = pitch_letter.to_semitone
7
+ unless mod.empty?
8
+ sem += case mod.text_value
9
+ when "#" then 1
10
+ when "b" then -1
11
+ end
12
+ end
13
+ oct = octave.to_i
14
+ ncents = 0
15
+ unless cents.empty?
16
+ ncents = cents.to_i
17
+ end
18
+
19
+ Musicality::Pitch.new(semitone: sem, octave: oct, cent: ncents)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,448 @@
1
+ # Autogenerated from a Treetop grammar. Edits may be lost.
2
+
3
+
4
+ module Musicality
5
+ module Parsing
6
+
7
+ module Pitch
8
+ include Treetop::Runtime
9
+
10
+ def root
11
+ @root ||= :pitch
12
+ end
13
+
14
+ include NonnegativeInteger
15
+
16
+ module Pitch0
17
+ def pitch_letter
18
+ elements[0]
19
+ end
20
+
21
+ def mod
22
+ elements[1]
23
+ end
24
+
25
+ def octave
26
+ elements[2]
27
+ end
28
+
29
+ def cents
30
+ elements[3]
31
+ end
32
+ end
33
+
34
+ def _nt_pitch
35
+ start_index = index
36
+ if node_cache[:pitch].has_key?(index)
37
+ cached = node_cache[:pitch][index]
38
+ if cached
39
+ node_cache[:pitch][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
40
+ @index = cached.interval.end
41
+ end
42
+ return cached
43
+ end
44
+
45
+ i0, s0 = index, []
46
+ r1 = _nt_pitch_letter
47
+ s0 << r1
48
+ if r1
49
+ if has_terminal?(@regexps[gr = '\A[#b]'] ||= Regexp.new(gr), :regexp, index)
50
+ r3 = true
51
+ @index += 1
52
+ else
53
+ terminal_parse_failure('[#b]')
54
+ r3 = nil
55
+ end
56
+ if r3
57
+ r2 = r3
58
+ else
59
+ r2 = instantiate_node(SyntaxNode,input, index...index)
60
+ end
61
+ s0 << r2
62
+ if r2
63
+ r4 = _nt_octave
64
+ s0 << r4
65
+ if r4
66
+ r6 = _nt_cent
67
+ if r6
68
+ r5 = r6
69
+ else
70
+ r5 = instantiate_node(SyntaxNode,input, index...index)
71
+ end
72
+ s0 << r5
73
+ end
74
+ end
75
+ end
76
+ if s0.last
77
+ r0 = instantiate_node(PitchNode,input, i0...index, s0)
78
+ r0.extend(Pitch0)
79
+ else
80
+ @index = i0
81
+ r0 = nil
82
+ end
83
+
84
+ node_cache[:pitch][start_index] = r0
85
+
86
+ r0
87
+ end
88
+
89
+ module Octave0
90
+ def n
91
+ elements[0]
92
+ end
93
+ end
94
+
95
+ module Octave1
96
+ def to_i; n.to_i; end
97
+ end
98
+
99
+ def _nt_octave
100
+ start_index = index
101
+ if node_cache[:octave].has_key?(index)
102
+ cached = node_cache[:octave][index]
103
+ if cached
104
+ node_cache[:octave][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
105
+ @index = cached.interval.end
106
+ end
107
+ return cached
108
+ end
109
+
110
+ i0, s0 = index, []
111
+ r1 = _nt_nonnegative_integer
112
+ s0 << r1
113
+ if s0.last
114
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
115
+ r0.extend(Octave0)
116
+ r0.extend(Octave1)
117
+ else
118
+ @index = i0
119
+ r0 = nil
120
+ end
121
+
122
+ node_cache[:octave][start_index] = r0
123
+
124
+ r0
125
+ end
126
+
127
+ module Cent0
128
+ def n
129
+ elements[1]
130
+ end
131
+ end
132
+
133
+ module Cent1
134
+ def to_i; text_value.to_i; end
135
+ end
136
+
137
+ def _nt_cent
138
+ start_index = index
139
+ if node_cache[:cent].has_key?(index)
140
+ cached = node_cache[:cent][index]
141
+ if cached
142
+ node_cache[:cent][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
143
+ @index = cached.interval.end
144
+ end
145
+ return cached
146
+ end
147
+
148
+ i0, s0 = index, []
149
+ if has_terminal?(@regexps[gr = '\A[+-]'] ||= Regexp.new(gr), :regexp, index)
150
+ r1 = true
151
+ @index += 1
152
+ else
153
+ terminal_parse_failure('[+-]')
154
+ r1 = nil
155
+ end
156
+ s0 << r1
157
+ if r1
158
+ r2 = _nt_nonnegative_integer
159
+ s0 << r2
160
+ end
161
+ if s0.last
162
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
163
+ r0.extend(Cent0)
164
+ r0.extend(Cent1)
165
+ else
166
+ @index = i0
167
+ r0 = nil
168
+ end
169
+
170
+ node_cache[:cent][start_index] = r0
171
+
172
+ r0
173
+ end
174
+
175
+ def _nt_pitch_letter
176
+ start_index = index
177
+ if node_cache[:pitch_letter].has_key?(index)
178
+ cached = node_cache[:pitch_letter][index]
179
+ if cached
180
+ node_cache[:pitch_letter][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
181
+ @index = cached.interval.end
182
+ end
183
+ return cached
184
+ end
185
+
186
+ i0 = index
187
+ r1 = _nt_letter_a
188
+ if r1
189
+ r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
190
+ r0 = r1
191
+ else
192
+ r2 = _nt_letter_b
193
+ if r2
194
+ r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
195
+ r0 = r2
196
+ else
197
+ r3 = _nt_letter_c
198
+ if r3
199
+ r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true
200
+ r0 = r3
201
+ else
202
+ r4 = _nt_letter_d
203
+ if r4
204
+ r4 = SyntaxNode.new(input, (index-1)...index) if r4 == true
205
+ r0 = r4
206
+ else
207
+ r5 = _nt_letter_e
208
+ if r5
209
+ r5 = SyntaxNode.new(input, (index-1)...index) if r5 == true
210
+ r0 = r5
211
+ else
212
+ r6 = _nt_letter_f
213
+ if r6
214
+ r6 = SyntaxNode.new(input, (index-1)...index) if r6 == true
215
+ r0 = r6
216
+ else
217
+ r7 = _nt_letter_g
218
+ if r7
219
+ r7 = SyntaxNode.new(input, (index-1)...index) if r7 == true
220
+ r0 = r7
221
+ else
222
+ @index = i0
223
+ r0 = nil
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end
230
+ end
231
+
232
+ node_cache[:pitch_letter][start_index] = r0
233
+
234
+ r0
235
+ end
236
+
237
+ module LetterA0
238
+ def to_semitone; 9; end
239
+ end
240
+
241
+ def _nt_letter_a
242
+ start_index = index
243
+ if node_cache[:letter_a].has_key?(index)
244
+ cached = node_cache[:letter_a][index]
245
+ if cached
246
+ node_cache[:letter_a][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
247
+ @index = cached.interval.end
248
+ end
249
+ return cached
250
+ end
251
+
252
+ if has_terminal?(@regexps[gr = '\A[Aa]'] ||= Regexp.new(gr), :regexp, index)
253
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
254
+ r0.extend(LetterA0)
255
+ @index += 1
256
+ else
257
+ terminal_parse_failure('[Aa]')
258
+ r0 = nil
259
+ end
260
+
261
+ node_cache[:letter_a][start_index] = r0
262
+
263
+ r0
264
+ end
265
+
266
+ module LetterB0
267
+ def to_semitone; 11; end
268
+ end
269
+
270
+ def _nt_letter_b
271
+ start_index = index
272
+ if node_cache[:letter_b].has_key?(index)
273
+ cached = node_cache[:letter_b][index]
274
+ if cached
275
+ node_cache[:letter_b][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
276
+ @index = cached.interval.end
277
+ end
278
+ return cached
279
+ end
280
+
281
+ if has_terminal?(@regexps[gr = '\A[Bb]'] ||= Regexp.new(gr), :regexp, index)
282
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
283
+ r0.extend(LetterB0)
284
+ @index += 1
285
+ else
286
+ terminal_parse_failure('[Bb]')
287
+ r0 = nil
288
+ end
289
+
290
+ node_cache[:letter_b][start_index] = r0
291
+
292
+ r0
293
+ end
294
+
295
+ module LetterC0
296
+ def to_semitone; 0; end
297
+ end
298
+
299
+ def _nt_letter_c
300
+ start_index = index
301
+ if node_cache[:letter_c].has_key?(index)
302
+ cached = node_cache[:letter_c][index]
303
+ if cached
304
+ node_cache[:letter_c][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
305
+ @index = cached.interval.end
306
+ end
307
+ return cached
308
+ end
309
+
310
+ if has_terminal?(@regexps[gr = '\A[Cc]'] ||= Regexp.new(gr), :regexp, index)
311
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
312
+ r0.extend(LetterC0)
313
+ @index += 1
314
+ else
315
+ terminal_parse_failure('[Cc]')
316
+ r0 = nil
317
+ end
318
+
319
+ node_cache[:letter_c][start_index] = r0
320
+
321
+ r0
322
+ end
323
+
324
+ module LetterD0
325
+ def to_semitone; 2; end
326
+ end
327
+
328
+ def _nt_letter_d
329
+ start_index = index
330
+ if node_cache[:letter_d].has_key?(index)
331
+ cached = node_cache[:letter_d][index]
332
+ if cached
333
+ node_cache[:letter_d][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
334
+ @index = cached.interval.end
335
+ end
336
+ return cached
337
+ end
338
+
339
+ if has_terminal?(@regexps[gr = '\A[Dd]'] ||= Regexp.new(gr), :regexp, index)
340
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
341
+ r0.extend(LetterD0)
342
+ @index += 1
343
+ else
344
+ terminal_parse_failure('[Dd]')
345
+ r0 = nil
346
+ end
347
+
348
+ node_cache[:letter_d][start_index] = r0
349
+
350
+ r0
351
+ end
352
+
353
+ module LetterE0
354
+ def to_semitone; 4; end
355
+ end
356
+
357
+ def _nt_letter_e
358
+ start_index = index
359
+ if node_cache[:letter_e].has_key?(index)
360
+ cached = node_cache[:letter_e][index]
361
+ if cached
362
+ node_cache[:letter_e][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
363
+ @index = cached.interval.end
364
+ end
365
+ return cached
366
+ end
367
+
368
+ if has_terminal?(@regexps[gr = '\A[Ee]'] ||= Regexp.new(gr), :regexp, index)
369
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
370
+ r0.extend(LetterE0)
371
+ @index += 1
372
+ else
373
+ terminal_parse_failure('[Ee]')
374
+ r0 = nil
375
+ end
376
+
377
+ node_cache[:letter_e][start_index] = r0
378
+
379
+ r0
380
+ end
381
+
382
+ module LetterF0
383
+ def to_semitone; 5; end
384
+ end
385
+
386
+ def _nt_letter_f
387
+ start_index = index
388
+ if node_cache[:letter_f].has_key?(index)
389
+ cached = node_cache[:letter_f][index]
390
+ if cached
391
+ node_cache[:letter_f][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
392
+ @index = cached.interval.end
393
+ end
394
+ return cached
395
+ end
396
+
397
+ if has_terminal?(@regexps[gr = '\A[Ff]'] ||= Regexp.new(gr), :regexp, index)
398
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
399
+ r0.extend(LetterF0)
400
+ @index += 1
401
+ else
402
+ terminal_parse_failure('[Ff]')
403
+ r0 = nil
404
+ end
405
+
406
+ node_cache[:letter_f][start_index] = r0
407
+
408
+ r0
409
+ end
410
+
411
+ module LetterG0
412
+ def to_semitone; 7; end
413
+ end
414
+
415
+ def _nt_letter_g
416
+ start_index = index
417
+ if node_cache[:letter_g].has_key?(index)
418
+ cached = node_cache[:letter_g][index]
419
+ if cached
420
+ node_cache[:letter_g][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
421
+ @index = cached.interval.end
422
+ end
423
+ return cached
424
+ end
425
+
426
+ if has_terminal?(@regexps[gr = '\A[Gg]'] ||= Regexp.new(gr), :regexp, index)
427
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
428
+ r0.extend(LetterG0)
429
+ @index += 1
430
+ else
431
+ terminal_parse_failure('[Gg]')
432
+ r0 = nil
433
+ end
434
+
435
+ node_cache[:letter_g][start_index] = r0
436
+
437
+ r0
438
+ end
439
+
440
+ end
441
+
442
+ class PitchParser < Treetop::Runtime::CompiledParser
443
+ include Pitch
444
+ end
445
+
446
+
447
+ end
448
+ end
@@ -0,0 +1,52 @@
1
+ module Musicality
2
+ module Parsing
3
+
4
+ grammar Pitch
5
+ include NonnegativeInteger
6
+ rule pitch
7
+ pitch_letter mod:[#b]? octave cents:cent? <PitchNode>
8
+ end
9
+
10
+ rule octave
11
+ n:nonnegative_integer { def to_i; n.to_i; end }
12
+ end
13
+
14
+ rule cent
15
+ [+-] n:nonnegative_integer { def to_i; text_value.to_i; end }
16
+ end
17
+
18
+ rule pitch_letter
19
+ letter_a / letter_b / letter_c / letter_d / letter_e / letter_f / letter_g
20
+ end
21
+
22
+ rule letter_a
23
+ [Aa] { def to_semitone; 9; end }
24
+ end
25
+
26
+ rule letter_b
27
+ [Bb] { def to_semitone; 11; end }
28
+ end
29
+
30
+ rule letter_c
31
+ [Cc] { def to_semitone; 0; end }
32
+ end
33
+
34
+ rule letter_d
35
+ [Dd] { def to_semitone; 2; end }
36
+ end
37
+
38
+ rule letter_e
39
+ [Ee] { def to_semitone; 4; end }
40
+ end
41
+
42
+ rule letter_f
43
+ [Ff] { def to_semitone; 5; end }
44
+ end
45
+
46
+ rule letter_g
47
+ [Gg] { def to_semitone; 7; end }
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,141 @@
1
+ # Autogenerated from a Treetop grammar. Edits may be lost.
2
+
3
+
4
+ module Musicality
5
+ module Parsing
6
+
7
+ module Segment
8
+ include Treetop::Runtime
9
+
10
+ def root
11
+ @root ||= :range
12
+ end
13
+
14
+ include NonnegativeInteger
15
+
16
+ include NonnegativeFloat
17
+
18
+ include NonnegativeRational
19
+
20
+ module Range0
21
+ def first
22
+ elements[0]
23
+ end
24
+
25
+ def last
26
+ elements[2]
27
+ end
28
+ end
29
+
30
+ module Range1
31
+ def to_range
32
+ first.to_num...last.to_num
33
+ end
34
+ end
35
+
36
+ def _nt_range
37
+ start_index = index
38
+ if node_cache[:range].has_key?(index)
39
+ cached = node_cache[:range][index]
40
+ if cached
41
+ node_cache[:range][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
42
+ @index = cached.interval.end
43
+ end
44
+ return cached
45
+ end
46
+
47
+ i0, s0 = index, []
48
+ r1 = _nt_nonnegative_number
49
+ s0 << r1
50
+ if r1
51
+ s2, i2 = [], index
52
+ loop do
53
+ if has_terminal?(@regexps[gr = '\A[.]'] ||= Regexp.new(gr), :regexp, index)
54
+ r3 = true
55
+ @index += 1
56
+ else
57
+ terminal_parse_failure('[.]')
58
+ r3 = nil
59
+ end
60
+ if r3
61
+ s2 << r3
62
+ else
63
+ break
64
+ end
65
+ if s2.size == 3
66
+ break
67
+ end
68
+ end
69
+ if s2.size < 2
70
+ @index = i2
71
+ r2 = nil
72
+ else
73
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
74
+ end
75
+ s0 << r2
76
+ if r2
77
+ r4 = _nt_nonnegative_number
78
+ s0 << r4
79
+ end
80
+ end
81
+ if s0.last
82
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
83
+ r0.extend(Range0)
84
+ r0.extend(Range1)
85
+ else
86
+ @index = i0
87
+ r0 = nil
88
+ end
89
+
90
+ node_cache[:range][start_index] = r0
91
+
92
+ r0
93
+ end
94
+
95
+ def _nt_nonnegative_number
96
+ start_index = index
97
+ if node_cache[:nonnegative_number].has_key?(index)
98
+ cached = node_cache[:nonnegative_number][index]
99
+ if cached
100
+ node_cache[:nonnegative_number][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
101
+ @index = cached.interval.end
102
+ end
103
+ return cached
104
+ end
105
+
106
+ i0 = index
107
+ r1 = _nt_nonnegative_float
108
+ if r1
109
+ r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
110
+ r0 = r1
111
+ else
112
+ r2 = _nt_nonnegative_rational
113
+ if r2
114
+ r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
115
+ r0 = r2
116
+ else
117
+ r3 = _nt_nonnegative_integer
118
+ if r3
119
+ r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true
120
+ r0 = r3
121
+ else
122
+ @index = i0
123
+ r0 = nil
124
+ end
125
+ end
126
+ end
127
+
128
+ node_cache[:nonnegative_number][start_index] = r0
129
+
130
+ r0
131
+ end
132
+
133
+ end
134
+
135
+ class SegmentParser < Treetop::Runtime::CompiledParser
136
+ include Segment
137
+ end
138
+
139
+
140
+ end
141
+ end