musicality 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +47 -0
  8. data/Rakefile +65 -0
  9. data/bin/midify +78 -0
  10. data/examples/hip.rb +32 -0
  11. data/examples/missed_connection.rb +26 -0
  12. data/examples/song1.rb +33 -0
  13. data/examples/song2.rb +32 -0
  14. data/lib/musicality/errors.rb +9 -0
  15. data/lib/musicality/notation/conversion/change_conversion.rb +19 -0
  16. data/lib/musicality/notation/conversion/measure_note_map.rb +40 -0
  17. data/lib/musicality/notation/conversion/measured_score_conversion.rb +70 -0
  18. data/lib/musicality/notation/conversion/measured_score_converter.rb +95 -0
  19. data/lib/musicality/notation/conversion/note_time_converter.rb +68 -0
  20. data/lib/musicality/notation/conversion/tempo_conversion.rb +25 -0
  21. data/lib/musicality/notation/conversion/unmeasured_score_conversion.rb +47 -0
  22. data/lib/musicality/notation/conversion/unmeasured_score_converter.rb +64 -0
  23. data/lib/musicality/notation/model/articulations.rb +13 -0
  24. data/lib/musicality/notation/model/change.rb +62 -0
  25. data/lib/musicality/notation/model/dynamics.rb +12 -0
  26. data/lib/musicality/notation/model/link.rb +73 -0
  27. data/lib/musicality/notation/model/meter.rb +54 -0
  28. data/lib/musicality/notation/model/meters.rb +9 -0
  29. data/lib/musicality/notation/model/note.rb +120 -0
  30. data/lib/musicality/notation/model/part.rb +54 -0
  31. data/lib/musicality/notation/model/pitch.rb +163 -0
  32. data/lib/musicality/notation/model/pitches.rb +21 -0
  33. data/lib/musicality/notation/model/program.rb +53 -0
  34. data/lib/musicality/notation/model/score.rb +132 -0
  35. data/lib/musicality/notation/packing/change_packing.rb +46 -0
  36. data/lib/musicality/notation/packing/part_packing.rb +31 -0
  37. data/lib/musicality/notation/packing/program_packing.rb +16 -0
  38. data/lib/musicality/notation/packing/score_packing.rb +108 -0
  39. data/lib/musicality/notation/parsing/articulation_parsing.rb +264 -0
  40. data/lib/musicality/notation/parsing/articulation_parsing.treetop +59 -0
  41. data/lib/musicality/notation/parsing/convenience_methods.rb +74 -0
  42. data/lib/musicality/notation/parsing/duration_nodes.rb +21 -0
  43. data/lib/musicality/notation/parsing/duration_parsing.rb +205 -0
  44. data/lib/musicality/notation/parsing/duration_parsing.treetop +25 -0
  45. data/lib/musicality/notation/parsing/link_nodes.rb +35 -0
  46. data/lib/musicality/notation/parsing/link_parsing.rb +270 -0
  47. data/lib/musicality/notation/parsing/link_parsing.treetop +33 -0
  48. data/lib/musicality/notation/parsing/meter_parsing.rb +190 -0
  49. data/lib/musicality/notation/parsing/meter_parsing.treetop +29 -0
  50. data/lib/musicality/notation/parsing/note_node.rb +40 -0
  51. data/lib/musicality/notation/parsing/note_parsing.rb +229 -0
  52. data/lib/musicality/notation/parsing/note_parsing.treetop +28 -0
  53. data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.rb +289 -0
  54. data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.treetop +29 -0
  55. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +64 -0
  56. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.treetop +17 -0
  57. data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.rb +86 -0
  58. data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.treetop +20 -0
  59. data/lib/musicality/notation/parsing/numbers/positive_float_parsing.rb +503 -0
  60. data/lib/musicality/notation/parsing/numbers/positive_float_parsing.treetop +33 -0
  61. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.rb +95 -0
  62. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.treetop +19 -0
  63. data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.rb +84 -0
  64. data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.treetop +19 -0
  65. data/lib/musicality/notation/parsing/parseable.rb +30 -0
  66. data/lib/musicality/notation/parsing/pitch_node.rb +23 -0
  67. data/lib/musicality/notation/parsing/pitch_parsing.rb +448 -0
  68. data/lib/musicality/notation/parsing/pitch_parsing.treetop +52 -0
  69. data/lib/musicality/notation/parsing/segment_parsing.rb +141 -0
  70. data/lib/musicality/notation/parsing/segment_parsing.treetop +23 -0
  71. data/lib/musicality/notation/util/interpolation.rb +16 -0
  72. data/lib/musicality/notation/util/piecewise_function.rb +122 -0
  73. data/lib/musicality/notation/util/value_computer.rb +170 -0
  74. data/lib/musicality/performance/conversion/glissando_converter.rb +34 -0
  75. data/lib/musicality/performance/conversion/note_sequence_extractor.rb +98 -0
  76. data/lib/musicality/performance/conversion/portamento_converter.rb +24 -0
  77. data/lib/musicality/performance/conversion/score_collator.rb +126 -0
  78. data/lib/musicality/performance/midi/midi_events.rb +34 -0
  79. data/lib/musicality/performance/midi/midi_util.rb +31 -0
  80. data/lib/musicality/performance/midi/part_sequencer.rb +123 -0
  81. data/lib/musicality/performance/midi/score_sequencer.rb +45 -0
  82. data/lib/musicality/performance/model/note_attacks.rb +19 -0
  83. data/lib/musicality/performance/model/note_sequence.rb +111 -0
  84. data/lib/musicality/performance/util/note_linker.rb +28 -0
  85. data/lib/musicality/performance/util/optimization.rb +31 -0
  86. data/lib/musicality/validatable.rb +38 -0
  87. data/lib/musicality/version.rb +3 -0
  88. data/lib/musicality.rb +81 -0
  89. data/musicality.gemspec +30 -0
  90. data/spec/musicality_spec.rb +7 -0
  91. data/spec/notation/conversion/change_conversion_spec.rb +40 -0
  92. data/spec/notation/conversion/measure_note_map_spec.rb +73 -0
  93. data/spec/notation/conversion/measured_score_conversion_spec.rb +141 -0
  94. data/spec/notation/conversion/measured_score_converter_spec.rb +329 -0
  95. data/spec/notation/conversion/note_time_converter_spec.rb +81 -0
  96. data/spec/notation/conversion/tempo_conversion_spec.rb +40 -0
  97. data/spec/notation/conversion/unmeasured_score_conversion_spec.rb +71 -0
  98. data/spec/notation/conversion/unmeasured_score_converter_spec.rb +116 -0
  99. data/spec/notation/model/change_spec.rb +90 -0
  100. data/spec/notation/model/link_spec.rb +83 -0
  101. data/spec/notation/model/meter_spec.rb +97 -0
  102. data/spec/notation/model/note_spec.rb +183 -0
  103. data/spec/notation/model/part_spec.rb +69 -0
  104. data/spec/notation/model/pitch_spec.rb +180 -0
  105. data/spec/notation/model/program_spec.rb +50 -0
  106. data/spec/notation/model/score_spec.rb +211 -0
  107. data/spec/notation/packing/change_packing_spec.rb +153 -0
  108. data/spec/notation/packing/part_packing_spec.rb +66 -0
  109. data/spec/notation/packing/program_packing_spec.rb +33 -0
  110. data/spec/notation/packing/score_packing_spec.rb +301 -0
  111. data/spec/notation/parsing/articulation_parsing_spec.rb +23 -0
  112. data/spec/notation/parsing/convenience_methods_spec.rb +99 -0
  113. data/spec/notation/parsing/duration_nodes_spec.rb +83 -0
  114. data/spec/notation/parsing/duration_parsing_spec.rb +70 -0
  115. data/spec/notation/parsing/link_nodes_spec.rb +30 -0
  116. data/spec/notation/parsing/link_parsing_spec.rb +13 -0
  117. data/spec/notation/parsing/meter_parsing_spec.rb +23 -0
  118. data/spec/notation/parsing/note_node_spec.rb +87 -0
  119. data/spec/notation/parsing/note_parsing_spec.rb +46 -0
  120. data/spec/notation/parsing/numbers/nonnegative_float_spec.rb +28 -0
  121. data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +11 -0
  122. data/spec/notation/parsing/numbers/nonnegative_rational_spec.rb +11 -0
  123. data/spec/notation/parsing/numbers/positive_float_spec.rb +28 -0
  124. data/spec/notation/parsing/numbers/positive_integer_spec.rb +28 -0
  125. data/spec/notation/parsing/numbers/positive_rational_spec.rb +28 -0
  126. data/spec/notation/parsing/pitch_node_spec.rb +38 -0
  127. data/spec/notation/parsing/pitch_parsing_spec.rb +14 -0
  128. data/spec/notation/parsing/segment_parsing_spec.rb +27 -0
  129. data/spec/notation/util/value_computer_spec.rb +146 -0
  130. data/spec/performance/conversion/glissando_converter_spec.rb +93 -0
  131. data/spec/performance/conversion/note_sequence_extractor_spec.rb +230 -0
  132. data/spec/performance/conversion/portamento_converter_spec.rb +91 -0
  133. data/spec/performance/conversion/score_collator_spec.rb +183 -0
  134. data/spec/performance/midi/midi_util_spec.rb +110 -0
  135. data/spec/performance/midi/part_sequencer_spec.rb +40 -0
  136. data/spec/performance/midi/score_sequencer_spec.rb +50 -0
  137. data/spec/performance/model/note_sequence_spec.rb +147 -0
  138. data/spec/performance/util/note_linker_spec.rb +68 -0
  139. data/spec/performance/util/optimization_spec.rb +73 -0
  140. data/spec/spec_helper.rb +43 -0
  141. metadata +323 -0
@@ -0,0 +1,147 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe NoteSequence do
4
+ describe '#initialize' do
5
+ it 'should assign given start, stop, pitches and attacks' do
6
+ start, stop = 15, 22
7
+ pitches = { 15 => F2, 16 => G2, 16.1 => Ab2, 21.99 => C2 }
8
+ attacks = { 15 => ACCENTED, 17 => UNACCENTED, 18 => ACCENTED }
9
+ seq = NoteSequence.new(start,stop,pitches,attacks)
10
+ seq.start.should eq(start)
11
+ seq.stop.should eq(stop)
12
+ seq.pitches.should eq(pitches)
13
+ seq.attacks.should eq(attacks)
14
+ end
15
+
16
+ it 'should raise ArgumentError if start offset >= stop offset' do
17
+ expect do
18
+ NoteSequence.new(20,19, { 20 => C4 }, { 20 => UNACCENTED })
19
+ end.to raise_error(ArgumentError)
20
+ end
21
+
22
+ it 'should raise ArgumentError if no pitches are given' do
23
+ expect do
24
+ NoteSequence.new(20,21, {}, { 20 => UNACCENTED })
25
+ end.to raise_error(ArgumentError)
26
+ end
27
+
28
+ it 'should raise ArgumentError if no attacks are given' do
29
+ expect do
30
+ NoteSequence.new(20,21, { 20 => C4 }, {})
31
+ end.to raise_error(ArgumentError)
32
+ end
33
+
34
+ it 'should raise ArgumentError if no start pitch is given' do
35
+ expect do
36
+ NoteSequence.new(20,21, { 20.1 => C4 }, { 20 => UNACCENTED })
37
+ end.to raise_error(ArgumentError)
38
+ end
39
+
40
+ it 'should raise ArgumentError if no start attack is given' do
41
+ expect do
42
+ NoteSequence.new(20,21, { 20 => C4 }, { 20.1 => UNACCENTED })
43
+ end.to raise_error(ArgumentError)
44
+ end
45
+
46
+ it 'should raise ArgumentError if any pitch offset is not between start..stop' do
47
+ expect do
48
+ NoteSequence.new(20,21, { 20 => C4, 21.01 => D4 }, { 20 => UNACCENTED })
49
+ end.to raise_error(ArgumentError)
50
+
51
+ expect do
52
+ NoteSequence.new(20,21, { 20 => C4, 19.99 => D4 }, { 20 => UNACCENTED })
53
+ end.to raise_error(ArgumentError)
54
+ end
55
+
56
+ it 'should raise ArgumentError if any attack offset is not between start..stop' do
57
+ expect do
58
+ NoteSequence.new(20,21, { 20 => C4 }, { 20 => UNACCENTED, 21.01 => ACCENTED })
59
+ end.to raise_error(ArgumentError)
60
+
61
+ expect do
62
+ NoteSequence.new(20,21, { 20 => C4 }, { 20 => UNACCENTED, 19.99 => ACCENTED })
63
+ end.to raise_error(ArgumentError)
64
+ end
65
+ end
66
+
67
+ describe '.from_elements' do
68
+ it 'should raise ArgumentError if no elements are given' do
69
+ expect { NoteSequence.from_elements(2,[]) }.to raise_error(ArgumentError)
70
+ end
71
+
72
+ context 'single element' do
73
+ before :all do
74
+ @offset = 0
75
+ @el = FinalElement.new(2, C2, true, NORMAL)
76
+ @seq = NoteSequence.from_elements(@offset, [ @el ])
77
+
78
+ end
79
+
80
+ it 'should return a NoteSequence' do
81
+ @seq.should be_a NoteSequence
82
+ end
83
+
84
+ it 'should set start offset to given offset' do
85
+ @seq.start.should eq(@offset)
86
+ end
87
+
88
+ it 'should set stop offset no more than "duration of first element" away from start' do
89
+ (@seq.stop - @seq.start).should be <= @el.duration
90
+ end
91
+
92
+ it 'should set start pitch according to element pitch' do
93
+ @seq.pitches[@seq.start].should eq(@el.pitch)
94
+ end
95
+
96
+ it 'should set start attack according to element.accented' do
97
+ @seq.attacks[@seq.start].accented?.should eq(@el.accented)
98
+ end
99
+ end
100
+
101
+ context 'multi-element' do
102
+ before :all do
103
+ @offset = 1.5
104
+ @els = [
105
+ SlurredElement.new(1.0, A2, false),
106
+ LegatoElement.new(1.1, B2, false),
107
+ SlurredElement.new(1.2, C2, false),
108
+ LegatoElement.new(1.3, B2, false),
109
+ FinalElement.new(1.4, A2, false, NORMAL)
110
+ ]
111
+ @seq = NoteSequence.from_elements(@offset, @els)
112
+ end
113
+
114
+ it 'should place pitches according to element duration' do
115
+ offset = @offset
116
+ @els.each do |el|
117
+ @seq.pitches.should have_key(offset)
118
+ @seq.pitches[offset].should eq(el.pitch)
119
+ offset += el.duration
120
+ end
121
+ end
122
+
123
+ it 'should place attacks at beginning and following non-slur elements' do
124
+ @seq.attacks.should have_key(@offset)
125
+
126
+ offset = @offset + @els.first.duration
127
+ (1...@els.size).each do |i|
128
+ unless @els[i-1].slurred?
129
+ @seq.attacks.should have_key(offset)
130
+ end
131
+ offset += @els[i].duration
132
+ end
133
+ end
134
+ end
135
+
136
+ context 'elements contain slur to same pitch' do
137
+ it 'should not add same pitch nor attack for second element' do
138
+ els = [ SlurredElement.new(1, C4, false), FinalElement.new(1, C4, false, NORMAL) ]
139
+ seq = NoteSequence.from_elements(0, els)
140
+ seq.pitches.should have_key(0)
141
+ seq.pitches.should_not have_key(1)
142
+ seq.attacks.should have_key(0)
143
+ seq.attacks.should_not have_key(1)
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,68 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe NoteLinker do
4
+ describe '.find_unlinked_pitches' do
5
+ {
6
+ 'note has no pitches' => [Note.quarter,[]],
7
+ 'note has 1 pitch, no links' => [Note.quarter([C4]),[C4]],
8
+ 'note has 2 pitches, no links' => [Note.quarter([C4,E4]),[C4,E4]],
9
+ 'note has 1 pitch, which is linked' => [Note.quarter([C4], links: {C4 => Link::Tie.new} ),[]],
10
+ 'note has 2 pitch, 1 of which is linked' => [Note.quarter([C4,E4], links: {C4 => Link::Tie.new} ),[E4]],
11
+ 'note has 2 pitches, both of which are linked' => [Note.quarter([C4,E4], links: {C4 => Link::Tie.new, E4 => Link::Tie.new} ),[]],
12
+ 'note has 1 pitch, and 1 unrelated link' => [Note.quarter([C4], links: {D4 => Link::Tie.new}),[C4]],
13
+ 'note has 2 pitch, and 2 unrelated links' => [Note.quarter([C4,E4], links: {D4 => Link::Tie.new, F4 => Link::Tie.new}),[C4,E4]],
14
+ }.each do |descr,given_expected|
15
+ context descr do
16
+ given, expected = given_expected
17
+ it "should return #{expected}" do
18
+ actual = NoteLinker.find_unlinked_pitches(given)
19
+ actual.should eq(expected)
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '.find_untargeted_pitches' do
26
+ {
27
+ 'note has no pitches, next note has no pitches' => [Note.quarter,Note.quarter,[]],
28
+ 'note has no pitches, next note has 3 pitch' => [Note.quarter,Note.quarter([C3,E3,F3]),[C3,E3,F3]],
29
+ 'note has 3 pitches + no links, next note has 2 pitches' => [Note.quarter([C3,E3,F3]),Note.quarter([D2,F2]),[D2,F2]],
30
+ 'note has 1 pitch + 1 unrelated link, next note has 1 pitch' => [Note.quarter([C3], links: {C3 => Link::Slur.new(C2)}),Note.quarter([D2]),[D2]],
31
+ 'note has 1 pitch + 1 related link, next note has 1 pitch' => [Note.quarter([C3], links: {C3 => Link::Slur.new(D2)}),Note.quarter([D2]),[]],
32
+ 'note has 2 pitches + 2 related link, next note has 2 pitches' => [Note.quarter([C3,E3], links: {C3 => Link::Slur.new(D2), E3 => Link::Slur.new(E2) }),Note.quarter([D2,E2]),[]],
33
+ 'note has 2 pitches + 1 unrelated link, next note has 2 pitches' => [Note.quarter([C3,E3], links: {C3 => Link::Slur.new(D2), E3 => Link::Slur.new(F2) }),Note.quarter([D2,E2]),[E2]],
34
+ }.each do |descr,given_expected|
35
+ context descr do
36
+ given_note, given_next_note, expected = given_expected
37
+ it "should return #{expected}" do
38
+ actual = NoteLinker.find_untargeted_pitches(given_note, given_next_note)
39
+ actual.should eq(expected)
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ describe '.fully_link' do
46
+ [
47
+ [ Note.quarter([C4,E4,G4]), Note.quarter, Note.quarter([C4,E4,G4]) ],
48
+ [ Note.quarter([G4]), Note.quarter([A4]), Note.quarter([G4], links: {G4 => Link::Slur.new(A4)}) ],
49
+ [
50
+ Note.quarter([G4,A4]),
51
+ Note.quarter([A4]),
52
+ Note.quarter([G4,A4], links: {A4 => Link::Slur.new(A4)})
53
+ ],
54
+ [
55
+ Note.quarter([G4,A4], links: {A4 => Link::Slur.new(B4)}),
56
+ Note.quarter([A4,B4]),
57
+ Note.quarter([G4,A4], links: {G4 => Link::Slur.new(A4), A4 => Link::Slur.new(B4)})
58
+ ],
59
+ ].each do |note,next_note,modified|
60
+ context "given note: #{note.to_s}, next_note: #{next_note.to_s}" do
61
+ it "should modifiy note to equal #{modified.to_s}" do
62
+ NoteLinker.fully_link(note, next_note, Link::Slur)
63
+ note.should eq(modified)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,73 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe Optimization do
4
+ describe '.linking' do
5
+ context 'one unlinked, one untargeted' do
6
+ it 'should map the one unlinked to the one untargeted' do
7
+ [ C4, Bb4, G2, A3 ].each do |p1|
8
+ [ C4, Bb4, G2, A3 ].each do |p2|
9
+ sol = Optimization.linking([p1], [p2])
10
+ sol.size.should eq 1
11
+ sol.should have_key p1
12
+ sol[p1].should eq p2
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ context 'two unlinked, one untargeted' do
19
+ it 'should map the closest unlinked to the one untargeted' do
20
+ unlinked = [C4,G4]
21
+ { [Bb4] => {G4 => Bb4},
22
+ [F4] => {G4 => F4},
23
+ [E4] => {G4 => E4},
24
+ [Eb4] => {C4 => Eb4},
25
+ [D4] => {C4 => D4},
26
+ [Bb3] => {C4 => Bb3}
27
+ }.each do |untargeted, expected_map|
28
+ sol = Optimization.linking(unlinked, untargeted)
29
+ sol.should eq expected_map
30
+ end
31
+ end
32
+ end
33
+
34
+ context 'one unlinked, two untargeted' do
35
+ it 'should map the one unlinked to the closest untargeted' do
36
+ unlinked = [C4]
37
+ { [G4,Bb4] => {C4 => G4},
38
+ [G4,F4] => {C4 => F4},
39
+ [Eb4,D4] => {C4 => D4},
40
+ [G4,Bb3] => {C4 => Bb3},
41
+ [G3,G4] => {C4 => G3}
42
+ }.each do |untargeted, expected_map|
43
+ sol = Optimization.linking(unlinked, untargeted)
44
+ sol.should eq expected_map
45
+ end
46
+ end
47
+ end
48
+
49
+ context 'many unlinked, many untargeted' do
50
+ it 'should map [unlinked.size, untargeted.size].min unlinked to untargeted, such that total pitch diffs is minimized' do
51
+ {
52
+ [[A3,B3,C3],[B3,Db3]] => { B3 => B3, C3 => Db3 },
53
+ [[A3,B3,C3],[Bb3,C3]] => { A3 => Bb3, C3 => C3 },
54
+ [[A3,B3,C3],[Gb3,Bb3]] => { A3 => Gb3, B3 => Bb3 },
55
+ [[D5,Gb5],[B5,E5,G5]] => { D5 => E5, Gb5 => G5 },
56
+ [[D5,Gb5],[Db5,E5,G5]] => { D5 => Db5, Gb5 => G5 },
57
+ [[D5,Gb5],[C5,E5,G5]] => { D5 => C5, Gb5 => G5 },
58
+ [[D5,Gb5],[B5,E5,G5]] => { D5 => E5, Gb5 => G5 },
59
+ [[D5,Gb5],[B5,E5,F5,G5]] => { D5 => E5, Gb5 => F5 },
60
+ [[D5,Gb5],[B5,F5,G5]] => { D5 => F5, Gb5 => G5 },
61
+ [[G5],[B5,F5,G5]] => { G5 => G5 },
62
+ [[B5,F5,G5],[G5]] => { G5 => G5 },
63
+ [[G5],[C5,A5,B5]] => { G5 => A5 },
64
+ [[C4,E4,G4,Bb4],[D4,Gb4,A4,C5]] => { C4 => D4, E4 => Gb4, G4 => A4, Bb4 => C5 }
65
+ }.each do |unlinked_untargeted, expected_map|
66
+ unlinked,untargeted = unlinked_untargeted
67
+ sol = Optimization.linking(unlinked, untargeted)
68
+ sol.should eq expected_map
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,43 @@
1
+ require 'rspec'
2
+ require 'musicality'
3
+
4
+ include Musicality
5
+ include Pitches
6
+ include Meters
7
+ include Articulations
8
+
9
+ class Samples
10
+ SAMPLE_PART = Part.new(
11
+ Dynamics::P,
12
+ notes: [
13
+ Note::quarter([ C1, D1 ]),
14
+ Note::quarter([ C2, D2 ]),
15
+ Note::whole([ C3, D3 ])
16
+ ],
17
+ dynamic_changes: {1.0 => Change::Immediate.new(Dynamics::MP)}
18
+ )
19
+ end
20
+
21
+ RSpec::Matchers.define :be_valid do
22
+ match do |obj|
23
+ obj.valid?
24
+ end
25
+ end
26
+
27
+ RSpec::Matchers.define :be_invalid do
28
+ match do |obj|
29
+ obj.invalid?
30
+ end
31
+ end
32
+
33
+ RSpec::Matchers.define :parse do |str|
34
+ match do |parser|
35
+ !parser.parse(str).nil?
36
+ end
37
+ end
38
+
39
+ RSpec::Matchers.define :parse_as do |str,nodeclass|
40
+ match do |parser|
41
+ parser.parse(str).is_a?(nodeclass)
42
+ end
43
+ end
metadata ADDED
@@ -0,0 +1,323 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: musicality
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - James Tunnell
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '2.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: treetop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.5'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: midilib
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: docopt
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '0.5'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '0.5'
97
+ description: "The library is based around an abstract representation for music notation.
98
+ \\\n From here, functions are built up to make composing
99
+ elaborate pieces in this notation representation more manageable. \\\n Finally,
100
+ music performance is supported by providing translation to common formats, like
101
+ MIDI. "
102
+ email:
103
+ - jamestunnell@gmail.com
104
+ executables:
105
+ - midify
106
+ extensions: []
107
+ extra_rdoc_files: []
108
+ files:
109
+ - .gitignore
110
+ - .rspec
111
+ - .ruby-version
112
+ - Gemfile
113
+ - LICENSE.txt
114
+ - README.md
115
+ - Rakefile
116
+ - bin/midify
117
+ - examples/hip.rb
118
+ - examples/missed_connection.rb
119
+ - examples/song1.rb
120
+ - examples/song2.rb
121
+ - lib/musicality.rb
122
+ - lib/musicality/errors.rb
123
+ - lib/musicality/notation/conversion/change_conversion.rb
124
+ - lib/musicality/notation/conversion/measure_note_map.rb
125
+ - lib/musicality/notation/conversion/measured_score_conversion.rb
126
+ - lib/musicality/notation/conversion/measured_score_converter.rb
127
+ - lib/musicality/notation/conversion/note_time_converter.rb
128
+ - lib/musicality/notation/conversion/tempo_conversion.rb
129
+ - lib/musicality/notation/conversion/unmeasured_score_conversion.rb
130
+ - lib/musicality/notation/conversion/unmeasured_score_converter.rb
131
+ - lib/musicality/notation/model/articulations.rb
132
+ - lib/musicality/notation/model/change.rb
133
+ - lib/musicality/notation/model/dynamics.rb
134
+ - lib/musicality/notation/model/link.rb
135
+ - lib/musicality/notation/model/meter.rb
136
+ - lib/musicality/notation/model/meters.rb
137
+ - lib/musicality/notation/model/note.rb
138
+ - lib/musicality/notation/model/part.rb
139
+ - lib/musicality/notation/model/pitch.rb
140
+ - lib/musicality/notation/model/pitches.rb
141
+ - lib/musicality/notation/model/program.rb
142
+ - lib/musicality/notation/model/score.rb
143
+ - lib/musicality/notation/packing/change_packing.rb
144
+ - lib/musicality/notation/packing/part_packing.rb
145
+ - lib/musicality/notation/packing/program_packing.rb
146
+ - lib/musicality/notation/packing/score_packing.rb
147
+ - lib/musicality/notation/parsing/articulation_parsing.rb
148
+ - lib/musicality/notation/parsing/articulation_parsing.treetop
149
+ - lib/musicality/notation/parsing/convenience_methods.rb
150
+ - lib/musicality/notation/parsing/duration_nodes.rb
151
+ - lib/musicality/notation/parsing/duration_parsing.rb
152
+ - lib/musicality/notation/parsing/duration_parsing.treetop
153
+ - lib/musicality/notation/parsing/link_nodes.rb
154
+ - lib/musicality/notation/parsing/link_parsing.rb
155
+ - lib/musicality/notation/parsing/link_parsing.treetop
156
+ - lib/musicality/notation/parsing/meter_parsing.rb
157
+ - lib/musicality/notation/parsing/meter_parsing.treetop
158
+ - lib/musicality/notation/parsing/note_node.rb
159
+ - lib/musicality/notation/parsing/note_parsing.rb
160
+ - lib/musicality/notation/parsing/note_parsing.treetop
161
+ - lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.rb
162
+ - lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.treetop
163
+ - lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb
164
+ - lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.treetop
165
+ - lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.rb
166
+ - lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.treetop
167
+ - lib/musicality/notation/parsing/numbers/positive_float_parsing.rb
168
+ - lib/musicality/notation/parsing/numbers/positive_float_parsing.treetop
169
+ - lib/musicality/notation/parsing/numbers/positive_integer_parsing.rb
170
+ - lib/musicality/notation/parsing/numbers/positive_integer_parsing.treetop
171
+ - lib/musicality/notation/parsing/numbers/positive_rational_parsing.rb
172
+ - lib/musicality/notation/parsing/numbers/positive_rational_parsing.treetop
173
+ - lib/musicality/notation/parsing/parseable.rb
174
+ - lib/musicality/notation/parsing/pitch_node.rb
175
+ - lib/musicality/notation/parsing/pitch_parsing.rb
176
+ - lib/musicality/notation/parsing/pitch_parsing.treetop
177
+ - lib/musicality/notation/parsing/segment_parsing.rb
178
+ - lib/musicality/notation/parsing/segment_parsing.treetop
179
+ - lib/musicality/notation/util/interpolation.rb
180
+ - lib/musicality/notation/util/piecewise_function.rb
181
+ - lib/musicality/notation/util/value_computer.rb
182
+ - lib/musicality/performance/conversion/glissando_converter.rb
183
+ - lib/musicality/performance/conversion/note_sequence_extractor.rb
184
+ - lib/musicality/performance/conversion/portamento_converter.rb
185
+ - lib/musicality/performance/conversion/score_collator.rb
186
+ - lib/musicality/performance/midi/midi_events.rb
187
+ - lib/musicality/performance/midi/midi_util.rb
188
+ - lib/musicality/performance/midi/part_sequencer.rb
189
+ - lib/musicality/performance/midi/score_sequencer.rb
190
+ - lib/musicality/performance/model/note_attacks.rb
191
+ - lib/musicality/performance/model/note_sequence.rb
192
+ - lib/musicality/performance/util/note_linker.rb
193
+ - lib/musicality/performance/util/optimization.rb
194
+ - lib/musicality/validatable.rb
195
+ - lib/musicality/version.rb
196
+ - musicality.gemspec
197
+ - spec/musicality_spec.rb
198
+ - spec/notation/conversion/change_conversion_spec.rb
199
+ - spec/notation/conversion/measure_note_map_spec.rb
200
+ - spec/notation/conversion/measured_score_conversion_spec.rb
201
+ - spec/notation/conversion/measured_score_converter_spec.rb
202
+ - spec/notation/conversion/note_time_converter_spec.rb
203
+ - spec/notation/conversion/tempo_conversion_spec.rb
204
+ - spec/notation/conversion/unmeasured_score_conversion_spec.rb
205
+ - spec/notation/conversion/unmeasured_score_converter_spec.rb
206
+ - spec/notation/model/change_spec.rb
207
+ - spec/notation/model/link_spec.rb
208
+ - spec/notation/model/meter_spec.rb
209
+ - spec/notation/model/note_spec.rb
210
+ - spec/notation/model/part_spec.rb
211
+ - spec/notation/model/pitch_spec.rb
212
+ - spec/notation/model/program_spec.rb
213
+ - spec/notation/model/score_spec.rb
214
+ - spec/notation/packing/change_packing_spec.rb
215
+ - spec/notation/packing/part_packing_spec.rb
216
+ - spec/notation/packing/program_packing_spec.rb
217
+ - spec/notation/packing/score_packing_spec.rb
218
+ - spec/notation/parsing/articulation_parsing_spec.rb
219
+ - spec/notation/parsing/convenience_methods_spec.rb
220
+ - spec/notation/parsing/duration_nodes_spec.rb
221
+ - spec/notation/parsing/duration_parsing_spec.rb
222
+ - spec/notation/parsing/link_nodes_spec.rb
223
+ - spec/notation/parsing/link_parsing_spec.rb
224
+ - spec/notation/parsing/meter_parsing_spec.rb
225
+ - spec/notation/parsing/note_node_spec.rb
226
+ - spec/notation/parsing/note_parsing_spec.rb
227
+ - spec/notation/parsing/numbers/nonnegative_float_spec.rb
228
+ - spec/notation/parsing/numbers/nonnegative_integer_spec.rb
229
+ - spec/notation/parsing/numbers/nonnegative_rational_spec.rb
230
+ - spec/notation/parsing/numbers/positive_float_spec.rb
231
+ - spec/notation/parsing/numbers/positive_integer_spec.rb
232
+ - spec/notation/parsing/numbers/positive_rational_spec.rb
233
+ - spec/notation/parsing/pitch_node_spec.rb
234
+ - spec/notation/parsing/pitch_parsing_spec.rb
235
+ - spec/notation/parsing/segment_parsing_spec.rb
236
+ - spec/notation/util/value_computer_spec.rb
237
+ - spec/performance/conversion/glissando_converter_spec.rb
238
+ - spec/performance/conversion/note_sequence_extractor_spec.rb
239
+ - spec/performance/conversion/portamento_converter_spec.rb
240
+ - spec/performance/conversion/score_collator_spec.rb
241
+ - spec/performance/midi/midi_util_spec.rb
242
+ - spec/performance/midi/part_sequencer_spec.rb
243
+ - spec/performance/midi/score_sequencer_spec.rb
244
+ - spec/performance/model/note_sequence_spec.rb
245
+ - spec/performance/util/note_linker_spec.rb
246
+ - spec/performance/util/optimization_spec.rb
247
+ - spec/spec_helper.rb
248
+ homepage: https://github.com/jamestunnell/musicality
249
+ licenses:
250
+ - MIT
251
+ metadata: {}
252
+ post_install_message:
253
+ rdoc_options: []
254
+ require_paths:
255
+ - lib
256
+ required_ruby_version: !ruby/object:Gem::Requirement
257
+ requirements:
258
+ - - '>='
259
+ - !ruby/object:Gem::Version
260
+ version: '0'
261
+ required_rubygems_version: !ruby/object:Gem::Requirement
262
+ requirements:
263
+ - - '>='
264
+ - !ruby/object:Gem::Version
265
+ version: '0'
266
+ requirements: []
267
+ rubyforge_project:
268
+ rubygems_version: 2.4.2
269
+ signing_key:
270
+ specification_version: 4
271
+ summary: Music notation, composition, and performance
272
+ test_files:
273
+ - spec/musicality_spec.rb
274
+ - spec/notation/conversion/change_conversion_spec.rb
275
+ - spec/notation/conversion/measure_note_map_spec.rb
276
+ - spec/notation/conversion/measured_score_conversion_spec.rb
277
+ - spec/notation/conversion/measured_score_converter_spec.rb
278
+ - spec/notation/conversion/note_time_converter_spec.rb
279
+ - spec/notation/conversion/tempo_conversion_spec.rb
280
+ - spec/notation/conversion/unmeasured_score_conversion_spec.rb
281
+ - spec/notation/conversion/unmeasured_score_converter_spec.rb
282
+ - spec/notation/model/change_spec.rb
283
+ - spec/notation/model/link_spec.rb
284
+ - spec/notation/model/meter_spec.rb
285
+ - spec/notation/model/note_spec.rb
286
+ - spec/notation/model/part_spec.rb
287
+ - spec/notation/model/pitch_spec.rb
288
+ - spec/notation/model/program_spec.rb
289
+ - spec/notation/model/score_spec.rb
290
+ - spec/notation/packing/change_packing_spec.rb
291
+ - spec/notation/packing/part_packing_spec.rb
292
+ - spec/notation/packing/program_packing_spec.rb
293
+ - spec/notation/packing/score_packing_spec.rb
294
+ - spec/notation/parsing/articulation_parsing_spec.rb
295
+ - spec/notation/parsing/convenience_methods_spec.rb
296
+ - spec/notation/parsing/duration_nodes_spec.rb
297
+ - spec/notation/parsing/duration_parsing_spec.rb
298
+ - spec/notation/parsing/link_nodes_spec.rb
299
+ - spec/notation/parsing/link_parsing_spec.rb
300
+ - spec/notation/parsing/meter_parsing_spec.rb
301
+ - spec/notation/parsing/note_node_spec.rb
302
+ - spec/notation/parsing/note_parsing_spec.rb
303
+ - spec/notation/parsing/numbers/nonnegative_float_spec.rb
304
+ - spec/notation/parsing/numbers/nonnegative_integer_spec.rb
305
+ - spec/notation/parsing/numbers/nonnegative_rational_spec.rb
306
+ - spec/notation/parsing/numbers/positive_float_spec.rb
307
+ - spec/notation/parsing/numbers/positive_integer_spec.rb
308
+ - spec/notation/parsing/numbers/positive_rational_spec.rb
309
+ - spec/notation/parsing/pitch_node_spec.rb
310
+ - spec/notation/parsing/pitch_parsing_spec.rb
311
+ - spec/notation/parsing/segment_parsing_spec.rb
312
+ - spec/notation/util/value_computer_spec.rb
313
+ - spec/performance/conversion/glissando_converter_spec.rb
314
+ - spec/performance/conversion/note_sequence_extractor_spec.rb
315
+ - spec/performance/conversion/portamento_converter_spec.rb
316
+ - spec/performance/conversion/score_collator_spec.rb
317
+ - spec/performance/midi/midi_util_spec.rb
318
+ - spec/performance/midi/part_sequencer_spec.rb
319
+ - spec/performance/midi/score_sequencer_spec.rb
320
+ - spec/performance/model/note_sequence_spec.rb
321
+ - spec/performance/util/note_linker_spec.rb
322
+ - spec/performance/util/optimization_spec.rb
323
+ - spec/spec_helper.rb