music-performance 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.gitignore +7 -0
  4. data/.rspec +1 -0
  5. data/.ruby-version +1 -0
  6. data/.yardopts +1 -0
  7. data/ChangeLog.rdoc +5 -0
  8. data/Gemfile +3 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.rdoc +28 -0
  11. data/Rakefile +54 -0
  12. data/bin/midify +61 -0
  13. data/lib/music-performance.rb +25 -0
  14. data/lib/music-performance/arrangement/midi/midi_events.rb +9 -0
  15. data/lib/music-performance/arrangement/midi/midi_util.rb +38 -0
  16. data/lib/music-performance/arrangement/midi/part_sequencer.rb +121 -0
  17. data/lib/music-performance/arrangement/midi/score_sequencer.rb +33 -0
  18. data/lib/music-performance/conversion/glissando_converter.rb +36 -0
  19. data/lib/music-performance/conversion/note_sequence_extractor.rb +100 -0
  20. data/lib/music-performance/conversion/note_time_converter.rb +76 -0
  21. data/lib/music-performance/conversion/portamento_converter.rb +26 -0
  22. data/lib/music-performance/conversion/score_collator.rb +121 -0
  23. data/lib/music-performance/conversion/score_time_converter.rb +112 -0
  24. data/lib/music-performance/model/note_attacks.rb +21 -0
  25. data/lib/music-performance/model/note_sequence.rb +113 -0
  26. data/lib/music-performance/util/interpolation.rb +18 -0
  27. data/lib/music-performance/util/note_linker.rb +30 -0
  28. data/lib/music-performance/util/optimization.rb +33 -0
  29. data/lib/music-performance/util/piecewise_function.rb +124 -0
  30. data/lib/music-performance/util/value_computer.rb +172 -0
  31. data/lib/music-performance/version.rb +7 -0
  32. data/music-performance.gemspec +33 -0
  33. data/spec/conversion/glissando_converter_spec.rb +93 -0
  34. data/spec/conversion/note_sequence_extractor_spec.rb +230 -0
  35. data/spec/conversion/note_time_converter_spec.rb +96 -0
  36. data/spec/conversion/portamento_converter_spec.rb +91 -0
  37. data/spec/conversion/score_collator_spec.rb +136 -0
  38. data/spec/conversion/score_time_converter_spec.rb +73 -0
  39. data/spec/model/note_sequence_spec.rb +147 -0
  40. data/spec/music-performance_spec.rb +7 -0
  41. data/spec/spec_helper.rb +8 -0
  42. data/spec/util/note_linker_spec.rb +68 -0
  43. data/spec/util/optimization_spec.rb +73 -0
  44. data/spec/util/value_computer_spec.rb +146 -0
  45. metadata +242 -0
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Music::Performance do
4
+ it "should have a VERSION constant" do
5
+ subject.const_get('VERSION').should_not be_empty
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ require 'rspec'
2
+ require 'music-performance'
3
+
4
+ include Music::Performance
5
+ include Music::Transcription
6
+ include Pitches
7
+ include Meters
8
+ include Articulations
@@ -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,146 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe ValueComputer do
4
+ describe '#value_at' do
5
+ before :all do
6
+ @value_change1 = Change::Immediate.new(0.6)
7
+ @value_change2 = Change::Gradual.new(0.6, 1.0)
8
+ end
9
+
10
+ context "constant value" do
11
+ before :each do
12
+ @comp = ValueComputer.new 0.5
13
+ end
14
+
15
+ it "should always return default value if no changes are given" do
16
+ [ValueComputer.domain_min, -1000, 0, 1, 5, 100, 10000, ValueComputer.domain_max].each do |offset|
17
+ @comp.value_at(offset).should eq(0.5)
18
+ end
19
+ end
20
+ end
21
+
22
+ context "one change, no transition" do
23
+ before :each do
24
+ @comp = ValueComputer.new 0.5, 1.0 => @value_change1
25
+ end
26
+
27
+ it "should be the default value just before the first change" do
28
+ @comp.value_at(0.999).should eq(0.5)
29
+ end
30
+
31
+ it "should transition to the second value immediately" do
32
+ @comp.value_at(1.0).should eq(0.6)
33
+ end
34
+
35
+ it "should be the first value for all time before" do
36
+ @comp.value_at(ValueComputer.domain_min).should eq(0.5)
37
+ end
38
+
39
+ it "should be at the second value for all time after" do
40
+ @comp.value_at(ValueComputer.domain_max).should eq(0.6)
41
+ end
42
+ end
43
+
44
+ context "one change, linear transition" do
45
+ before :each do
46
+ @comp = ValueComputer.new 0.2, 1.0 => @value_change2
47
+ end
48
+
49
+ it "should be the first (starting) value just before the second value" do
50
+ @comp.value_at(0.999).should eq(0.2)
51
+ end
52
+
53
+ it "should be the first (starting) value exactly at the second value" do
54
+ @comp.value_at(1.0).should eq(0.2)
55
+ end
56
+
57
+ it "should be 1/4 to the second value after 1/4 transition duration has elapsed" do
58
+ @comp.value_at(Rational(5,4).to_f).should eq(0.3)
59
+ end
60
+
61
+ it "should be 1/2 to the second value after 1/2 transition duration has elapsed" do
62
+ @comp.value_at(Rational(6,4).to_f).should eq(0.4)
63
+ end
64
+
65
+ it "should be 3/4 to the second value after 3/4 transition duration has elapsed" do
66
+ @comp.value_at(Rational(7,4).to_f).should eq(0.5)
67
+ end
68
+
69
+ it "should be at the second value after transition duration has elapsed" do
70
+ @comp.value_at(Rational(8,4).to_f).should eq(0.6)
71
+ end
72
+ end
73
+
74
+ # context "one change, sigmoid transition" do
75
+ # before :all do
76
+ # @cases = [
77
+ # { :start_value => 0, :end_value => 1, :offset => 0, :duration => 1.0, :abruptness => 0.75 },
78
+ # { :start_value => 0.25, :end_value => 0.75, :offset => 1.0, :duration => 2.0, :abruptness => 0.75 },
79
+ # { :start_value => -1.0, :end_value => 5.5, :offset => 2.4, :duration => 20, :abruptness => 0.75 },
80
+ # { :start_value => 10, :end_value => 100, :offset => 20, :duration => 4, :abruptness => 0.75 },
81
+ # ]
82
+ #
83
+ # @computers = {}
84
+ # @cases.each do |case_hash|
85
+ # start_value = case_hash[:start_value]
86
+ # offset = case_hash[:offset]
87
+ # end_value = case_hash[:end_value]
88
+ # duration = case_hash[:duration]
89
+ # #abruptness = case_hash[:abruptness]
90
+ #
91
+ # change = Change::Gradual.new(end_value, duration)
92
+ # @computers[case_hash] = ValueComputer.new start_value, offset => change
93
+ # # @computers[case_hash].plot_range(offset..(offset + duration), 0.01)
94
+ # end
95
+ # end
96
+ #
97
+ # it "should be the first (starting) value just before the value change offset" do
98
+ # @computers.each do |case_hash, comp|
99
+ # comp.value_at(case_hash[:offset] - 0.0001).should eq(case_hash[:start_value])
100
+ # end
101
+ # end
102
+ #
103
+ # it "should be very nearly the first (starting) value exactly at the value change offset" do
104
+ # @computers.each do |case_hash, comp|
105
+ # comp.value_at(case_hash[:offset]).should be_within(0.0001).of(case_hash[:start_value])
106
+ # end
107
+ # end
108
+ #
109
+ # it "should be within 1% of start/end difference away from the start value after 1/4 transition duration has elapsed" do
110
+ # @computers.each do |case_hash, comp|
111
+ # test_offset = case_hash[:offset] + (case_hash[:duration] * 0.25)
112
+ # start_value = case_hash[:start_value]
113
+ # end_value = case_hash[:end_value]
114
+ # tolerance = 0.01 * (end_value - start_value)
115
+ # comp.value_at(test_offset).should be_within(tolerance).of(start_value)
116
+ # end
117
+ # end
118
+ #
119
+ # it "should be half way to the end value after half way through transition" do
120
+ # @computers.each do |case_hash, comp|
121
+ # test_offset = case_hash[:offset] + (case_hash[:duration] * 0.5)
122
+ # start_value = case_hash[:start_value]
123
+ # expected_value = start_value + (case_hash[:end_value] - start_value) * 0.5
124
+ # comp.value_at(test_offset).should be_within(0.0001).of(expected_value)
125
+ # end
126
+ # end
127
+ #
128
+ # it "should be within 1% of start/end difference away from the end value after 3/4 transition duration has elapsed" do
129
+ # @computers.each do |case_hash, comp|
130
+ # test_offset = case_hash[:offset] + (case_hash[:duration] * 0.75)
131
+ # start_value = case_hash[:start_value]
132
+ # end_value = case_hash[:end_value]
133
+ # tolerance = 0.01 * (end_value - start_value)
134
+ # comp.value_at(test_offset).should be_within(tolerance).of(end_value)
135
+ # end
136
+ # end
137
+ #
138
+ # it "should be at the second value after transition duration has elapsed" do
139
+ # @computers.each do |case_hash, comp|
140
+ # comp.value_at(case_hash[:offset] + case_hash[:duration]).should eq(case_hash[:end_value])
141
+ # end
142
+ # end
143
+ # end
144
+ end
145
+ end
146
+
metadata ADDED
@@ -0,0 +1,242 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: music-performance
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - James Tunnell
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-29 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.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubygems-bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '10.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '10.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.14'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '2.14'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '0.8'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '0.8'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry-nav
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: music-transcription
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 0.17.0
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 0.17.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: midilib
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ~>
130
+ - !ruby/object:Gem::Version
131
+ version: '2.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ~>
137
+ - !ruby/object:Gem::Version
138
+ version: '2.0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: docopt
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description: |
154
+ Prepare a transcribed musical score for performance by a computer.
155
+ email: jamestunnell@gmail.com
156
+ executables:
157
+ - midify
158
+ extensions: []
159
+ extra_rdoc_files: []
160
+ files:
161
+ - .document
162
+ - .gitignore
163
+ - .rspec
164
+ - .ruby-version
165
+ - .yardopts
166
+ - ChangeLog.rdoc
167
+ - Gemfile
168
+ - LICENSE.txt
169
+ - README.rdoc
170
+ - Rakefile
171
+ - bin/midify
172
+ - lib/music-performance.rb
173
+ - lib/music-performance/arrangement/midi/midi_events.rb
174
+ - lib/music-performance/arrangement/midi/midi_util.rb
175
+ - lib/music-performance/arrangement/midi/part_sequencer.rb
176
+ - lib/music-performance/arrangement/midi/score_sequencer.rb
177
+ - lib/music-performance/conversion/glissando_converter.rb
178
+ - lib/music-performance/conversion/note_sequence_extractor.rb
179
+ - lib/music-performance/conversion/note_time_converter.rb
180
+ - lib/music-performance/conversion/portamento_converter.rb
181
+ - lib/music-performance/conversion/score_collator.rb
182
+ - lib/music-performance/conversion/score_time_converter.rb
183
+ - lib/music-performance/model/note_attacks.rb
184
+ - lib/music-performance/model/note_sequence.rb
185
+ - lib/music-performance/util/interpolation.rb
186
+ - lib/music-performance/util/note_linker.rb
187
+ - lib/music-performance/util/optimization.rb
188
+ - lib/music-performance/util/piecewise_function.rb
189
+ - lib/music-performance/util/value_computer.rb
190
+ - lib/music-performance/version.rb
191
+ - music-performance.gemspec
192
+ - spec/conversion/glissando_converter_spec.rb
193
+ - spec/conversion/note_sequence_extractor_spec.rb
194
+ - spec/conversion/note_time_converter_spec.rb
195
+ - spec/conversion/portamento_converter_spec.rb
196
+ - spec/conversion/score_collator_spec.rb
197
+ - spec/conversion/score_time_converter_spec.rb
198
+ - spec/model/note_sequence_spec.rb
199
+ - spec/music-performance_spec.rb
200
+ - spec/spec_helper.rb
201
+ - spec/util/note_linker_spec.rb
202
+ - spec/util/optimization_spec.rb
203
+ - spec/util/value_computer_spec.rb
204
+ homepage: https://github.com/jamestunnell/music-performance
205
+ licenses:
206
+ - MIT
207
+ metadata: {}
208
+ post_install_message:
209
+ rdoc_options: []
210
+ require_paths:
211
+ - lib
212
+ required_ruby_version: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - '>='
215
+ - !ruby/object:Gem::Version
216
+ version: '0'
217
+ required_rubygems_version: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ requirements: []
223
+ rubyforge_project:
224
+ rubygems_version: 2.4.2
225
+ signing_key:
226
+ specification_version: 4
227
+ summary: Classes for representing music notational features like pitch, note, loudness,
228
+ tempo, etc.
229
+ test_files:
230
+ - spec/conversion/glissando_converter_spec.rb
231
+ - spec/conversion/note_sequence_extractor_spec.rb
232
+ - spec/conversion/note_time_converter_spec.rb
233
+ - spec/conversion/portamento_converter_spec.rb
234
+ - spec/conversion/score_collator_spec.rb
235
+ - spec/conversion/score_time_converter_spec.rb
236
+ - spec/model/note_sequence_spec.rb
237
+ - spec/music-performance_spec.rb
238
+ - spec/spec_helper.rb
239
+ - spec/util/note_linker_spec.rb
240
+ - spec/util/optimization_spec.rb
241
+ - spec/util/value_computer_spec.rb
242
+ has_rdoc: