musicality 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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