music-transcription 0.15.0 → 0.16.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.yml +88 -0
- data/examples/missed_connection.yml +34 -0
- data/examples/song1.yml +66 -0
- data/examples/song2.yml +22 -0
- data/lib/music-transcription/model/link.rb +8 -8
- data/lib/music-transcription/model/note.rb +1 -1
- data/lib/music-transcription/model/pitch.rb +66 -46
- data/lib/music-transcription/parsing/articulation_parsing.rb +2 -2
- data/lib/music-transcription/parsing/articulation_parsing.treetop +1 -1
- data/lib/music-transcription/parsing/link_parsing.rb +2 -2
- data/lib/music-transcription/parsing/link_parsing.treetop +1 -1
- data/lib/music-transcription/parsing/pitch_node.rb +7 -2
- data/lib/music-transcription/parsing/pitch_parsing.rb +103 -8
- data/lib/music-transcription/parsing/pitch_parsing.treetop +10 -1
- data/lib/music-transcription/version.rb +1 -1
- data/spec/model/note_spec.rb +2 -1
- data/spec/model/pitch_spec.rb +41 -34
- data/spec/parsing/articulation_parsing_spec.rb +1 -1
- data/spec/parsing/link_nodes_spec.rb +1 -1
- data/spec/parsing/link_parsing_spec.rb +4 -14
- data/spec/parsing/note_node_spec.rb +1 -1
- data/spec/parsing/note_parsing_spec.rb +6 -6
- data/spec/parsing/pitch_node_spec.rb +6 -0
- data/spec/parsing/pitch_parsing_spec.rb +5 -14
- metadata +3 -3
data/examples/song1.yml
CHANGED
@@ -21,6 +21,8 @@ parts:
|
|
21
21
|
- !ruby/object:Music::Transcription::Pitch
|
22
22
|
octave: 2
|
23
23
|
semitone: 0
|
24
|
+
cent: 0
|
25
|
+
total_cents: 2400
|
24
26
|
articulation: :normal
|
25
27
|
accented: false
|
26
28
|
links: {}
|
@@ -32,6 +34,8 @@ parts:
|
|
32
34
|
- !ruby/object:Music::Transcription::Pitch
|
33
35
|
octave: 2
|
34
36
|
semitone: 3
|
37
|
+
cent: 0
|
38
|
+
total_cents: 2700
|
35
39
|
articulation: :normal
|
36
40
|
accented: false
|
37
41
|
links: {}
|
@@ -43,6 +47,8 @@ parts:
|
|
43
47
|
- !ruby/object:Music::Transcription::Pitch
|
44
48
|
octave: 2
|
45
49
|
semitone: 5
|
50
|
+
cent: 0
|
51
|
+
total_cents: 2900
|
46
52
|
articulation: :normal
|
47
53
|
accented: false
|
48
54
|
links: {}
|
@@ -54,6 +60,8 @@ parts:
|
|
54
60
|
- !ruby/object:Music::Transcription::Pitch
|
55
61
|
octave: 2
|
56
62
|
semitone: 3
|
63
|
+
cent: 0
|
64
|
+
total_cents: 2700
|
57
65
|
articulation: :normal
|
58
66
|
accented: false
|
59
67
|
links: {}
|
@@ -73,6 +81,8 @@ parts:
|
|
73
81
|
- !ruby/object:Music::Transcription::Pitch
|
74
82
|
octave: 2
|
75
83
|
semitone: 0
|
84
|
+
cent: 0
|
85
|
+
total_cents: 2400
|
76
86
|
articulation: :normal
|
77
87
|
accented: false
|
78
88
|
links: {}
|
@@ -84,6 +94,8 @@ parts:
|
|
84
94
|
- !ruby/object:Music::Transcription::Pitch
|
85
95
|
octave: 2
|
86
96
|
semitone: 3
|
97
|
+
cent: 0
|
98
|
+
total_cents: 2700
|
87
99
|
articulation: :normal
|
88
100
|
accented: false
|
89
101
|
links: {}
|
@@ -103,6 +115,8 @@ parts:
|
|
103
115
|
- !ruby/object:Music::Transcription::Pitch
|
104
116
|
octave: 2
|
105
117
|
semitone: 0
|
118
|
+
cent: 0
|
119
|
+
total_cents: 2400
|
106
120
|
articulation: :normal
|
107
121
|
accented: false
|
108
122
|
links: {}
|
@@ -114,6 +128,8 @@ parts:
|
|
114
128
|
- !ruby/object:Music::Transcription::Pitch
|
115
129
|
octave: 2
|
116
130
|
semitone: 3
|
131
|
+
cent: 0
|
132
|
+
total_cents: 2700
|
117
133
|
articulation: :normal
|
118
134
|
accented: false
|
119
135
|
links: {}
|
@@ -125,6 +141,8 @@ parts:
|
|
125
141
|
- !ruby/object:Music::Transcription::Pitch
|
126
142
|
octave: 2
|
127
143
|
semitone: 5
|
144
|
+
cent: 0
|
145
|
+
total_cents: 2900
|
128
146
|
articulation: :normal
|
129
147
|
accented: false
|
130
148
|
links: {}
|
@@ -136,6 +154,8 @@ parts:
|
|
136
154
|
- !ruby/object:Music::Transcription::Pitch
|
137
155
|
octave: 2
|
138
156
|
semitone: 3
|
157
|
+
cent: 0
|
158
|
+
total_cents: 2700
|
139
159
|
articulation: :normal
|
140
160
|
accented: false
|
141
161
|
links: {}
|
@@ -155,6 +175,8 @@ parts:
|
|
155
175
|
- !ruby/object:Music::Transcription::Pitch
|
156
176
|
octave: 2
|
157
177
|
semitone: 0
|
178
|
+
cent: 0
|
179
|
+
total_cents: 2400
|
158
180
|
articulation: :normal
|
159
181
|
accented: false
|
160
182
|
links: {}
|
@@ -166,6 +188,8 @@ parts:
|
|
166
188
|
- !ruby/object:Music::Transcription::Pitch
|
167
189
|
octave: 2
|
168
190
|
semitone: 3
|
191
|
+
cent: 0
|
192
|
+
total_cents: 2700
|
169
193
|
articulation: :normal
|
170
194
|
accented: false
|
171
195
|
links: {}
|
@@ -189,6 +213,8 @@ parts:
|
|
189
213
|
- !ruby/object:Music::Transcription::Pitch
|
190
214
|
octave: 3
|
191
215
|
semitone: 10
|
216
|
+
cent: 0
|
217
|
+
total_cents: 4600
|
192
218
|
articulation: :normal
|
193
219
|
accented: false
|
194
220
|
links: {}
|
@@ -200,6 +226,8 @@ parts:
|
|
200
226
|
- !ruby/object:Music::Transcription::Pitch
|
201
227
|
octave: 3
|
202
228
|
semitone: 10
|
229
|
+
cent: 0
|
230
|
+
total_cents: 4600
|
203
231
|
articulation: :normal
|
204
232
|
accented: false
|
205
233
|
links: {}
|
@@ -211,6 +239,8 @@ parts:
|
|
211
239
|
- !ruby/object:Music::Transcription::Pitch
|
212
240
|
octave: 3
|
213
241
|
semitone: 10
|
242
|
+
cent: 0
|
243
|
+
total_cents: 4600
|
214
244
|
articulation: :normal
|
215
245
|
accented: false
|
216
246
|
links: {}
|
@@ -222,6 +252,8 @@ parts:
|
|
222
252
|
- !ruby/object:Music::Transcription::Pitch
|
223
253
|
octave: 3
|
224
254
|
semitone: 10
|
255
|
+
cent: 0
|
256
|
+
total_cents: 4600
|
225
257
|
articulation: :normal
|
226
258
|
accented: false
|
227
259
|
links: {}
|
@@ -233,6 +265,8 @@ parts:
|
|
233
265
|
- !ruby/object:Music::Transcription::Pitch
|
234
266
|
octave: 4
|
235
267
|
semitone: 0
|
268
|
+
cent: 0
|
269
|
+
total_cents: 4800
|
236
270
|
articulation: :normal
|
237
271
|
accented: false
|
238
272
|
links: {}
|
@@ -244,6 +278,8 @@ parts:
|
|
244
278
|
- !ruby/object:Music::Transcription::Pitch
|
245
279
|
octave: 3
|
246
280
|
semitone: 9
|
281
|
+
cent: 0
|
282
|
+
total_cents: 4500
|
247
283
|
articulation: :normal
|
248
284
|
accented: false
|
249
285
|
links: {}
|
@@ -255,6 +291,8 @@ parts:
|
|
255
291
|
- !ruby/object:Music::Transcription::Pitch
|
256
292
|
octave: 3
|
257
293
|
semitone: 7
|
294
|
+
cent: 0
|
295
|
+
total_cents: 4300
|
258
296
|
articulation: :normal
|
259
297
|
accented: false
|
260
298
|
links: {}
|
@@ -266,6 +304,8 @@ parts:
|
|
266
304
|
- !ruby/object:Music::Transcription::Pitch
|
267
305
|
octave: 3
|
268
306
|
semitone: 5
|
307
|
+
cent: 0
|
308
|
+
total_cents: 4100
|
269
309
|
articulation: :normal
|
270
310
|
accented: false
|
271
311
|
links: {}
|
@@ -277,6 +317,8 @@ parts:
|
|
277
317
|
- !ruby/object:Music::Transcription::Pitch
|
278
318
|
octave: 3
|
279
319
|
semitone: 7
|
320
|
+
cent: 0
|
321
|
+
total_cents: 4300
|
280
322
|
articulation: :slur
|
281
323
|
accented: false
|
282
324
|
links: {}
|
@@ -288,6 +330,8 @@ parts:
|
|
288
330
|
- !ruby/object:Music::Transcription::Pitch
|
289
331
|
octave: 3
|
290
332
|
semitone: 5
|
333
|
+
cent: 0
|
334
|
+
total_cents: 4100
|
291
335
|
articulation: :slur
|
292
336
|
accented: false
|
293
337
|
links: {}
|
@@ -299,6 +343,8 @@ parts:
|
|
299
343
|
- !ruby/object:Music::Transcription::Pitch
|
300
344
|
octave: 3
|
301
345
|
semitone: 4
|
346
|
+
cent: 0
|
347
|
+
total_cents: 4000
|
302
348
|
articulation: :normal
|
303
349
|
accented: false
|
304
350
|
links: {}
|
@@ -326,6 +372,8 @@ parts:
|
|
326
372
|
- !ruby/object:Music::Transcription::Pitch
|
327
373
|
octave: 3
|
328
374
|
semitone: 10
|
375
|
+
cent: 0
|
376
|
+
total_cents: 4600
|
329
377
|
articulation: :normal
|
330
378
|
accented: false
|
331
379
|
links: {}
|
@@ -337,6 +385,8 @@ parts:
|
|
337
385
|
- !ruby/object:Music::Transcription::Pitch
|
338
386
|
octave: 3
|
339
387
|
semitone: 10
|
388
|
+
cent: 0
|
389
|
+
total_cents: 4600
|
340
390
|
articulation: :normal
|
341
391
|
accented: false
|
342
392
|
links: {}
|
@@ -348,6 +398,8 @@ parts:
|
|
348
398
|
- !ruby/object:Music::Transcription::Pitch
|
349
399
|
octave: 3
|
350
400
|
semitone: 10
|
401
|
+
cent: 0
|
402
|
+
total_cents: 4600
|
351
403
|
articulation: :normal
|
352
404
|
accented: false
|
353
405
|
links: {}
|
@@ -359,6 +411,8 @@ parts:
|
|
359
411
|
- !ruby/object:Music::Transcription::Pitch
|
360
412
|
octave: 3
|
361
413
|
semitone: 10
|
414
|
+
cent: 0
|
415
|
+
total_cents: 4600
|
362
416
|
articulation: :normal
|
363
417
|
accented: false
|
364
418
|
links: {}
|
@@ -370,6 +424,8 @@ parts:
|
|
370
424
|
- !ruby/object:Music::Transcription::Pitch
|
371
425
|
octave: 4
|
372
426
|
semitone: 0
|
427
|
+
cent: 0
|
428
|
+
total_cents: 4800
|
373
429
|
articulation: :normal
|
374
430
|
accented: false
|
375
431
|
links: {}
|
@@ -381,6 +437,8 @@ parts:
|
|
381
437
|
- !ruby/object:Music::Transcription::Pitch
|
382
438
|
octave: 3
|
383
439
|
semitone: 9
|
440
|
+
cent: 0
|
441
|
+
total_cents: 4500
|
384
442
|
articulation: :normal
|
385
443
|
accented: false
|
386
444
|
links: {}
|
@@ -392,6 +450,8 @@ parts:
|
|
392
450
|
- !ruby/object:Music::Transcription::Pitch
|
393
451
|
octave: 4
|
394
452
|
semitone: 4
|
453
|
+
cent: 0
|
454
|
+
total_cents: 5200
|
395
455
|
articulation: :normal
|
396
456
|
accented: false
|
397
457
|
links: {}
|
@@ -403,6 +463,8 @@ parts:
|
|
403
463
|
- !ruby/object:Music::Transcription::Pitch
|
404
464
|
octave: 4
|
405
465
|
semitone: 4
|
466
|
+
cent: 0
|
467
|
+
total_cents: 5200
|
406
468
|
articulation: :slur
|
407
469
|
accented: false
|
408
470
|
links: {}
|
@@ -414,6 +476,8 @@ parts:
|
|
414
476
|
- !ruby/object:Music::Transcription::Pitch
|
415
477
|
octave: 4
|
416
478
|
semitone: 2
|
479
|
+
cent: 0
|
480
|
+
total_cents: 5000
|
417
481
|
articulation: :slur
|
418
482
|
accented: false
|
419
483
|
links: {}
|
@@ -425,6 +489,8 @@ parts:
|
|
425
489
|
- !ruby/object:Music::Transcription::Pitch
|
426
490
|
octave: 4
|
427
491
|
semitone: 0
|
492
|
+
cent: 0
|
493
|
+
total_cents: 4800
|
428
494
|
articulation: :normal
|
429
495
|
accented: false
|
430
496
|
links: {}
|
data/examples/song2.yml
CHANGED
@@ -21,6 +21,8 @@ parts:
|
|
21
21
|
- !ruby/object:Music::Transcription::Pitch
|
22
22
|
octave: 4
|
23
23
|
semitone: 0
|
24
|
+
cent: 0
|
25
|
+
total_cents: 4800
|
24
26
|
articulation: :normal
|
25
27
|
accented: false
|
26
28
|
links: {}
|
@@ -32,6 +34,8 @@ parts:
|
|
32
34
|
- !ruby/object:Music::Transcription::Pitch
|
33
35
|
octave: 3
|
34
36
|
semitone: 10
|
37
|
+
cent: 0
|
38
|
+
total_cents: 4600
|
35
39
|
articulation: :normal
|
36
40
|
accented: false
|
37
41
|
links: {}
|
@@ -43,6 +47,8 @@ parts:
|
|
43
47
|
- !ruby/object:Music::Transcription::Pitch
|
44
48
|
octave: 3
|
45
49
|
semitone: 8
|
50
|
+
cent: 0
|
51
|
+
total_cents: 4400
|
46
52
|
articulation: :normal
|
47
53
|
accented: false
|
48
54
|
links: {}
|
@@ -54,6 +60,8 @@ parts:
|
|
54
60
|
- !ruby/object:Music::Transcription::Pitch
|
55
61
|
octave: 3
|
56
62
|
semitone: 7
|
63
|
+
cent: 0
|
64
|
+
total_cents: 4300
|
57
65
|
articulation: :normal
|
58
66
|
accented: false
|
59
67
|
links: {}
|
@@ -65,6 +73,8 @@ parts:
|
|
65
73
|
- !ruby/object:Music::Transcription::Pitch
|
66
74
|
octave: 3
|
67
75
|
semitone: 10
|
76
|
+
cent: 0
|
77
|
+
total_cents: 4600
|
68
78
|
articulation: :normal
|
69
79
|
accented: false
|
70
80
|
links: {}
|
@@ -80,6 +90,8 @@ parts:
|
|
80
90
|
- !ruby/object:Music::Transcription::Pitch
|
81
91
|
octave: 5
|
82
92
|
semitone: 4
|
93
|
+
cent: 0
|
94
|
+
total_cents: 6400
|
83
95
|
articulation: :normal
|
84
96
|
accented: false
|
85
97
|
links: {}
|
@@ -91,6 +103,8 @@ parts:
|
|
91
103
|
- !ruby/object:Music::Transcription::Pitch
|
92
104
|
octave: 5
|
93
105
|
semitone: 2
|
106
|
+
cent: 0
|
107
|
+
total_cents: 6200
|
94
108
|
articulation: :normal
|
95
109
|
accented: false
|
96
110
|
links: {}
|
@@ -102,6 +116,8 @@ parts:
|
|
102
116
|
- !ruby/object:Music::Transcription::Pitch
|
103
117
|
octave: 5
|
104
118
|
semitone: 0
|
119
|
+
cent: 0
|
120
|
+
total_cents: 6000
|
105
121
|
articulation: :normal
|
106
122
|
accented: false
|
107
123
|
links: {}
|
@@ -113,6 +129,8 @@ parts:
|
|
113
129
|
- !ruby/object:Music::Transcription::Pitch
|
114
130
|
octave: 5
|
115
131
|
semitone: 0
|
132
|
+
cent: 0
|
133
|
+
total_cents: 6000
|
116
134
|
articulation: :normal
|
117
135
|
accented: false
|
118
136
|
links: {}
|
@@ -124,6 +142,8 @@ parts:
|
|
124
142
|
- !ruby/object:Music::Transcription::Pitch
|
125
143
|
octave: 5
|
126
144
|
semitone: 0
|
145
|
+
cent: 0
|
146
|
+
total_cents: 6000
|
127
147
|
articulation: :normal
|
128
148
|
accented: false
|
129
149
|
links: {}
|
@@ -135,6 +155,8 @@ parts:
|
|
135
155
|
- !ruby/object:Music::Transcription::Pitch
|
136
156
|
octave: 5
|
137
157
|
semitone: 2
|
158
|
+
cent: 0
|
159
|
+
total_cents: 6200
|
138
160
|
articulation: :normal
|
139
161
|
accented: false
|
140
162
|
links: {}
|
@@ -30,11 +30,10 @@ class Link
|
|
30
30
|
end
|
31
31
|
|
32
32
|
class TargetedLink < Link
|
33
|
-
attr_accessor :target_pitch
|
33
|
+
attr_accessor :target_pitch
|
34
34
|
|
35
|
-
def initialize target_pitch
|
35
|
+
def initialize target_pitch
|
36
36
|
@target_pitch = target_pitch
|
37
|
-
@link_char = link_char
|
38
37
|
end
|
39
38
|
|
40
39
|
def ==(other)
|
@@ -47,27 +46,28 @@ class Link
|
|
47
46
|
|
48
47
|
def transpose! diff
|
49
48
|
@target_pitch = @target_pitch.transpose(diff)
|
49
|
+
return self
|
50
50
|
end
|
51
51
|
|
52
52
|
def to_s
|
53
|
-
|
53
|
+
link_char + @target_pitch.to_s
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
57
|
class Glissando < TargetedLink
|
58
|
-
def
|
58
|
+
def link_char; "~"; end
|
59
59
|
end
|
60
60
|
|
61
61
|
class Portamento < TargetedLink
|
62
|
-
def
|
62
|
+
def link_char; "/"; end
|
63
63
|
end
|
64
64
|
|
65
65
|
class Slur < TargetedLink
|
66
|
-
def
|
66
|
+
def link_char; "="; end
|
67
67
|
end
|
68
68
|
|
69
69
|
class Legato < TargetedLink
|
70
|
-
def
|
70
|
+
def link_char; "|"; end
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -71,7 +71,7 @@ class Note
|
|
71
71
|
|
72
72
|
art_str = case @articulation
|
73
73
|
when Articulations::SLUR then "="
|
74
|
-
when Articulations::LEGATO then "
|
74
|
+
when Articulations::LEGATO then "|"
|
75
75
|
when Articulations::TENUTO then "_"
|
76
76
|
when Articulations::PORTATO then "%"
|
77
77
|
when Articulations::STACCATO then "."
|
@@ -3,8 +3,8 @@ module Transcription
|
|
3
3
|
|
4
4
|
# Abstraction of a musical pitch. Contains values for octave and semitone.
|
5
5
|
#
|
6
|
-
# Octaves represent the largest means of differing two pitches. Each
|
7
|
-
# octave added will double the ratio. At zero octaves, the ratio is
|
6
|
+
# Octaves represent the largest means of differing two pitches. Each
|
7
|
+
# octave added will double the ratio. At zero octaves, the ratio is
|
8
8
|
# 1.0. At one octave, the ratio will be 2.0. Each semitone is an increment
|
9
9
|
# of less-than-power-of-two.
|
10
10
|
#
|
@@ -12,7 +12,7 @@ module Transcription
|
|
12
12
|
# semitones per octave is 12.
|
13
13
|
|
14
14
|
# @author James Tunnell
|
15
|
-
#
|
15
|
+
#
|
16
16
|
# @!attribute [r] octave
|
17
17
|
# @return [Fixnum] The pitch octave.
|
18
18
|
# @!attribute [r] semitone
|
@@ -20,71 +20,87 @@ module Transcription
|
|
20
20
|
#
|
21
21
|
class Pitch
|
22
22
|
include Comparable
|
23
|
-
attr_reader :octave, :semitone, :
|
23
|
+
attr_reader :octave, :semitone, :cent, :total_cents
|
24
24
|
|
25
|
-
#The default number of semitones per octave is 12, corresponding to
|
25
|
+
#The default number of semitones per octave is 12, corresponding to
|
26
26
|
# the twelve-tone equal temperment tuning system.
|
27
27
|
SEMITONES_PER_OCTAVE = 12
|
28
|
+
CENTS_PER_SEMITONE = 100
|
29
|
+
CENTS_PER_OCTAVE = SEMITONES_PER_OCTAVE * CENTS_PER_SEMITONE
|
28
30
|
|
29
31
|
# The base ferquency is C0
|
30
32
|
BASE_FREQ = 16.351597831287414
|
31
|
-
|
32
|
-
def initialize octave:0, semitone:0
|
33
|
+
|
34
|
+
def initialize octave:0, semitone:0, cent: 0
|
35
|
+
raise NonIntegerError, "octave #{octave} is not an integer" unless octave.is_a?(Integer)
|
36
|
+
raise NonIntegerError, "semitone #{semitone} is not an integer" unless semitone.is_a?(Integer)
|
37
|
+
raise NonIntegerError, "cent #{cent} is not an integer" unless cent.is_a?(Integer)
|
38
|
+
|
33
39
|
@octave = octave
|
34
40
|
@semitone = semitone
|
41
|
+
@cent = cent
|
42
|
+
@total_cents = (@octave*SEMITONES_PER_OCTAVE + @semitone)*CENTS_PER_SEMITONE + @cent
|
35
43
|
normalize!
|
36
|
-
@total_semitone = @octave*SEMITONES_PER_OCTAVE + @semitone
|
37
44
|
end
|
38
45
|
|
39
|
-
# Return the pitch's frequency, which is determined by multiplying the base
|
46
|
+
# Return the pitch's frequency, which is determined by multiplying the base
|
40
47
|
# frequency and the pitch ratio. Base frequency defaults to DEFAULT_BASE_FREQ,
|
41
|
-
# but can be set during initialization to something else by specifying the
|
48
|
+
# but can be set during initialization to something else by specifying the
|
42
49
|
# :base_freq key.
|
43
50
|
def freq
|
44
51
|
return self.ratio() * BASE_FREQ
|
45
52
|
end
|
46
|
-
|
47
|
-
# Calculate the pitch ratio. Raises 2 to the power of the total
|
48
|
-
# count divided by
|
53
|
+
|
54
|
+
# Calculate the pitch ratio. Raises 2 to the power of the total cent
|
55
|
+
# count divided by cents-per-octave.
|
49
56
|
# @return [Float] ratio
|
50
57
|
def ratio
|
51
|
-
2.0**(@
|
58
|
+
2.0**(@total_cents.to_f / CENTS_PER_OCTAVE)
|
52
59
|
end
|
53
|
-
|
60
|
+
|
54
61
|
# Override default hash method.
|
55
62
|
def hash
|
56
|
-
return @
|
63
|
+
return @total_cents
|
57
64
|
end
|
58
|
-
|
65
|
+
|
59
66
|
# Compare pitch equality using total semitone
|
60
67
|
def ==(other)
|
61
68
|
return (self.class == other.class &&
|
62
|
-
@
|
69
|
+
@total_cents == other.total_cents)
|
63
70
|
end
|
64
|
-
|
71
|
+
|
65
72
|
def eql?(other)
|
66
73
|
self == other
|
67
74
|
end
|
68
|
-
|
75
|
+
|
69
76
|
# Compare pitches. A higher ratio or total semitone is considered larger.
|
70
77
|
# @param [Pitch] other The pitch object to compare.
|
71
78
|
def <=> (other)
|
72
|
-
@
|
79
|
+
@total_cents <=> other.total_cents
|
80
|
+
end
|
81
|
+
|
82
|
+
# rounds to the nearest semitone
|
83
|
+
def round
|
84
|
+
if @cent == 0
|
85
|
+
self.clone
|
86
|
+
else
|
87
|
+
Pitch.new(semitone: (@total_cents / CENTS_PER_SEMITONE.to_f).round)
|
88
|
+
end
|
73
89
|
end
|
74
|
-
|
90
|
+
|
91
|
+
# diff in (rounded) semitones
|
75
92
|
def diff other
|
76
|
-
@
|
93
|
+
Rational(@total_cents - other.total_cents, CENTS_PER_SEMITONE)
|
77
94
|
end
|
78
|
-
|
79
|
-
def transpose
|
80
|
-
Pitch.
|
95
|
+
|
96
|
+
def transpose semitones
|
97
|
+
Pitch.new(cent: (@total_cents + semitones * CENTS_PER_SEMITONE).round)
|
81
98
|
end
|
82
|
-
|
83
|
-
# Produce an identical Pitch object.
|
99
|
+
|
84
100
|
def clone
|
85
|
-
|
101
|
+
Pitch.new(cent: @total_cents)
|
86
102
|
end
|
87
|
-
|
103
|
+
|
88
104
|
def to_s(sharpit = false)
|
89
105
|
letter = case semitone
|
90
106
|
when 0 then "C"
|
@@ -101,34 +117,38 @@ class Pitch
|
|
101
117
|
when 11 then "B"
|
102
118
|
end
|
103
119
|
|
104
|
-
|
120
|
+
if @cent == 0
|
121
|
+
return letter + octave.to_s
|
122
|
+
elsif @cent > 0
|
123
|
+
return letter + octave.to_s + "+" + @cent.to_s
|
124
|
+
else
|
125
|
+
return letter + octave.to_s + @cent.to_s
|
126
|
+
end
|
105
127
|
end
|
106
|
-
|
128
|
+
|
107
129
|
def self.from_ratio ratio
|
108
130
|
raise NonPositiveError, "ratio #{ratio} is not > 0" unless ratio > 0
|
109
131
|
x = Math.log2 ratio
|
110
|
-
|
111
|
-
from_semitones(semitones)
|
132
|
+
new(cent: (x * CENTS_PER_OCTAVE).round)
|
112
133
|
end
|
113
|
-
|
134
|
+
|
114
135
|
def self.from_freq freq
|
115
136
|
from_ratio(freq / BASE_FREQ)
|
116
137
|
end
|
117
|
-
|
118
|
-
def self.from_semitones semitones
|
119
|
-
Pitch.new(semitone: semitones)
|
120
|
-
end
|
121
|
-
|
138
|
+
|
122
139
|
private
|
123
|
-
|
124
|
-
# Balance out the octave and semitone count.
|
140
|
+
|
141
|
+
# Balance out the octave and semitone count.
|
125
142
|
def normalize!
|
126
|
-
|
143
|
+
centsTotal = @total_cents
|
144
|
+
|
145
|
+
@octave = centsTotal / CENTS_PER_OCTAVE
|
146
|
+
centsTotal -= @octave * CENTS_PER_OCTAVE
|
127
147
|
|
128
|
-
@
|
129
|
-
|
148
|
+
@semitone = centsTotal / CENTS_PER_SEMITONE
|
149
|
+
centsTotal -= @semitone * CENTS_PER_SEMITONE
|
130
150
|
|
131
|
-
@
|
151
|
+
@cent = centsTotal
|
132
152
|
return self
|
133
153
|
end
|
134
154
|
end
|