musicality 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +7 -1
  3. data/lib/musicality.rb +0 -1
  4. data/lib/musicality/composition/dsl/score_methods.rb +5 -6
  5. data/lib/musicality/notation/conversion/score_conversion.rb +3 -34
  6. data/lib/musicality/notation/conversion/score_converter.rb +6 -17
  7. data/lib/musicality/notation/model/mark.rb +0 -12
  8. data/lib/musicality/notation/model/marks.rb +0 -3
  9. data/lib/musicality/notation/model/note.rb +0 -8
  10. data/lib/musicality/notation/model/score.rb +14 -35
  11. data/lib/musicality/notation/model/symbols.rb +0 -2
  12. data/lib/musicality/notation/parsing/mark_parsing.rb +0 -58
  13. data/lib/musicality/notation/parsing/mark_parsing.treetop +0 -12
  14. data/lib/musicality/notation/parsing/note_node.rb +22 -27
  15. data/lib/musicality/notation/parsing/note_parsing.rb +59 -189
  16. data/lib/musicality/notation/parsing/note_parsing.treetop +2 -9
  17. data/lib/musicality/performance/conversion/note_sequence_extractor.rb +1 -20
  18. data/lib/musicality/performance/model/note_sequence.rb +1 -1
  19. data/lib/musicality/printing/lilypond/note_engraving.rb +3 -3
  20. data/lib/musicality/printing/lilypond/part_engraver.rb +16 -12
  21. data/lib/musicality/project/create_tasks.rb +1 -1
  22. data/lib/musicality/project/load_config.rb +16 -1
  23. data/lib/musicality/project/project.rb +2 -2
  24. data/lib/musicality/version.rb +1 -1
  25. data/musicality.gemspec +0 -1
  26. data/spec/composition/dsl/score_methods_spec.rb +73 -0
  27. data/spec/notation/conversion/score_conversion_spec.rb +0 -100
  28. data/spec/notation/conversion/score_converter_spec.rb +33 -33
  29. data/spec/notation/model/note_spec.rb +2 -2
  30. data/spec/notation/model/score_spec.rb +17 -87
  31. data/spec/notation/parsing/note_node_spec.rb +2 -2
  32. data/spec/notation/parsing/note_parsing_spec.rb +3 -3
  33. data/spec/performance/conversion/note_sequence_extractor_spec.rb +23 -0
  34. data/spec/performance/model/note_sequence_spec.rb +50 -6
  35. metadata +4 -19
  36. data/lib/musicality/notation/conversion/measure_note_map.rb +0 -40
  37. data/spec/notation/conversion/measure_note_map_spec.rb +0 -73
@@ -88,9 +88,9 @@ describe Parsing::NoteNode do
88
88
  end
89
89
 
90
90
  context 'with marks' do
91
- [[BEGIN_SLUR],[BEGIN_SLUR, BEGIN_TRIPLET],[BEGIN_TRIPLET]].each do |begin_marks|
91
+ [[BEGIN_SLUR],[]].each do |begin_marks|
92
92
  begin_marks_str = begin_marks.map {|m| m.to_s}.join
93
- [[END_SLUR],[END_SLUR, END_TRIPLET],[END_TRIPLET]].each do |end_marks|
93
+ [[END_SLUR],[]].each do |end_marks|
94
94
  end_marks_str = end_marks.map {|m| m.to_s}.join
95
95
  describe '#to_note' do
96
96
  it 'should produce a Note with marks set correctly' do
@@ -12,7 +12,7 @@ describe Parsing::NoteParser do
12
12
  'with articulation' => ['/4C2.',"5/3Db3,Bb2,E5.",'/2D3,F4_'],
13
13
  'with accent' => ['/4C2','3/2Db3,Bb4'],
14
14
  'with links' => ['/2C2~','/2C2:D2','/4D4:E4,G4;A5.'],
15
- 'with marks' => ['(3/4Bb3]', '[/2F3,G3)', '[(2/4C3', '([1B2', '/3B2,C2)]', '2/3D4])'],
15
+ 'with marks' => ['(3/4Bb3', '/2F3,G3)', '(2/4C3', '(1B2', '/3B2,C2)', '(2/3D4)'],
16
16
  'with single pitch + articulation + link + accent' => [
17
17
  '(3/4D2~','5/8F2;G2.','/8Db4:Db5','/3G4;B4_'],
18
18
  'with multiple pitches + articulation + links + accent' => [
@@ -23,8 +23,8 @@ describe Parsing::NoteParser do
23
23
  'duration + accent + link' => ['1/4;','/2:','2/3~'],
24
24
  'single pith with bad letter' => ['5/3Hb3'],
25
25
  'single pitch without octave' => ['/33E)'],
26
- 'begins marks at the end' => ['1Bb3(', '2Bb3['],
27
- 'end marks at the beginning ' => [']1B5', ')3C3']
26
+ 'begins marks at the end' => ['1Bb3('],
27
+ 'end marks at the beginning ' => [')3C3']
28
28
  }
29
29
 
30
30
  valid_cases.each do |descr, strs|
@@ -221,5 +221,28 @@ describe NoteSequenceExtractor do
221
221
  @seqs[0].duration.should be <= (@notes[0].duration + @notes[1].duration)
222
222
  end
223
223
  end
224
+
225
+ context 'three notes with single pitch, tie between first two, portamento between last two' do
226
+ before :all do
227
+ @notes = "/8Eb4~ /8Eb4:C5 3/4C5".to_notes
228
+ @seqs = NoteSequenceExtractor.new(@notes).extract_sequences
229
+ end
230
+
231
+ it 'should produce a single sequence' do
232
+ expect(@seqs.size).to eq(1)
233
+ end
234
+
235
+ it 'should have same full duration as the notes together' do
236
+ expected_dur = @notes.map {|n| n.duration }.inject(0,:+)
237
+ seq = @seqs.first
238
+ expect(seq.full_duration).to eq(expected_dur)
239
+ end
240
+
241
+ it 'should have duration less than the notes together' do
242
+ max_dur = @notes.map {|n| n.duration }.inject(0,:+)
243
+ seq = @seqs.first
244
+ expect(seq.duration).to be < max_dur
245
+ end
246
+ end
224
247
  end
225
248
  end
@@ -15,11 +15,10 @@ describe NoteSequence do
15
15
  end
16
16
 
17
17
  before :all do
18
- @element_arys = [
19
- [ NoteSequence::Element.new(0.5, B2, Attack::NONE) ],
20
- [ NoteSequence::Element.new(0.5, A2, Attack::NORMAL),
21
- NoteSequence::Element.new(0.5, B2, Attack::NONE),
22
- NoteSequence::Element.new(0.5, B2, Attack::ACCENT) ],
18
+ @element_ary = [
19
+ NoteSequence::Element.new(0.5, A2, Attack::NORMAL),
20
+ NoteSequence::Element.new(0.5, B2, Attack::NONE),
21
+ NoteSequence::Element.new(0.5, B2, Attack::ACCENT)
23
22
  ]
24
23
  @offsets = [ 0, -5, 7, 77 ]
25
24
  end
@@ -37,7 +36,7 @@ describe NoteSequence do
37
36
  context 'with at least one element' do
38
37
  it 'should return offsets of each element' do
39
38
  @offsets.each do |offset|
40
- @element_arys.each do |els|
39
+ @element_ary.combination(@element_ary.size-1).each do |els|
41
40
  seq = NoteSequence.new(offset, Separation::NORMAL, els)
42
41
  offsets = seq.offsets
43
42
  expect(offsets.size).to eq(els.size)
@@ -51,4 +50,49 @@ describe NoteSequence do
51
50
  end
52
51
  end
53
52
  end
53
+
54
+ describe '#stop' do
55
+ context 'no elements' do
56
+ it 'should raise RuntimeError' do
57
+ ns = NoteSequence.new(1.2, Separation::NORMAL, [])
58
+ expect { ns.stop }.to raise_error(RuntimeError)
59
+ end
60
+ end
61
+ end
62
+
63
+ describe '#duration' do
64
+ context 'no elements' do
65
+ it 'should raise RuntimeError' do
66
+ ns = NoteSequence.new(1.2, Separation::NORMAL, [])
67
+ expect { ns.duration }.to raise_error(RuntimeError)
68
+ end
69
+ end
70
+ end
71
+
72
+ describe '#full_duration' do
73
+ context 'no elements' do
74
+ it 'should return 0' do
75
+ ns = NoteSequence.new(1.2, Separation::NORMAL, [])
76
+ expect(ns.full_duration).to eq(0)
77
+ end
78
+ end
79
+
80
+ context 'with one element' do
81
+ it 'should return element duration' do
82
+ @element_ary.each do |el|
83
+ ns = NoteSequence.new(1.2, Separation::NORMAL, [el])
84
+ expect(ns.full_duration).to eq(el.duration)
85
+ end
86
+ end
87
+ end
88
+
89
+ context 'with multiple elements' do
90
+ it 'should return the sum of element durations' do
91
+ els = [ NoteSequence::Element.new(0.5, D4, Attack::NORMAL),
92
+ NoteSequence::Element.new(0.25, F3, Attack::TENUTO) ]
93
+ ns = NoteSequence.new(1.2, Separation::NORMAL, els)
94
+ expect(ns.full_duration).to eq(0.75)
95
+ end
96
+ end
97
+ end
54
98
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: musicality
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Tunnell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-01 00:00:00.000000000 Z
11
+ date: 2016-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -108,20 +108,6 @@ dependencies:
108
108
  - - ~>
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.5'
111
- - !ruby/object:Gem::Dependency
112
- name: ruby-osc
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ~>
116
- - !ruby/object:Gem::Version
117
- version: '0.4'
118
- type: :runtime
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ~>
123
- - !ruby/object:Gem::Version
124
- version: '0.4'
125
111
  description: "The library is based around an abstract representation for music notation.
126
112
  \\\n From here, functions are built up to make composing
127
113
  elaborate pieces in this notation representation more manageable. \\\n Finally,
@@ -175,7 +161,6 @@ files:
175
161
  - lib/musicality/composition/util/repeating_sequence.rb
176
162
  - lib/musicality/errors.rb
177
163
  - lib/musicality/notation/conversion/change_conversion.rb
178
- - lib/musicality/notation/conversion/measure_note_map.rb
179
164
  - lib/musicality/notation/conversion/note_time_converter.rb
180
165
  - lib/musicality/notation/conversion/score_conversion.rb
181
166
  - lib/musicality/notation/conversion/score_converter.rb
@@ -288,6 +273,7 @@ files:
288
273
  - lib/musicality/version.rb
289
274
  - musicality.gemspec
290
275
  - spec/composition/convenience_methods_spec.rb
276
+ - spec/composition/dsl/score_methods_spec.rb
291
277
  - spec/composition/generation/random_rhythm_generator_spec.rb
292
278
  - spec/composition/model/pitch_class_spec.rb
293
279
  - spec/composition/model/pitch_classes_spec.rb
@@ -301,7 +287,6 @@ files:
301
287
  - spec/composition/util/repeating_sequence_spec.rb
302
288
  - spec/musicality_spec.rb
303
289
  - spec/notation/conversion/change_conversion_spec.rb
304
- - spec/notation/conversion/measure_note_map_spec.rb
305
290
  - spec/notation/conversion/note_time_converter_spec.rb
306
291
  - spec/notation/conversion/score_conversion_spec.rb
307
292
  - spec/notation/conversion/score_converter_spec.rb
@@ -374,6 +359,7 @@ specification_version: 4
374
359
  summary: Music notation, composition, and performance
375
360
  test_files:
376
361
  - spec/composition/convenience_methods_spec.rb
362
+ - spec/composition/dsl/score_methods_spec.rb
377
363
  - spec/composition/generation/random_rhythm_generator_spec.rb
378
364
  - spec/composition/model/pitch_class_spec.rb
379
365
  - spec/composition/model/pitch_classes_spec.rb
@@ -387,7 +373,6 @@ test_files:
387
373
  - spec/composition/util/repeating_sequence_spec.rb
388
374
  - spec/musicality_spec.rb
389
375
  - spec/notation/conversion/change_conversion_spec.rb
390
- - spec/notation/conversion/measure_note_map_spec.rb
391
376
  - spec/notation/conversion/note_time_converter_spec.rb
392
377
  - spec/notation/conversion/score_conversion_spec.rb
393
378
  - spec/notation/conversion/score_converter_spec.rb
@@ -1,40 +0,0 @@
1
- module Musicality
2
-
3
- module Conversion
4
- # Convert offsets from measure-based to note-based.
5
- # @param [Array] measure_offsets Measure offsets to be converted
6
- # @param [Hash] measure_durations Map measure durations to measure offsets where the duration takes effect.
7
- # @raise [NonZeroError] if first measure duration is not mapped to offset 0
8
- def self.measure_note_map measure_offsets, measure_durations
9
- mnoff_map = {}
10
- moffs = measure_offsets.uniq.sort
11
- mdurs = measure_durations.sort
12
- cur_noff = 0.to_r
13
- j = 0 # next measure offset to be converted
14
-
15
- if mdurs[0][0] != 0
16
- raise NonZeroError, "measure offset of 1st measure duration must be 0, not #{mdurs[0][0]}"
17
- end
18
-
19
- (0...mdurs.size).each do |i|
20
- cur_moff, cur_mdur = mdurs[i]
21
- if i < (mdurs.size - 1)
22
- next_moff = mdurs[i+1][0]
23
- else
24
- next_moff = Float::INFINITY
25
- end
26
-
27
- while(j < moffs.size && moffs[j] <= next_moff) do
28
- moff = moffs[j]
29
- mnoff_map[moff] = cur_noff + (moff - cur_moff)*cur_mdur
30
- j += 1
31
- end
32
-
33
- cur_noff += (next_moff - cur_moff) * cur_mdur
34
- end
35
-
36
- return mnoff_map
37
- end
38
- end
39
-
40
- end
@@ -1,73 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- describe 'Conversion.measure_note_map' do
4
- before :all do
5
- mdurs = Hash[ [[0, (3/4)], [1, (1/2)], [3, (3/4)]] ]
6
- @moffs = [ 0, 1, 3, 4, 5, 6, 7, 8, 11, 14, 17, 20, (45/2)]
7
- @mnoff_map = Conversion.measure_note_map(@moffs,mdurs)
8
- end
9
-
10
- it 'should return a Hash' do
11
- @mnoff_map.should be_a Hash
12
- end
13
-
14
- it 'should have same size as array returned by #measure_offsets' do
15
- @mnoff_map.size.should eq(@moffs.size)
16
- end
17
-
18
- it 'should have a key for each offset in the array returned by #measure_offsets' do
19
- @mnoff_map.keys.sort.should eq(@moffs)
20
- end
21
-
22
- context 'single measure duration at 0' do
23
- it 'should mutiply all measure offsets by start measure duration' do
24
- [TWO_FOUR,SIX_EIGHT,FOUR_FOUR,THREE_FOUR].each do |meter|
25
- mdur = meter.measure_duration
26
- mdurs = { 0 => mdur }
27
- tgt = @moffs.map {|moff| moff * mdur}
28
- Conversion.measure_note_map(@moffs,mdurs).values.sort.should eq(tgt)
29
- end
30
- end
31
- end
32
-
33
- context '1 meter change' do
34
- before :all do
35
- @first_mc_off = 3
36
- @start_meter = THREE_FOUR
37
- @new_meter = TWO_FOUR
38
- @score = Score::Tempo.new(@start_meter, 120,
39
- meter_changes: { @first_mc_off => Change::Immediate.new(@new_meter) },
40
- tempo_changes: {
41
- "1/2".to_r => Change::Gradual.linear(100,1),
42
- 2 => Change::Immediate.new(120),
43
- 3 => Change::Immediate.new(100),
44
- 3.1 => Change::Gradual.linear(100,1),
45
- 5 => Change::Immediate.new(120),
46
- 6 => Change::Immediate.new(100),
47
- }
48
- )
49
- @moffs = @score.measure_offsets
50
- @mdurs = @score.measure_durations
51
- @mnoff_map = Conversion.measure_note_map(@moffs,@mdurs)
52
- end
53
-
54
- it 'should mutiply all measure offsets that occur on or before 1st meter change offset by start measure duration' do
55
- moffs = @moffs.select{ |x| x <= @first_mc_off }
56
- tgt = moffs.map do |moff|
57
- moff * @start_meter.measure_duration
58
- end.sort
59
- src = @mnoff_map.select {|k,v| k <= @first_mc_off }
60
- src.values.sort.should eq(tgt)
61
- end
62
-
63
- it 'should, for any measure offsets occurring after 1st meter change offset, add 1st_meter_change_offset * 1st_measure_duration to \
64
- new_measure_duration * (offset - 1st_meter_change_offset)' do
65
- moffs = @moffs.select{ |x| x > @first_mc_off }
66
- tgt = moffs.map do |moff|
67
- @first_mc_off * @start_meter.measure_duration + (moff - @first_mc_off) * @new_meter.measure_duration
68
- end.sort
69
- src = @mnoff_map.select {|k,v| k > @first_mc_off }
70
- src.values.sort.should eq(tgt)
71
- end
72
- end
73
- end