music-transcription 0.9.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +34 -0
  3. data/lib/music-transcription/change.rb +2 -2
  4. data/lib/music-transcription/meter.rb +3 -4
  5. data/lib/music-transcription/note.rb +1 -2
  6. data/lib/music-transcription/parsing/articulation_parsing.rb +266 -0
  7. data/lib/music-transcription/parsing/articulation_parsing.treetop +61 -0
  8. data/lib/music-transcription/parsing/convenience_methods.rb +83 -0
  9. data/lib/music-transcription/parsing/duration_nodes.rb +23 -0
  10. data/lib/music-transcription/parsing/duration_parsing.rb +207 -0
  11. data/lib/music-transcription/parsing/duration_parsing.treetop +27 -0
  12. data/lib/music-transcription/parsing/link_nodes.rb +37 -0
  13. data/lib/music-transcription/parsing/link_parsing.rb +272 -0
  14. data/lib/music-transcription/parsing/link_parsing.treetop +35 -0
  15. data/lib/music-transcription/parsing/nonnegative_integer_parsing.rb +57 -0
  16. data/lib/music-transcription/parsing/nonnegative_integer_parsing.treetop +13 -0
  17. data/lib/music-transcription/parsing/note_nodes.rb +64 -0
  18. data/lib/music-transcription/parsing/note_parsing.rb +354 -0
  19. data/lib/music-transcription/parsing/note_parsing.treetop +47 -0
  20. data/lib/music-transcription/parsing/pitch_node.rb +20 -0
  21. data/lib/music-transcription/parsing/pitch_parsing.rb +355 -0
  22. data/lib/music-transcription/parsing/pitch_parsing.treetop +45 -0
  23. data/lib/music-transcription/parsing/positive_integer_parsing.rb +95 -0
  24. data/lib/music-transcription/parsing/positive_integer_parsing.treetop +19 -0
  25. data/lib/music-transcription/part.rb +1 -1
  26. data/lib/music-transcription/program.rb +1 -4
  27. data/lib/music-transcription/score.rb +1 -1
  28. data/lib/music-transcription/validatable.rb +16 -1
  29. data/lib/music-transcription/version.rb +1 -1
  30. data/lib/music-transcription.rb +14 -0
  31. data/music-transcription.gemspec +2 -0
  32. data/spec/parsing/articulation_parsing_spec.rb +23 -0
  33. data/spec/parsing/convenience_methods_spec.rb +89 -0
  34. data/spec/parsing/duration_nodes_spec.rb +83 -0
  35. data/spec/parsing/duration_parsing_spec.rb +70 -0
  36. data/spec/parsing/link_nodes_spec.rb +30 -0
  37. data/spec/parsing/link_parsing_spec.rb +23 -0
  38. data/spec/parsing/nonnegative_integer_spec.rb +11 -0
  39. data/spec/parsing/note_nodes_spec.rb +84 -0
  40. data/spec/parsing/note_parsing_spec.rb +43 -0
  41. data/spec/parsing/pitch_node_spec.rb +32 -0
  42. data/spec/parsing/pitch_parsing_spec.rb +23 -0
  43. data/spec/parsing/positive_integer_spec.rb +17 -0
  44. data/spec/spec_helper.rb +12 -0
  45. metadata +59 -2
@@ -0,0 +1,47 @@
1
+ module Music
2
+ module Transcription
3
+ module Parsing
4
+
5
+ grammar Note
6
+ include Pitch
7
+ include Articulation
8
+ include Link
9
+ include Duration
10
+
11
+ rule note
12
+ polyphonic_note / monophonic_note / rest_note
13
+ end
14
+
15
+ rule rest_note
16
+ duration:duration <RestNoteNode>
17
+ end
18
+
19
+ rule monophonic_note
20
+ duration
21
+ art:articulation?
22
+ pl:pitch_link
23
+ acc:accent?
24
+ <MonophonicNoteNode>
25
+ end
26
+
27
+ rule polyphonic_note
28
+ duration
29
+ art:articulation?
30
+ pl:pitch_link
31
+ more_pitches:("," pl:pitch_link)+
32
+ acc:accent?
33
+ <PolyphonicNoteNode>
34
+ end
35
+
36
+ rule pitch_link
37
+ pitch the_link:link?
38
+ end
39
+
40
+ rule accent
41
+ "!"
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,20 @@
1
+ module Music
2
+ module Transcription
3
+ module Parsing
4
+ class PitchNode < Treetop::Runtime::SyntaxNode
5
+ def to_pitch
6
+
7
+ sem = pitch_letter.to_semitone
8
+ unless mod.empty?
9
+ sem += case mod.text_value
10
+ when "#" then 1
11
+ when "b" then -1
12
+ end
13
+ end
14
+ oct = octn.text_value.to_i
15
+ Music::Transcription::Pitch.new(semitone: sem, octave: oct)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,355 @@
1
+ # Autogenerated from a Treetop grammar. Edits may be lost.
2
+
3
+
4
+ module Music
5
+ module Transcription
6
+ module Parsing
7
+
8
+ module Pitch
9
+ include Treetop::Runtime
10
+
11
+ def root
12
+ @root ||= :pitch
13
+ end
14
+
15
+ module Pitch0
16
+ def pitch_letter
17
+ elements[0]
18
+ end
19
+
20
+ def mod
21
+ elements[1]
22
+ end
23
+
24
+ def octn
25
+ elements[2]
26
+ end
27
+ end
28
+
29
+ def _nt_pitch
30
+ start_index = index
31
+ if node_cache[:pitch].has_key?(index)
32
+ cached = node_cache[:pitch][index]
33
+ if cached
34
+ node_cache[:pitch][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
35
+ @index = cached.interval.end
36
+ end
37
+ return cached
38
+ end
39
+
40
+ i0, s0 = index, []
41
+ r1 = _nt_pitch_letter
42
+ s0 << r1
43
+ if r1
44
+ if has_terminal?(@regexps[gr = '\A[#b]'] ||= Regexp.new(gr), :regexp, index)
45
+ r3 = true
46
+ @index += 1
47
+ else
48
+ terminal_parse_failure('[#b]')
49
+ r3 = nil
50
+ end
51
+ if r3
52
+ r2 = r3
53
+ else
54
+ r2 = instantiate_node(SyntaxNode,input, index...index)
55
+ end
56
+ s0 << r2
57
+ if r2
58
+ if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index)
59
+ r4 = true
60
+ @index += 1
61
+ else
62
+ terminal_parse_failure('[0-9]')
63
+ r4 = nil
64
+ end
65
+ s0 << r4
66
+ end
67
+ end
68
+ if s0.last
69
+ r0 = instantiate_node(PitchNode,input, i0...index, s0)
70
+ r0.extend(Pitch0)
71
+ else
72
+ @index = i0
73
+ r0 = nil
74
+ end
75
+
76
+ node_cache[:pitch][start_index] = r0
77
+
78
+ r0
79
+ end
80
+
81
+ def _nt_pitch_letter
82
+ start_index = index
83
+ if node_cache[:pitch_letter].has_key?(index)
84
+ cached = node_cache[:pitch_letter][index]
85
+ if cached
86
+ node_cache[:pitch_letter][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
87
+ @index = cached.interval.end
88
+ end
89
+ return cached
90
+ end
91
+
92
+ i0 = index
93
+ r1 = _nt_letter_a
94
+ if r1
95
+ r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
96
+ r0 = r1
97
+ else
98
+ r2 = _nt_letter_b
99
+ if r2
100
+ r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
101
+ r0 = r2
102
+ else
103
+ r3 = _nt_letter_c
104
+ if r3
105
+ r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true
106
+ r0 = r3
107
+ else
108
+ r4 = _nt_letter_d
109
+ if r4
110
+ r4 = SyntaxNode.new(input, (index-1)...index) if r4 == true
111
+ r0 = r4
112
+ else
113
+ r5 = _nt_letter_e
114
+ if r5
115
+ r5 = SyntaxNode.new(input, (index-1)...index) if r5 == true
116
+ r0 = r5
117
+ else
118
+ r6 = _nt_letter_f
119
+ if r6
120
+ r6 = SyntaxNode.new(input, (index-1)...index) if r6 == true
121
+ r0 = r6
122
+ else
123
+ r7 = _nt_letter_g
124
+ if r7
125
+ r7 = SyntaxNode.new(input, (index-1)...index) if r7 == true
126
+ r0 = r7
127
+ else
128
+ @index = i0
129
+ r0 = nil
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ node_cache[:pitch_letter][start_index] = r0
139
+
140
+ r0
141
+ end
142
+
143
+ module LetterA0
144
+ def to_semitone; 9; end
145
+ end
146
+
147
+ def _nt_letter_a
148
+ start_index = index
149
+ if node_cache[:letter_a].has_key?(index)
150
+ cached = node_cache[:letter_a][index]
151
+ if cached
152
+ node_cache[:letter_a][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
153
+ @index = cached.interval.end
154
+ end
155
+ return cached
156
+ end
157
+
158
+ if has_terminal?(@regexps[gr = '\A[Aa]'] ||= Regexp.new(gr), :regexp, index)
159
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
160
+ r0.extend(LetterA0)
161
+ @index += 1
162
+ else
163
+ terminal_parse_failure('[Aa]')
164
+ r0 = nil
165
+ end
166
+
167
+ node_cache[:letter_a][start_index] = r0
168
+
169
+ r0
170
+ end
171
+
172
+ module LetterB0
173
+ def to_semitone; 11; end
174
+ end
175
+
176
+ def _nt_letter_b
177
+ start_index = index
178
+ if node_cache[:letter_b].has_key?(index)
179
+ cached = node_cache[:letter_b][index]
180
+ if cached
181
+ node_cache[:letter_b][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
182
+ @index = cached.interval.end
183
+ end
184
+ return cached
185
+ end
186
+
187
+ if has_terminal?(@regexps[gr = '\A[Bb]'] ||= Regexp.new(gr), :regexp, index)
188
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
189
+ r0.extend(LetterB0)
190
+ @index += 1
191
+ else
192
+ terminal_parse_failure('[Bb]')
193
+ r0 = nil
194
+ end
195
+
196
+ node_cache[:letter_b][start_index] = r0
197
+
198
+ r0
199
+ end
200
+
201
+ module LetterC0
202
+ def to_semitone; 0; end
203
+ end
204
+
205
+ def _nt_letter_c
206
+ start_index = index
207
+ if node_cache[:letter_c].has_key?(index)
208
+ cached = node_cache[:letter_c][index]
209
+ if cached
210
+ node_cache[:letter_c][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
211
+ @index = cached.interval.end
212
+ end
213
+ return cached
214
+ end
215
+
216
+ if has_terminal?(@regexps[gr = '\A[Cc]'] ||= Regexp.new(gr), :regexp, index)
217
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
218
+ r0.extend(LetterC0)
219
+ @index += 1
220
+ else
221
+ terminal_parse_failure('[Cc]')
222
+ r0 = nil
223
+ end
224
+
225
+ node_cache[:letter_c][start_index] = r0
226
+
227
+ r0
228
+ end
229
+
230
+ module LetterD0
231
+ def to_semitone; 2; end
232
+ end
233
+
234
+ def _nt_letter_d
235
+ start_index = index
236
+ if node_cache[:letter_d].has_key?(index)
237
+ cached = node_cache[:letter_d][index]
238
+ if cached
239
+ node_cache[:letter_d][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
240
+ @index = cached.interval.end
241
+ end
242
+ return cached
243
+ end
244
+
245
+ if has_terminal?(@regexps[gr = '\A[Dd]'] ||= Regexp.new(gr), :regexp, index)
246
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
247
+ r0.extend(LetterD0)
248
+ @index += 1
249
+ else
250
+ terminal_parse_failure('[Dd]')
251
+ r0 = nil
252
+ end
253
+
254
+ node_cache[:letter_d][start_index] = r0
255
+
256
+ r0
257
+ end
258
+
259
+ module LetterE0
260
+ def to_semitone; 4; end
261
+ end
262
+
263
+ def _nt_letter_e
264
+ start_index = index
265
+ if node_cache[:letter_e].has_key?(index)
266
+ cached = node_cache[:letter_e][index]
267
+ if cached
268
+ node_cache[:letter_e][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
269
+ @index = cached.interval.end
270
+ end
271
+ return cached
272
+ end
273
+
274
+ if has_terminal?(@regexps[gr = '\A[Ee]'] ||= Regexp.new(gr), :regexp, index)
275
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
276
+ r0.extend(LetterE0)
277
+ @index += 1
278
+ else
279
+ terminal_parse_failure('[Ee]')
280
+ r0 = nil
281
+ end
282
+
283
+ node_cache[:letter_e][start_index] = r0
284
+
285
+ r0
286
+ end
287
+
288
+ module LetterF0
289
+ def to_semitone; 5; end
290
+ end
291
+
292
+ def _nt_letter_f
293
+ start_index = index
294
+ if node_cache[:letter_f].has_key?(index)
295
+ cached = node_cache[:letter_f][index]
296
+ if cached
297
+ node_cache[:letter_f][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
298
+ @index = cached.interval.end
299
+ end
300
+ return cached
301
+ end
302
+
303
+ if has_terminal?(@regexps[gr = '\A[Ff]'] ||= Regexp.new(gr), :regexp, index)
304
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
305
+ r0.extend(LetterF0)
306
+ @index += 1
307
+ else
308
+ terminal_parse_failure('[Ff]')
309
+ r0 = nil
310
+ end
311
+
312
+ node_cache[:letter_f][start_index] = r0
313
+
314
+ r0
315
+ end
316
+
317
+ module LetterG0
318
+ def to_semitone; 7; end
319
+ end
320
+
321
+ def _nt_letter_g
322
+ start_index = index
323
+ if node_cache[:letter_g].has_key?(index)
324
+ cached = node_cache[:letter_g][index]
325
+ if cached
326
+ node_cache[:letter_g][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
327
+ @index = cached.interval.end
328
+ end
329
+ return cached
330
+ end
331
+
332
+ if has_terminal?(@regexps[gr = '\A[Gg]'] ||= Regexp.new(gr), :regexp, index)
333
+ r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
334
+ r0.extend(LetterG0)
335
+ @index += 1
336
+ else
337
+ terminal_parse_failure('[Gg]')
338
+ r0 = nil
339
+ end
340
+
341
+ node_cache[:letter_g][start_index] = r0
342
+
343
+ r0
344
+ end
345
+
346
+ end
347
+
348
+ class PitchParser < Treetop::Runtime::CompiledParser
349
+ include Pitch
350
+ end
351
+
352
+
353
+ end
354
+ end
355
+ end
@@ -0,0 +1,45 @@
1
+ module Music
2
+ module Transcription
3
+ module Parsing
4
+
5
+ grammar Pitch
6
+ rule pitch
7
+ pitch_letter mod:[#b]? octn:[0-9] <PitchNode>
8
+ end
9
+
10
+ rule pitch_letter
11
+ letter_a / letter_b / letter_c / letter_d / letter_e / letter_f / letter_g
12
+ end
13
+
14
+ rule letter_a
15
+ [Aa] { def to_semitone; 9; end }
16
+ end
17
+
18
+ rule letter_b
19
+ [Bb] { def to_semitone; 11; end }
20
+ end
21
+
22
+ rule letter_c
23
+ [Cc] { def to_semitone; 0; end }
24
+ end
25
+
26
+ rule letter_d
27
+ [Dd] { def to_semitone; 2; end }
28
+ end
29
+
30
+ rule letter_e
31
+ [Ee] { def to_semitone; 4; end }
32
+ end
33
+
34
+ rule letter_f
35
+ [Ff] { def to_semitone; 5; end }
36
+ end
37
+
38
+ rule letter_g
39
+ [Gg] { def to_semitone; 7; end }
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end