music-transcription 0.17.1 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/hip.rb +4 -4
- data/examples/missed_connection.rb +3 -3
- data/examples/song1.rb +6 -6
- data/examples/song2.rb +3 -3
- data/lib/music-transcription.rb +8 -2
- data/lib/music-transcription/model/change.rb +9 -3
- data/lib/music-transcription/model/measure_score.rb +62 -0
- data/lib/music-transcription/model/meter.rb +5 -1
- data/lib/music-transcription/model/note.rb +4 -1
- data/lib/music-transcription/model/note_score.rb +60 -0
- data/lib/music-transcription/model/part.rb +4 -1
- data/lib/music-transcription/model/program.rb +5 -2
- data/lib/music-transcription/model/tempo.rb +13 -23
- data/lib/music-transcription/packing/measure_score_packing.rb +34 -0
- data/lib/music-transcription/packing/{score_packing.rb → note_score_packing.rb} +12 -21
- data/lib/music-transcription/packing/part_packing.rb +1 -1
- data/lib/music-transcription/packing/program_packing.rb +1 -1
- data/lib/music-transcription/parsing/convenience_methods.rb +37 -58
- data/lib/music-transcription/parsing/numbers/nonnegative_float_parsing.rb +172 -59
- data/lib/music-transcription/parsing/numbers/nonnegative_float_parsing.treetop +13 -1
- data/lib/music-transcription/parsing/numbers/positive_float_parsing.rb +505 -0
- data/lib/music-transcription/parsing/numbers/positive_float_parsing.treetop +35 -0
- data/lib/music-transcription/parsing/numbers/positive_integer_parsing.rb +2 -0
- data/lib/music-transcription/parsing/numbers/positive_integer_parsing.treetop +2 -0
- data/lib/music-transcription/parsing/numbers/positive_rational_parsing.rb +86 -0
- data/lib/music-transcription/parsing/numbers/positive_rational_parsing.treetop +21 -0
- data/lib/music-transcription/parsing/parseable.rb +32 -0
- data/lib/music-transcription/parsing/tempo_parsing.rb +396 -0
- data/lib/music-transcription/parsing/tempo_parsing.treetop +49 -0
- data/lib/music-transcription/validatable.rb +5 -18
- data/lib/music-transcription/version.rb +1 -1
- data/spec/model/measure_score_spec.rb +85 -0
- data/spec/model/note_score_spec.rb +68 -0
- data/spec/model/tempo_spec.rb +15 -15
- data/spec/packing/{score_packing_spec.rb → measure_score_packing_spec.rb} +13 -7
- data/spec/packing/note_score_packing_spec.rb +100 -0
- data/spec/packing/part_packing_spec.rb +1 -1
- data/spec/parsing/convenience_methods_spec.rb +80 -81
- data/spec/parsing/numbers/nonnegative_float_spec.rb +19 -2
- data/spec/parsing/numbers/positive_float_spec.rb +28 -0
- data/spec/parsing/numbers/positive_integer_spec.rb +13 -2
- data/spec/parsing/numbers/positive_rational_spec.rb +28 -0
- data/spec/parsing/tempo_parsing_spec.rb +21 -0
- metadata +27 -8
- data/lib/music-transcription/model/score.rb +0 -68
- data/spec/model/score_spec.rb +0 -69
@@ -16,7 +16,7 @@ class Part
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.unpack packing
|
19
|
-
unpacked_notes =
|
19
|
+
unpacked_notes = Note.split_parse(packing["notes"])
|
20
20
|
unpacked_dcs = Hash[ packing["dynamic_changes"].map do |offset,change|
|
21
21
|
[ offset,Change.unpack(change) ]
|
22
22
|
end ]
|
@@ -1,103 +1,82 @@
|
|
1
1
|
module Music
|
2
2
|
module Transcription
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
SEGMENT_PARSER = SegmentParser.new
|
9
|
-
|
10
|
-
def duration dur_str
|
11
|
-
DURATION_PARSER.parse(dur_str).to_r
|
3
|
+
|
4
|
+
class Duration
|
5
|
+
PARSER = Parsing::DurationParser.new
|
6
|
+
CONVERSION_METHOD = :to_r
|
7
|
+
include Parseable
|
12
8
|
end
|
13
|
-
alias :dur :duration
|
14
|
-
module_function :duration
|
15
|
-
module_function :dur
|
16
9
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
10
|
+
class Pitch
|
11
|
+
PARSER = Parsing::PitchParser.new
|
12
|
+
CONVERSION_METHOD = :to_pitch
|
13
|
+
include Parseable
|
21
14
|
end
|
22
|
-
alias :durs :durations
|
23
|
-
module_function :durs
|
24
|
-
module_function :durations
|
25
15
|
|
26
|
-
|
27
|
-
|
16
|
+
class Note
|
17
|
+
PARSER = Parsing::NoteParser.new
|
18
|
+
CONVERSION_METHOD = :to_note
|
19
|
+
include Parseable
|
28
20
|
end
|
29
|
-
module_function :pitch
|
30
21
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
module_function :pitches
|
37
|
-
|
38
|
-
def note note_str
|
39
|
-
NOTE_PARSER.parse(note_str).to_note
|
22
|
+
class Meter
|
23
|
+
PARSER = Parsing::MeterParser.new
|
24
|
+
CONVERSION_METHOD = :to_meter
|
25
|
+
include Parseable
|
40
26
|
end
|
41
|
-
module_function :note
|
42
27
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
28
|
+
class Segment
|
29
|
+
PARSER = Parsing::SegmentParser.new
|
30
|
+
CONVERSION_METHOD = :to_range
|
31
|
+
include Parseable
|
47
32
|
end
|
48
|
-
module_function :notes
|
49
33
|
|
50
|
-
|
51
|
-
|
34
|
+
class Tempo
|
35
|
+
PARSER = Parsing::TempoParser.new
|
36
|
+
CONVERSION_METHOD = :to_tempo
|
37
|
+
include Parseable
|
52
38
|
end
|
53
|
-
module_function :meter
|
54
|
-
|
55
|
-
def segment seg_str
|
56
|
-
SEGMENT_PARSER.parse(seg_str).to_range
|
57
|
-
end
|
58
|
-
module_function :segment
|
59
|
-
end
|
60
39
|
end
|
61
40
|
end
|
62
41
|
|
63
42
|
class String
|
64
43
|
def to_duration
|
65
|
-
Music::Transcription::
|
44
|
+
Music::Transcription::Duration.parse(self)
|
66
45
|
end
|
67
46
|
alias :to_dur :to_duration
|
68
47
|
alias :to_d :to_duration
|
69
48
|
|
70
|
-
def to_durations
|
71
|
-
Music::Transcription::
|
49
|
+
def to_durations pattern=" "
|
50
|
+
Music::Transcription::Duration.split_parse(self, pattern)
|
72
51
|
end
|
73
52
|
alias :to_durs :to_durations
|
74
53
|
alias :to_ds :to_durations
|
75
54
|
|
76
|
-
def to_pitch
|
77
|
-
Music::Transcription::
|
55
|
+
def to_pitch
|
56
|
+
Music::Transcription::Pitch.parse(self)
|
78
57
|
end
|
79
58
|
alias :to_p :to_pitch
|
80
59
|
|
81
|
-
def to_pitches
|
82
|
-
Music::Transcription::
|
60
|
+
def to_pitches pattern=" "
|
61
|
+
Music::Transcription::Pitch.split_parse(self, pattern)
|
83
62
|
end
|
84
63
|
alias :to_ps :to_pitches
|
85
64
|
|
86
65
|
def to_note
|
87
|
-
Music::Transcription::
|
66
|
+
Music::Transcription::Note.parse(self)
|
88
67
|
end
|
89
68
|
alias :to_n :to_note
|
90
69
|
|
91
|
-
def to_notes
|
92
|
-
Music::Transcription::
|
70
|
+
def to_notes pattern=" "
|
71
|
+
Music::Transcription::Note.split_parse(self, pattern)
|
93
72
|
end
|
94
73
|
alias :to_ns :to_notes
|
95
74
|
|
96
75
|
def to_meter
|
97
|
-
Music::Transcription::
|
76
|
+
Music::Transcription::Meter.parse(self)
|
98
77
|
end
|
99
78
|
|
100
79
|
def to_segment
|
101
|
-
Music::Transcription::
|
80
|
+
Music::Transcription::Segment.parse(self)
|
102
81
|
end
|
103
82
|
end
|
@@ -13,12 +13,6 @@ module NonnegativeFloat
|
|
13
13
|
end
|
14
14
|
|
15
15
|
module NonnegativeFloat0
|
16
|
-
end
|
17
|
-
|
18
|
-
module NonnegativeFloat1
|
19
|
-
end
|
20
|
-
|
21
|
-
module NonnegativeFloat2
|
22
16
|
def to_f
|
23
17
|
text_value.to_f
|
24
18
|
end
|
@@ -37,6 +31,100 @@ module NonnegativeFloat
|
|
37
31
|
return cached
|
38
32
|
end
|
39
33
|
|
34
|
+
i0 = index
|
35
|
+
r1 = _nt_float1
|
36
|
+
if r1
|
37
|
+
r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
|
38
|
+
r0 = r1
|
39
|
+
r0.extend(NonnegativeFloat0)
|
40
|
+
else
|
41
|
+
r2 = _nt_float2
|
42
|
+
if r2
|
43
|
+
r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
|
44
|
+
r0 = r2
|
45
|
+
r0.extend(NonnegativeFloat0)
|
46
|
+
else
|
47
|
+
@index = i0
|
48
|
+
r0 = nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
node_cache[:nonnegative_float][start_index] = r0
|
53
|
+
|
54
|
+
r0
|
55
|
+
end
|
56
|
+
|
57
|
+
module Float10
|
58
|
+
def exponent
|
59
|
+
elements[1]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def _nt_float1
|
64
|
+
start_index = index
|
65
|
+
if node_cache[:float1].has_key?(index)
|
66
|
+
cached = node_cache[:float1][index]
|
67
|
+
if cached
|
68
|
+
node_cache[:float1][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
69
|
+
@index = cached.interval.end
|
70
|
+
end
|
71
|
+
return cached
|
72
|
+
end
|
73
|
+
|
74
|
+
i0, s0 = index, []
|
75
|
+
s1, i1 = [], index
|
76
|
+
loop do
|
77
|
+
if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index)
|
78
|
+
r2 = true
|
79
|
+
@index += 1
|
80
|
+
else
|
81
|
+
terminal_parse_failure('[0-9]')
|
82
|
+
r2 = nil
|
83
|
+
end
|
84
|
+
if r2
|
85
|
+
s1 << r2
|
86
|
+
else
|
87
|
+
break
|
88
|
+
end
|
89
|
+
end
|
90
|
+
if s1.empty?
|
91
|
+
@index = i1
|
92
|
+
r1 = nil
|
93
|
+
else
|
94
|
+
r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
|
95
|
+
end
|
96
|
+
s0 << r1
|
97
|
+
if r1
|
98
|
+
r3 = _nt_exponent
|
99
|
+
s0 << r3
|
100
|
+
end
|
101
|
+
if s0.last
|
102
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
103
|
+
r0.extend(Float10)
|
104
|
+
else
|
105
|
+
@index = i0
|
106
|
+
r0 = nil
|
107
|
+
end
|
108
|
+
|
109
|
+
node_cache[:float1][start_index] = r0
|
110
|
+
|
111
|
+
r0
|
112
|
+
end
|
113
|
+
|
114
|
+
module Float20
|
115
|
+
end
|
116
|
+
|
117
|
+
def _nt_float2
|
118
|
+
start_index = index
|
119
|
+
if node_cache[:float2].has_key?(index)
|
120
|
+
cached = node_cache[:float2][index]
|
121
|
+
if cached
|
122
|
+
node_cache[:float2][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
123
|
+
@index = cached.interval.end
|
124
|
+
end
|
125
|
+
return cached
|
126
|
+
end
|
127
|
+
|
40
128
|
i0, s0 = index, []
|
41
129
|
s1, i1 = [], index
|
42
130
|
loop do
|
@@ -93,56 +181,7 @@ module NonnegativeFloat
|
|
93
181
|
end
|
94
182
|
s0 << r4
|
95
183
|
if r4
|
96
|
-
|
97
|
-
if (match_len = has_terminal?("e", false, index))
|
98
|
-
r8 = true
|
99
|
-
@index += match_len
|
100
|
-
else
|
101
|
-
terminal_parse_failure("e")
|
102
|
-
r8 = nil
|
103
|
-
end
|
104
|
-
s7 << r8
|
105
|
-
if r8
|
106
|
-
if has_terminal?(@regexps[gr = '\A[+-]'] ||= Regexp.new(gr), :regexp, index)
|
107
|
-
r9 = true
|
108
|
-
@index += 1
|
109
|
-
else
|
110
|
-
terminal_parse_failure('[+-]')
|
111
|
-
r9 = nil
|
112
|
-
end
|
113
|
-
s7 << r9
|
114
|
-
if r9
|
115
|
-
s10, i10 = [], index
|
116
|
-
loop do
|
117
|
-
if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index)
|
118
|
-
r11 = true
|
119
|
-
@index += 1
|
120
|
-
else
|
121
|
-
terminal_parse_failure('[0-9]')
|
122
|
-
r11 = nil
|
123
|
-
end
|
124
|
-
if r11
|
125
|
-
s10 << r11
|
126
|
-
else
|
127
|
-
break
|
128
|
-
end
|
129
|
-
end
|
130
|
-
if s10.empty?
|
131
|
-
@index = i10
|
132
|
-
r10 = nil
|
133
|
-
else
|
134
|
-
r10 = instantiate_node(SyntaxNode,input, i10...index, s10)
|
135
|
-
end
|
136
|
-
s7 << r10
|
137
|
-
end
|
138
|
-
end
|
139
|
-
if s7.last
|
140
|
-
r7 = instantiate_node(SyntaxNode,input, i7...index, s7)
|
141
|
-
r7.extend(NonnegativeFloat0)
|
142
|
-
else
|
143
|
-
@index = i7
|
144
|
-
r7 = nil
|
145
|
-
end
|
184
|
+
r7 = _nt_exponent
|
146
185
|
if r7
|
147
186
|
r6 = r7
|
148
187
|
else
|
@@ -154,14 +193,88 @@ module NonnegativeFloat
|
|
154
193
|
end
|
155
194
|
if s0.last
|
156
195
|
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
157
|
-
r0.extend(
|
158
|
-
r0.extend(NonnegativeFloat2)
|
196
|
+
r0.extend(Float20)
|
159
197
|
else
|
160
198
|
@index = i0
|
161
199
|
r0 = nil
|
162
200
|
end
|
163
201
|
|
164
|
-
node_cache[:
|
202
|
+
node_cache[:float2][start_index] = r0
|
203
|
+
|
204
|
+
r0
|
205
|
+
end
|
206
|
+
|
207
|
+
module Exponent0
|
208
|
+
end
|
209
|
+
|
210
|
+
def _nt_exponent
|
211
|
+
start_index = index
|
212
|
+
if node_cache[:exponent].has_key?(index)
|
213
|
+
cached = node_cache[:exponent][index]
|
214
|
+
if cached
|
215
|
+
node_cache[:exponent][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
|
216
|
+
@index = cached.interval.end
|
217
|
+
end
|
218
|
+
return cached
|
219
|
+
end
|
220
|
+
|
221
|
+
i0, s0 = index, []
|
222
|
+
if (match_len = has_terminal?("e", false, index))
|
223
|
+
r1 = true
|
224
|
+
@index += match_len
|
225
|
+
else
|
226
|
+
terminal_parse_failure("e")
|
227
|
+
r1 = nil
|
228
|
+
end
|
229
|
+
s0 << r1
|
230
|
+
if r1
|
231
|
+
if has_terminal?(@regexps[gr = '\A[+-]'] ||= Regexp.new(gr), :regexp, index)
|
232
|
+
r3 = true
|
233
|
+
@index += 1
|
234
|
+
else
|
235
|
+
terminal_parse_failure('[+-]')
|
236
|
+
r3 = nil
|
237
|
+
end
|
238
|
+
if r3
|
239
|
+
r2 = r3
|
240
|
+
else
|
241
|
+
r2 = instantiate_node(SyntaxNode,input, index...index)
|
242
|
+
end
|
243
|
+
s0 << r2
|
244
|
+
if r2
|
245
|
+
s4, i4 = [], index
|
246
|
+
loop do
|
247
|
+
if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index)
|
248
|
+
r5 = true
|
249
|
+
@index += 1
|
250
|
+
else
|
251
|
+
terminal_parse_failure('[0-9]')
|
252
|
+
r5 = nil
|
253
|
+
end
|
254
|
+
if r5
|
255
|
+
s4 << r5
|
256
|
+
else
|
257
|
+
break
|
258
|
+
end
|
259
|
+
end
|
260
|
+
if s4.empty?
|
261
|
+
@index = i4
|
262
|
+
r4 = nil
|
263
|
+
else
|
264
|
+
r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
|
265
|
+
end
|
266
|
+
s0 << r4
|
267
|
+
end
|
268
|
+
end
|
269
|
+
if s0.last
|
270
|
+
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
|
271
|
+
r0.extend(Exponent0)
|
272
|
+
else
|
273
|
+
@index = i0
|
274
|
+
r0 = nil
|
275
|
+
end
|
276
|
+
|
277
|
+
node_cache[:exponent][start_index] = r0
|
165
278
|
|
166
279
|
r0
|
167
280
|
end
|
@@ -4,7 +4,7 @@ module Parsing
|
|
4
4
|
|
5
5
|
grammar NonnegativeFloat
|
6
6
|
rule nonnegative_float
|
7
|
-
|
7
|
+
(float1 / float2) {
|
8
8
|
def to_f
|
9
9
|
text_value.to_f
|
10
10
|
end
|
@@ -12,6 +12,18 @@ grammar NonnegativeFloat
|
|
12
12
|
alias :to_num :to_f
|
13
13
|
}
|
14
14
|
end
|
15
|
+
|
16
|
+
rule float1
|
17
|
+
[0-9]+ exponent
|
18
|
+
end
|
19
|
+
|
20
|
+
rule float2
|
21
|
+
[0-9]+ [.] [0-9]+ exponent?
|
22
|
+
end
|
23
|
+
|
24
|
+
rule exponent
|
25
|
+
"e" [+-]? [0-9]+
|
26
|
+
end
|
15
27
|
end
|
16
28
|
|
17
29
|
end
|