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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8b7b17820849b85c63d55bd0ddac48b10c53e86c
4
- data.tar.gz: 7ba98c1ae18ea8b6631d8a2c40ffb55525fbe3f4
3
+ metadata.gz: 8d21073b4a61467ca784ffae3482346e9c0d34b3
4
+ data.tar.gz: 381efdae0c02c9dcf0700f21ee5462accd5d5db3
5
5
  SHA512:
6
- metadata.gz: 36033a773afaf9999d7601236093bab72d71e5a639373de670431b563c23a07329a00ea61d8e70edd9c3f5d129e6bb118d6551466fb2468e8b4fc4e366d13b32
7
- data.tar.gz: 224776f667078ff2fe8f3fd6aafd262aad382e6d487c27c35da9a5caab3dfbbb5b6c6755cc602b1c616fd7da8713e4d2b14997f4bfb1d8c7a9bedb0b65400a68
6
+ metadata.gz: 6d27840fc552267e4327afd0c25238ec1cc48972192ed90643046b0980ec31f70be9e3a4d8f4f43b77fe23988a33b0186b6fe7b6d0b5b28d5492015c49de0d63
7
+ data.tar.gz: 1750142a012d3314e102157689d4e146ca63c35d6762bf2b02173b549c750ed56c2e8820cda0a930942647a2be6878c58ab99a936207578160ad6575b9f130ff
data/Rakefile CHANGED
@@ -52,3 +52,37 @@ task :make_examples do
52
52
 
53
53
  Dir.chdir current_dir
54
54
  end
55
+
56
+ def rb_fname fname
57
+ basename = File.basename(fname, File.extname(fname))
58
+ dirname = File.dirname(fname)
59
+ "#{dirname}/#{basename}.rb"
60
+ end
61
+
62
+ task :build_parsers do
63
+ wd = Dir.pwd
64
+ Dir.chdir "lib/music-transcription/parsing"
65
+ parser_files = Dir.glob(["**/*.treetop","**/*.tt"])
66
+
67
+ if parser_files.empty?
68
+ puts "No parsers found"
69
+ return
70
+ end
71
+
72
+ build_list = parser_files.select do |fname|
73
+ rb_name = rb_fname(fname)
74
+ !File.exists?(rb_name) || (File.mtime(fname) > File.mtime(rb_name))
75
+ end
76
+
77
+ if build_list.any?
78
+ puts "building parsers:"
79
+ build_list.each do |fname|
80
+ puts " #{fname} -> #{rb_fname(fname)}"
81
+ `tt -f #{fname}`
82
+ end
83
+ else
84
+ puts "Parsers are up-to-date"
85
+ end
86
+ Dir.chdir wd
87
+ end
88
+ task :spec => :build_parsers
@@ -18,8 +18,8 @@ class Change
18
18
  class Immediate < Change
19
19
  include Validatable
20
20
 
21
+ @@check_methods = [ :ensure_zero_duration ]
21
22
  def initialize value
22
- @check_methods = [ :ensure_zero_duration ]
23
23
  super(value,0)
24
24
  end
25
25
 
@@ -33,8 +33,8 @@ class Change
33
33
  class Gradual < Change
34
34
  include Validatable
35
35
 
36
+ @@check_methods = [ :ensure_nonnegative_duration ]
36
37
  def initialize value, transition_duration
37
- @check_methods = [ :ensure_nonnegative_duration ]
38
38
  super(value, transition_duration)
39
39
  end
40
40
 
@@ -3,14 +3,13 @@ module Transcription
3
3
 
4
4
  class Meter
5
5
  include Validatable
6
-
7
6
  attr_reader :measure_duration, :beat_duration, :beats_per_measure
7
+
8
+ @@check_methods = [ :check_beats_per_measure, :check_beat_duration ]
8
9
  def initialize beats_per_measure, beat_duration
9
10
  @beats_per_measure = beats_per_measure
10
11
  @beat_duration = beat_duration
11
- @measure_duration = beats_per_measure * beat_duration
12
-
13
- @check_methods = [ :check_beats_per_measure, :check_beat_duration ]
12
+ @measure_duration = beats_per_measure * beat_duration
14
13
  end
15
14
 
16
15
  def check_beats_per_measure
@@ -11,14 +11,13 @@ class Note
11
11
 
12
12
  DEFAULT_ARTICULATION = Articulations::NORMAL
13
13
 
14
+ @@check_methods = [ :ensure_positive_duration ]
14
15
  def initialize duration, pitches = [], articulation: DEFAULT_ARTICULATION, accented: false, links: {}
15
16
  @duration = duration
16
17
  @pitches = Set.new(pitches).sort
17
18
  @articulation = articulation
18
19
  @accented = accented
19
20
  @links = links
20
-
21
- @check_methods = [ :ensure_positive_duration ]
22
21
  end
23
22
 
24
23
  def ensure_positive_duration
@@ -0,0 +1,266 @@
1
+ # Autogenerated from a Treetop grammar. Edits may be lost.
2
+
3
+
4
+ module Music
5
+ module Transcription
6
+ module Parsing
7
+
8
+ module Articulation
9
+ include Treetop::Runtime
10
+
11
+ def root
12
+ @root ||= :articulation
13
+ end
14
+
15
+ def _nt_articulation
16
+ start_index = index
17
+ if node_cache[:articulation].has_key?(index)
18
+ cached = node_cache[:articulation][index]
19
+ if cached
20
+ node_cache[:articulation][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
21
+ @index = cached.interval.end
22
+ end
23
+ return cached
24
+ end
25
+
26
+ i0 = index
27
+ r1 = _nt_slur
28
+ if r1
29
+ r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
30
+ r0 = r1
31
+ else
32
+ r2 = _nt_legato
33
+ if r2
34
+ r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
35
+ r0 = r2
36
+ else
37
+ r3 = _nt_tenuto
38
+ if r3
39
+ r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true
40
+ r0 = r3
41
+ else
42
+ r4 = _nt_portato
43
+ if r4
44
+ r4 = SyntaxNode.new(input, (index-1)...index) if r4 == true
45
+ r0 = r4
46
+ else
47
+ r5 = _nt_staccato
48
+ if r5
49
+ r5 = SyntaxNode.new(input, (index-1)...index) if r5 == true
50
+ r0 = r5
51
+ else
52
+ r6 = _nt_staccatissimo
53
+ if r6
54
+ r6 = SyntaxNode.new(input, (index-1)...index) if r6 == true
55
+ r0 = r6
56
+ else
57
+ @index = i0
58
+ r0 = nil
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ node_cache[:articulation][start_index] = r0
67
+
68
+ r0
69
+ end
70
+
71
+ module Slur0
72
+ def to_articulation
73
+ Music::Transcription::Articulations::SLUR
74
+ end
75
+ end
76
+
77
+ def _nt_slur
78
+ start_index = index
79
+ if node_cache[:slur].has_key?(index)
80
+ cached = node_cache[:slur][index]
81
+ if cached
82
+ node_cache[:slur][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
83
+ @index = cached.interval.end
84
+ end
85
+ return cached
86
+ end
87
+
88
+ if (match_len = has_terminal?("=", false, index))
89
+ r0 = instantiate_node(SyntaxNode,input, index...(index + match_len))
90
+ r0.extend(Slur0)
91
+ @index += match_len
92
+ else
93
+ terminal_parse_failure("=")
94
+ r0 = nil
95
+ end
96
+
97
+ node_cache[:slur][start_index] = r0
98
+
99
+ r0
100
+ end
101
+
102
+ module Legato0
103
+ def to_articulation
104
+ Music::Transcription::Articulations::LEGATO
105
+ end
106
+ end
107
+
108
+ def _nt_legato
109
+ start_index = index
110
+ if node_cache[:legato].has_key?(index)
111
+ cached = node_cache[:legato][index]
112
+ if cached
113
+ node_cache[:legato][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
114
+ @index = cached.interval.end
115
+ end
116
+ return cached
117
+ end
118
+
119
+ if (match_len = has_terminal?("-", false, index))
120
+ r0 = instantiate_node(SyntaxNode,input, index...(index + match_len))
121
+ r0.extend(Legato0)
122
+ @index += match_len
123
+ else
124
+ terminal_parse_failure("-")
125
+ r0 = nil
126
+ end
127
+
128
+ node_cache[:legato][start_index] = r0
129
+
130
+ r0
131
+ end
132
+
133
+ module Tenuto0
134
+ def to_articulation
135
+ Music::Transcription::Articulations::TENUTO
136
+ end
137
+ end
138
+
139
+ def _nt_tenuto
140
+ start_index = index
141
+ if node_cache[:tenuto].has_key?(index)
142
+ cached = node_cache[:tenuto][index]
143
+ if cached
144
+ node_cache[:tenuto][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
145
+ @index = cached.interval.end
146
+ end
147
+ return cached
148
+ end
149
+
150
+ if (match_len = has_terminal?("_", false, index))
151
+ r0 = instantiate_node(SyntaxNode,input, index...(index + match_len))
152
+ r0.extend(Tenuto0)
153
+ @index += match_len
154
+ else
155
+ terminal_parse_failure("_")
156
+ r0 = nil
157
+ end
158
+
159
+ node_cache[:tenuto][start_index] = r0
160
+
161
+ r0
162
+ end
163
+
164
+ module Portato0
165
+ def to_articulation
166
+ Music::Transcription::Articulations::PORTATO
167
+ end
168
+ end
169
+
170
+ def _nt_portato
171
+ start_index = index
172
+ if node_cache[:portato].has_key?(index)
173
+ cached = node_cache[:portato][index]
174
+ if cached
175
+ node_cache[:portato][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
176
+ @index = cached.interval.end
177
+ end
178
+ return cached
179
+ end
180
+
181
+ if (match_len = has_terminal?("%", false, index))
182
+ r0 = instantiate_node(SyntaxNode,input, index...(index + match_len))
183
+ r0.extend(Portato0)
184
+ @index += match_len
185
+ else
186
+ terminal_parse_failure("%")
187
+ r0 = nil
188
+ end
189
+
190
+ node_cache[:portato][start_index] = r0
191
+
192
+ r0
193
+ end
194
+
195
+ module Staccato0
196
+ def to_articulation
197
+ Music::Transcription::Articulations::STACCATO
198
+ end
199
+ end
200
+
201
+ def _nt_staccato
202
+ start_index = index
203
+ if node_cache[:staccato].has_key?(index)
204
+ cached = node_cache[:staccato][index]
205
+ if cached
206
+ node_cache[:staccato][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
207
+ @index = cached.interval.end
208
+ end
209
+ return cached
210
+ end
211
+
212
+ if (match_len = has_terminal?(".", false, index))
213
+ r0 = instantiate_node(SyntaxNode,input, index...(index + match_len))
214
+ r0.extend(Staccato0)
215
+ @index += match_len
216
+ else
217
+ terminal_parse_failure(".")
218
+ r0 = nil
219
+ end
220
+
221
+ node_cache[:staccato][start_index] = r0
222
+
223
+ r0
224
+ end
225
+
226
+ module Staccatissimo0
227
+ def to_articulation
228
+ Music::Transcription::Articulations::STACCATISSIMO
229
+ end
230
+ end
231
+
232
+ def _nt_staccatissimo
233
+ start_index = index
234
+ if node_cache[:staccatissimo].has_key?(index)
235
+ cached = node_cache[:staccatissimo][index]
236
+ if cached
237
+ node_cache[:staccatissimo][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
238
+ @index = cached.interval.end
239
+ end
240
+ return cached
241
+ end
242
+
243
+ if (match_len = has_terminal?("'", false, index))
244
+ r0 = instantiate_node(SyntaxNode,input, index...(index + match_len))
245
+ r0.extend(Staccatissimo0)
246
+ @index += match_len
247
+ else
248
+ terminal_parse_failure("'")
249
+ r0 = nil
250
+ end
251
+
252
+ node_cache[:staccatissimo][start_index] = r0
253
+
254
+ r0
255
+ end
256
+
257
+ end
258
+
259
+ class ArticulationParser < Treetop::Runtime::CompiledParser
260
+ include Articulation
261
+ end
262
+
263
+
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,61 @@
1
+ module Music
2
+ module Transcription
3
+ module Parsing
4
+
5
+ grammar Articulation
6
+ rule articulation
7
+ slur / legato / tenuto / portato / staccato / staccatissimo
8
+ end
9
+
10
+ rule slur
11
+ "=" {
12
+ def to_articulation
13
+ Music::Transcription::Articulations::SLUR
14
+ end
15
+ }
16
+ end
17
+
18
+ rule legato
19
+ "-" {
20
+ def to_articulation
21
+ Music::Transcription::Articulations::LEGATO
22
+ end
23
+ }
24
+ end
25
+
26
+ rule tenuto
27
+ "_" {
28
+ def to_articulation
29
+ Music::Transcription::Articulations::TENUTO
30
+ end
31
+ }
32
+ end
33
+
34
+ rule portato
35
+ "%" {
36
+ def to_articulation
37
+ Music::Transcription::Articulations::PORTATO
38
+ end
39
+ }
40
+ end
41
+
42
+ rule staccato
43
+ "." {
44
+ def to_articulation
45
+ Music::Transcription::Articulations::STACCATO
46
+ end
47
+ }
48
+ end
49
+
50
+ rule staccatissimo
51
+ "'" {
52
+ def to_articulation
53
+ Music::Transcription::Articulations::STACCATISSIMO
54
+ end
55
+ }
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,83 @@
1
+ module Music
2
+ module Transcription
3
+ module Parsing
4
+ DURATION_PARSER = DurationParser.new
5
+ PITCH_PARSER = PitchParser.new
6
+ NOTE_PARSER = NoteParser.new
7
+
8
+ def duration dur_str
9
+ DURATION_PARSER.parse(dur_str).to_r
10
+ end
11
+ alias :dur :duration
12
+ module_function :duration
13
+ module_function :dur
14
+
15
+ def durations durs_str
16
+ durs_str.split.map do |dur_str|
17
+ duration(dur_str)
18
+ end
19
+ end
20
+ alias :durs :durations
21
+ module_function :durs
22
+ module_function :durations
23
+
24
+ def pitch p_str
25
+ PITCH_PARSER.parse(p_str).to_pitch
26
+ end
27
+ module_function :pitch
28
+
29
+ def pitches ps_str
30
+ ps_str.split.map do |p_str|
31
+ pitch(p_str)
32
+ end
33
+ end
34
+ module_function :pitches
35
+
36
+ def note note_str
37
+ NOTE_PARSER.parse(note_str).to_note
38
+ end
39
+ module_function :note
40
+
41
+ def notes notes_str
42
+ notes_str.split.map do |note_str|
43
+ note(note_str)
44
+ end
45
+ end
46
+ module_function :notes
47
+ end
48
+ end
49
+ end
50
+
51
+ class String
52
+ def to_duration
53
+ Music::Transcription::Parsing::duration(self)
54
+ end
55
+ alias :to_dur :to_duration
56
+ alias :to_d :to_duration
57
+
58
+ def to_durations
59
+ Music::Transcription::Parsing::durations(self)
60
+ end
61
+ alias :to_durs :to_durations
62
+ alias :to_ds :to_durations
63
+
64
+ def to_pitch
65
+ Music::Transcription::Parsing::pitch(self)
66
+ end
67
+ alias :to_p :to_pitch
68
+
69
+ def to_pitches
70
+ Music::Transcription::Parsing::pitches(self)
71
+ end
72
+ alias :to_ps :to_pitches
73
+
74
+ def to_note
75
+ Music::Transcription::Parsing::note(self)
76
+ end
77
+ alias :to_n :to_note
78
+
79
+ def to_notes
80
+ Music::Transcription::Parsing::notes(self)
81
+ end
82
+ alias :to_ns :to_notes
83
+ end