music-transcription 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/examples/song2.yml CHANGED
@@ -7,65 +7,80 @@ start_meter: !ruby/object:Music::Transcription::Meter
7
7
  measure_duration: !ruby/object:Rational
8
8
  denominator: 1
9
9
  numerator: 1
10
+ check_methods:
11
+ - :check_beats_per_measure
12
+ - :check_beat_duration
10
13
  start_tempo: 120
11
14
  meter_changes: {}
12
15
  tempo_changes: {}
13
16
  parts:
14
17
  1: !ruby/object:Music::Transcription::Part
15
18
  notes:
16
- - !ruby/object:Music::Transcription::Note::Whole
17
- duration: !ruby/object:Rational
19
+ - !ruby/object:Music::Transcription::Note
20
+ duration: &1 !ruby/object:Rational
18
21
  denominator: 1
19
22
  numerator: 1
20
23
  pitches:
21
24
  - !ruby/object:Music::Transcription::Pitch
22
25
  octave: 4
23
26
  semitone: 0
27
+ articulation: :normal
28
+ accented: false
24
29
  links: {}
25
- accent: &1 !ruby/class 'Music::Transcription::Accent::None'
26
- - !ruby/object:Music::Transcription::Note::Whole
27
- duration: !ruby/object:Rational
28
- denominator: 1
29
- numerator: 1
30
+ check_methods:
31
+ - :ensure_positive_duration
32
+ - !ruby/object:Music::Transcription::Note
33
+ duration: *1
30
34
  pitches:
31
- - &2 !ruby/object:Music::Transcription::Pitch
35
+ - &3 !ruby/object:Music::Transcription::Pitch
32
36
  octave: 3
33
37
  semitone: 10
38
+ articulation: :normal
39
+ accented: false
34
40
  links: {}
35
- accent: *1
36
- - !ruby/object:Music::Transcription::Note::Whole
37
- duration: !ruby/object:Rational
38
- denominator: 1
39
- numerator: 1
41
+ check_methods:
42
+ - :ensure_positive_duration
43
+ - !ruby/object:Music::Transcription::Note
44
+ duration: *1
40
45
  pitches:
41
46
  - !ruby/object:Music::Transcription::Pitch
42
47
  octave: 3
43
48
  semitone: 8
49
+ articulation: :normal
50
+ accented: false
44
51
  links: {}
45
- accent: *1
46
- - !ruby/object:Music::Transcription::Note::Half
47
- duration: !ruby/object:Rational
52
+ check_methods:
53
+ - :ensure_positive_duration
54
+ - !ruby/object:Music::Transcription::Note
55
+ duration: &2 !ruby/object:Rational
48
56
  denominator: 2
49
57
  numerator: 1
50
58
  pitches:
51
59
  - !ruby/object:Music::Transcription::Pitch
52
60
  octave: 3
53
61
  semitone: 7
62
+ articulation: :normal
63
+ accented: false
54
64
  links: {}
55
- accent: *1
56
- - !ruby/object:Music::Transcription::Note::Half
57
- duration: !ruby/object:Rational
58
- denominator: 2
59
- numerator: 1
65
+ check_methods:
66
+ - :ensure_positive_duration
67
+ - !ruby/object:Music::Transcription::Note
68
+ duration: *2
60
69
  pitches:
61
- - *2
70
+ - *3
71
+ articulation: :normal
72
+ accented: false
62
73
  links: {}
63
- accent: *1
64
- start_dynamic: &5 !ruby/object:Music::Transcription::Dynamic::MezzoForte {}
74
+ check_methods:
75
+ - :ensure_positive_duration
76
+ start_dynamic: 0.625
65
77
  dynamic_changes: {}
78
+ check_methods:
79
+ - :ensure_start_dynamic
80
+ - :ensure_dynamic_change_values_range
66
81
  2: !ruby/object:Music::Transcription::Part
67
82
  notes:
68
- - !ruby/object:Music::Transcription::Note::DottedQuarter
83
+ - !ruby/object:Music::Transcription::Note
69
84
  duration: !ruby/object:Rational
70
85
  denominator: 8
71
86
  numerator: 3
@@ -73,156 +88,188 @@ parts:
73
88
  - !ruby/object:Music::Transcription::Pitch
74
89
  octave: 5
75
90
  semitone: 4
91
+ articulation: :normal
92
+ accented: false
76
93
  links: {}
77
- accent: *1
78
- - !ruby/object:Music::Transcription::Note::Whole
79
- duration: !ruby/object:Rational
80
- denominator: 1
81
- numerator: 1
94
+ check_methods:
95
+ - :ensure_positive_duration
96
+ - !ruby/object:Music::Transcription::Note
97
+ duration: *1
82
98
  pitches:
83
- - &4 !ruby/object:Music::Transcription::Pitch
99
+ - &5 !ruby/object:Music::Transcription::Pitch
84
100
  octave: 5
85
101
  semitone: 2
102
+ articulation: :normal
103
+ accented: false
86
104
  links: {}
87
- accent: *1
88
- - !ruby/object:Music::Transcription::Note::Whole
89
- duration: !ruby/object:Rational
90
- denominator: 1
91
- numerator: 1
105
+ check_methods:
106
+ - :ensure_positive_duration
107
+ - !ruby/object:Music::Transcription::Note
108
+ duration: *1
92
109
  pitches:
93
- - &3 !ruby/object:Music::Transcription::Pitch
110
+ - &4 !ruby/object:Music::Transcription::Pitch
94
111
  octave: 5
95
112
  semitone: 0
113
+ articulation: :normal
114
+ accented: false
96
115
  links: {}
97
- accent: *1
116
+ check_methods:
117
+ - :ensure_positive_duration
98
118
  - !ruby/object:Music::Transcription::Note
99
119
  duration: !ruby/object:Rational
100
120
  denominator: 8
101
121
  numerator: 5
102
122
  pitches:
103
- - *3
123
+ - *4
124
+ articulation: :normal
125
+ accented: false
104
126
  links: {}
105
- accent: *1
106
- - !ruby/object:Music::Transcription::Note::Half
107
- duration: !ruby/object:Rational
108
- denominator: 2
109
- numerator: 1
127
+ check_methods:
128
+ - :ensure_positive_duration
129
+ - !ruby/object:Music::Transcription::Note
130
+ duration: *2
110
131
  pitches:
111
- - *3
132
+ - *4
133
+ articulation: :normal
134
+ accented: false
112
135
  links: {}
113
- accent: *1
114
- - !ruby/object:Music::Transcription::Note::Half
115
- duration: !ruby/object:Rational
116
- denominator: 2
117
- numerator: 1
136
+ check_methods:
137
+ - :ensure_positive_duration
138
+ - !ruby/object:Music::Transcription::Note
139
+ duration: *2
118
140
  pitches:
119
- - *4
141
+ - *5
142
+ articulation: :normal
143
+ accented: false
120
144
  links: {}
121
- accent: *1
122
- start_dynamic: *5
145
+ check_methods:
146
+ - :ensure_positive_duration
147
+ start_dynamic: 0.625
123
148
  dynamic_changes: {}
149
+ check_methods:
150
+ - :ensure_start_dynamic
151
+ - :ensure_dynamic_change_values_range
124
152
  3: !ruby/object:Music::Transcription::Part
125
153
  notes:
126
- - !ruby/object:Music::Transcription::Note::Eighth
127
- duration: !ruby/object:Rational
154
+ - !ruby/object:Music::Transcription::Note
155
+ duration: &9 !ruby/object:Rational
128
156
  denominator: 8
129
157
  numerator: 1
130
158
  pitches: []
159
+ articulation: :normal
160
+ accented: false
131
161
  links: {}
132
- accent: *1
133
- - !ruby/object:Music::Transcription::Note::Quarter
134
- duration: !ruby/object:Rational
162
+ check_methods:
163
+ - :ensure_positive_duration
164
+ - !ruby/object:Music::Transcription::Note
165
+ duration: &6 !ruby/object:Rational
135
166
  denominator: 4
136
167
  numerator: 1
137
168
  pitches:
138
169
  - !ruby/object:Music::Transcription::Pitch
139
170
  octave: 5
140
171
  semitone: 7
172
+ articulation: :normal
173
+ accented: false
141
174
  links: {}
142
- accent: *1
143
- - !ruby/object:Music::Transcription::Note::Half
144
- duration: !ruby/object:Rational
145
- denominator: 2
146
- numerator: 1
175
+ check_methods:
176
+ - :ensure_positive_duration
177
+ - !ruby/object:Music::Transcription::Note
178
+ duration: *2
147
179
  pitches:
148
- - &6 !ruby/object:Music::Transcription::Pitch
180
+ - &7 !ruby/object:Music::Transcription::Pitch
149
181
  octave: 5
150
182
  semitone: 5
183
+ articulation: :normal
184
+ accented: false
151
185
  links: {}
152
- accent: *1
153
- - !ruby/object:Music::Transcription::Note::Quarter
154
- duration: !ruby/object:Rational
155
- denominator: 4
156
- numerator: 1
186
+ check_methods:
187
+ - :ensure_positive_duration
188
+ - !ruby/object:Music::Transcription::Note
189
+ duration: *6
157
190
  pitches: []
191
+ articulation: :normal
192
+ accented: false
158
193
  links: {}
159
- accent: *1
160
- - !ruby/object:Music::Transcription::Note::Quarter
161
- duration: !ruby/object:Rational
162
- denominator: 4
163
- numerator: 1
194
+ check_methods:
195
+ - :ensure_positive_duration
196
+ - !ruby/object:Music::Transcription::Note
197
+ duration: *6
164
198
  pitches:
165
- - *6
199
+ - *7
200
+ articulation: :normal
201
+ accented: false
166
202
  links: {}
167
- accent: *1
168
- - !ruby/object:Music::Transcription::Note::Half
169
- duration: !ruby/object:Rational
170
- denominator: 2
171
- numerator: 1
203
+ check_methods:
204
+ - :ensure_positive_duration
205
+ - !ruby/object:Music::Transcription::Note
206
+ duration: *2
172
207
  pitches:
173
- - &7 !ruby/object:Music::Transcription::Pitch
208
+ - &8 !ruby/object:Music::Transcription::Pitch
174
209
  octave: 5
175
210
  semitone: 3
211
+ articulation: :normal
212
+ accented: false
176
213
  links: {}
177
- accent: *1
178
- - !ruby/object:Music::Transcription::Note::Quarter
179
- duration: !ruby/object:Rational
180
- denominator: 4
181
- numerator: 1
214
+ check_methods:
215
+ - :ensure_positive_duration
216
+ - !ruby/object:Music::Transcription::Note
217
+ duration: *6
182
218
  pitches: []
219
+ articulation: :normal
220
+ accented: false
183
221
  links: {}
184
- accent: *1
185
- - !ruby/object:Music::Transcription::Note::Quarter
186
- duration: !ruby/object:Rational
187
- denominator: 4
188
- numerator: 1
222
+ check_methods:
223
+ - :ensure_positive_duration
224
+ - !ruby/object:Music::Transcription::Note
225
+ duration: *6
189
226
  pitches:
190
- - *7
227
+ - *8
228
+ articulation: :normal
229
+ accented: false
191
230
  links: {}
192
- accent: *1
193
- - !ruby/object:Music::Transcription::Note::Half
194
- duration: !ruby/object:Rational
195
- denominator: 2
196
- numerator: 1
231
+ check_methods:
232
+ - :ensure_positive_duration
233
+ - !ruby/object:Music::Transcription::Note
234
+ duration: *2
197
235
  pitches:
198
- - *7
236
+ - *8
237
+ articulation: :normal
238
+ accented: false
199
239
  links: {}
200
- accent: *1
201
- - !ruby/object:Music::Transcription::Note::Eighth
202
- duration: !ruby/object:Rational
203
- denominator: 8
204
- numerator: 1
240
+ check_methods:
241
+ - :ensure_positive_duration
242
+ - !ruby/object:Music::Transcription::Note
243
+ duration: *9
205
244
  pitches: []
245
+ articulation: :normal
246
+ accented: false
206
247
  links: {}
207
- accent: *1
208
- - !ruby/object:Music::Transcription::Note::Half
209
- duration: !ruby/object:Rational
210
- denominator: 2
211
- numerator: 1
248
+ check_methods:
249
+ - :ensure_positive_duration
250
+ - !ruby/object:Music::Transcription::Note
251
+ duration: *2
212
252
  pitches:
213
- - *7
253
+ - *8
254
+ articulation: :normal
255
+ accented: false
214
256
  links: {}
215
- accent: *1
216
- - !ruby/object:Music::Transcription::Note::Half
217
- duration: !ruby/object:Rational
218
- denominator: 2
219
- numerator: 1
257
+ check_methods:
258
+ - :ensure_positive_duration
259
+ - !ruby/object:Music::Transcription::Note
260
+ duration: *2
220
261
  pitches:
221
- - *6
262
+ - *7
263
+ articulation: :normal
264
+ accented: false
222
265
  links: {}
223
- accent: *1
224
- start_dynamic: *5
266
+ check_methods:
267
+ - :ensure_positive_duration
268
+ start_dynamic: 0.625
225
269
  dynamic_changes: {}
270
+ check_methods:
271
+ - :ensure_start_dynamic
272
+ - :ensure_dynamic_change_values_range
226
273
  program: !ruby/object:Music::Transcription::Program
227
274
  segments:
228
275
  :segments:
@@ -234,3 +281,10 @@ program: !ruby/object:Music::Transcription::Program
234
281
  begin: 0
235
282
  end: 4.0
236
283
  excl: true
284
+ check_methods:
285
+ - :ensure_increasing_segments
286
+ - :ensure_nonnegative_segments
287
+ check_methods:
288
+ - :check_start_tempo
289
+ - :check_tempo_changes
290
+ - :check_meter_changes
@@ -3,14 +3,12 @@ module Transcription
3
3
 
4
4
  module Articulations
5
5
  NORMAL = :normal
6
+ SLUR = :slur
7
+ LEGATO = :legato
8
+ TENUTO = :tenuto
9
+ PORTATO = :portato
6
10
  STACCATO = :staccato
7
11
  STACCATISSIMO = :staccatissimo
8
- TENUTO = :tenuto
9
- ACCENTED = :accented
10
- ACCENTED_STACCATO = :accented_staccato
11
- HAMMERED = ACCENTED_STACCATO
12
- ACCENTED_TENUTO = :accented_tenuto
13
- ACCENTED_STACCATISSIMO = :accented_staccatissimo
14
12
  end
15
13
 
16
14
  end
@@ -7,32 +7,34 @@ module Transcription
7
7
  # @return [Pitch] The pitch of the note which is being connected to.
8
8
  #
9
9
  class Link
10
- attr_accessor :target_pitch
11
-
12
- def initialize target_pitch
13
- @target_pitch = target_pitch
10
+ def clone
11
+ Marshal.load(Marshal.dump(self))
14
12
  end
15
13
 
16
- def ==(other)
17
- self.class == other.class && self.target_pitch == other.target_pitch
18
- end
19
-
20
- def clone
21
- self.class.new @target_pitch.clone
14
+ class Tie < Link
15
+ def initialize; end
16
+
17
+ def ==(other)
18
+ self.class == other.class
19
+ end
22
20
  end
23
21
 
24
- [ :Slur,
25
- :Legato,
26
- :Glissando,
27
- :Portamento,
28
- ].each do |name|
29
- klass = Class.new(Link) do
30
- def initialize target_pitch
31
- super(target_pitch)
32
- end
22
+ class TargetedLink < Link
23
+ attr_accessor :target_pitch
24
+
25
+ def initialize target_pitch
26
+ @target_pitch = target_pitch
27
+ end
28
+
29
+ def ==(other)
30
+ self.class == other.class && @target_pitch == other.target_pitch
33
31
  end
34
- Link.const_set(name.to_sym, klass)
35
32
  end
33
+
34
+ class Glissando < TargetedLink; end
35
+ class Portamento < TargetedLink; end
36
+ class SlurGuide < TargetedLink; end
37
+ class LegatoGuide < TargetedLink; end
36
38
  end
37
39
 
38
40
  end
@@ -7,16 +7,16 @@ class Note
7
7
  include Validatable
8
8
 
9
9
  attr_reader :pitches, :links
10
- attr_accessor :articulation, :duration
10
+ attr_accessor :articulation, :duration, :accented
11
11
 
12
12
  DEFAULT_ARTICULATION = Articulations::NORMAL
13
13
 
14
- def initialize duration, pitches = [], links: {}, articulation: DEFAULT_ARTICULATION
15
- self.duration = duration
16
- @pitches = Set.new(pitches).sort
17
- @links = links
14
+ def initialize duration, pitches = [], articulation: DEFAULT_ARTICULATION, accented: false, links: {}
18
15
  @duration = duration
16
+ @pitches = Set.new(pitches).sort
19
17
  @articulation = articulation
18
+ @accented = accented
19
+ @links = links
20
20
 
21
21
  @check_methods = [ :ensure_positive_duration ]
22
22
  end
@@ -31,7 +31,8 @@ class Note
31
31
  return (@duration == other.duration) &&
32
32
  (self.pitches == other.pitches) &&
33
33
  (@links.to_a.sort == other.links.to_a.sort) &&
34
- (@articulation == other.articulation)
34
+ (@articulation == other.articulation) &&
35
+ (@accented == other.accented)
35
36
  end
36
37
 
37
38
  def clone
@@ -67,8 +68,8 @@ class Note
67
68
  end
68
69
 
69
70
  def self.add_note_method(name, dur)
70
- self.class.send(:define_method,name.to_sym) do |pitches = [], articulation: DEFAULT_ARTICULATION, links: {}|
71
- Note.new(dur, pitches, articulation: articulation, links: links)
71
+ self.class.send(:define_method,name.to_sym) do |pitches = [], articulation: DEFAULT_ARTICULATION, links: {}, accented: false|
72
+ Note.new(dur, pitches, articulation: articulation, links: links, accented: accented)
72
73
  end
73
74
  end
74
75
 
@@ -2,6 +2,6 @@
2
2
  module Music
3
3
  module Transcription
4
4
  # music-transcription version
5
- VERSION = "0.8.1"
5
+ VERSION = "0.9.0"
6
6
  end
7
7
  end
data/spec/link_spec.rb CHANGED
@@ -1,41 +1,98 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe Link do
4
- context '#initialize' do
3
+ describe Link::Glissando do
4
+ describe '#initialize' do
5
5
  it 'should assign the given pitch to :target_pitch' do
6
- Link.new(C2).target_pitch.should eq(C2)
6
+ Link::Glissando.new(C2).target_pitch.should eq(C2)
7
7
  end
8
8
  end
9
+
10
+ describe '#==' do
11
+ it 'should return true if two links have the same target pitch' do
12
+ Link::Glissando.new(C2).should eq(Link::Glissando.new(C2))
13
+ end
9
14
 
15
+ it 'should return false if two links do not have the same target pitch' do
16
+ Link::Glissando.new(C2).should_not eq(Link::Glissando.new(F5))
17
+ end
18
+
19
+ it 'should return false if the link type is different' do
20
+ Link::Glissando.new(C2).should_not eq(Link::Portamento.new(D2))
21
+ end
22
+ end
23
+
24
+ describe '#clone' do
25
+ it 'should return a link equal to original' do
26
+ l = Link::Glissando.new(C4)
27
+ l.clone.should eq l
28
+ end
29
+ end
30
+
31
+ describe '#to_yaml' do
32
+ it 'should produce YAML that can be loaded' do
33
+ l = Link::Glissando.new(C5)
34
+ YAML.load(l.to_yaml).should eq l
35
+ end
36
+ end
37
+ end
38
+
39
+ describe Link::Portamento do
40
+ describe '#initialize' do
41
+ it 'should assign the given pitch to :target_pitch' do
42
+ Link::Portamento.new(C2).target_pitch.should eq(C2)
43
+ end
44
+ end
45
+
10
46
  describe '#==' do
11
47
  it 'should return true if two links have the same target pitch' do
12
- Link.new(C2).should eq(Link.new(C2))
48
+ Link::Portamento.new(C2).should eq(Link::Portamento.new(C2))
13
49
  end
14
50
 
15
51
  it 'should return false if two links do not have the same target pitch' do
16
- Link.new(C2).should_not eq(Link.new(F5))
52
+ Link::Portamento.new(C2).should_not eq(Link::Portamento.new(F5))
17
53
  end
18
54
 
19
55
  it 'should return false if the link type is different' do
20
- Link::Slur.new(C2).should_not eq(Link::Legato.new(D2))
56
+ Link::Portamento.new(C2).should_not eq(Link::Glissando.new(D2))
21
57
  end
22
58
  end
23
59
 
24
60
  describe '#clone' do
25
- it 'should return a link with the same target pitch' do
26
- l = Link.new(C4)
27
- l.clone.target_pitch.should eq(C4)
61
+ it 'should return a link equal to original' do
62
+ l = Link::Portamento.new(C4)
63
+ l.clone.should eq l
64
+ end
65
+ end
66
+
67
+ describe '#to_yaml' do
68
+ it 'should produce YAML that can be loaded' do
69
+ l = Link::Portamento.new(C5)
70
+ YAML.load(l.to_yaml).should eq l
71
+ end
72
+ end
73
+ end
74
+
75
+ describe Link::Tie do
76
+ describe '#==' do
77
+ it 'should return true if another Tie object is given' do
78
+ Link::Tie.new.should eq(Link::Tie.new)
28
79
  end
29
80
 
30
- it 'should return a link with the same class' do
31
- l = Link::Slur.new(Eb2)
32
- l.clone.class.should eq(Link::Slur)
81
+ it 'should return false if a non-Tie object is given' do
82
+ Link::Tie.new.should_not eq(Link::Portamento.new(C2))
83
+ end
84
+ end
85
+
86
+ describe '#clone' do
87
+ it 'should return a link equal to original' do
88
+ l = Link::Tie.new
89
+ l.clone.should eq l
33
90
  end
34
91
  end
35
92
 
36
93
  describe '#to_yaml' do
37
94
  it 'should produce YAML that can be loaded' do
38
- l = Link::Slur.new(C5)
95
+ l = Link::Tie.new
39
96
  YAML.load(l.to_yaml).should eq l
40
97
  end
41
98
  end
data/spec/note_spec.rb CHANGED
@@ -7,13 +7,23 @@ describe Note do
7
7
 
8
8
  describe '.new' do
9
9
  it 'should assign :duration that is given during construction' do
10
- note = Note.new 2
11
- note.duration.should eq(2)
10
+ Note.new(2).duration.should eq(2)
11
+ end
12
+
13
+ it "should assign :articulation to Note::DEFAULT_ARTICULATION if not given" do
14
+ Note.new(2).articulation.should eq(Note::DEFAULT_ARTICULATION)
12
15
  end
13
16
 
14
17
  it "should assign :articulation parameter if given during construction" do
15
- note = Note.new 2, articulation: STACCATO
16
- note.articulation.should eq(STACCATO)
18
+ Note.new(2, articulation: STACCATO).articulation.should eq(STACCATO)
19
+ end
20
+
21
+ it 'should assign :accented to false if not given' do
22
+ Note.new(2).accented.should be false
23
+ end
24
+
25
+ it 'should assign :accented if given' do
26
+ Note.new(2, accented: true).accented.should be true
17
27
  end
18
28
 
19
29
  it 'should have no pitches if not given' do
@@ -57,7 +67,7 @@ describe Note do
57
67
  describe '#transpose!' do
58
68
  context 'given pitch diff' do
59
69
  before(:all) do
60
- @note = Note::quarter([C2,F2], links:{C2=>Link::Slur.new(D2)})
70
+ @note = Note::quarter([C2,F2], links:{C2=>Link::Glissando.new(D2)})
61
71
  @diff = Pitch.new(semitone: 4)
62
72
  @note.transpose! @diff
63
73
  end
@@ -116,7 +126,7 @@ describe Note do
116
126
  n = Note.new(1,[C2], articulation: STACCATO)
117
127
  YAML.load(n.to_yaml).should eq n
118
128
 
119
- n = Note.new(1,[E2], links: {E2 => Link::Legato.new(F2)})
129
+ n = Note.new(1,[E2], links: {E2 => Link::Portamento.new(F2)})
120
130
  YAML.load(n.to_yaml).should eq n
121
131
  end
122
132
  end