musicality 0.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.
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