music-transcription 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +3 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.rdoc +4 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +28 -0
- data/Rakefile +54 -0
- data/bin/transcribe +176 -0
- data/lib/music-transcription.rb +20 -0
- data/lib/music-transcription/arrangement.rb +31 -0
- data/lib/music-transcription/instrument_config.rb +38 -0
- data/lib/music-transcription/interval.rb +66 -0
- data/lib/music-transcription/link.rb +115 -0
- data/lib/music-transcription/note.rb +156 -0
- data/lib/music-transcription/part.rb +128 -0
- data/lib/music-transcription/pitch.rb +297 -0
- data/lib/music-transcription/pitch_constants.rb +204 -0
- data/lib/music-transcription/profile.rb +105 -0
- data/lib/music-transcription/program.rb +136 -0
- data/lib/music-transcription/score.rb +122 -0
- data/lib/music-transcription/tempo.rb +44 -0
- data/lib/music-transcription/transition.rb +71 -0
- data/lib/music-transcription/value_change.rb +85 -0
- data/lib/music-transcription/version.rb +7 -0
- data/music-transcription.gemspec +36 -0
- data/samples/arrangements/glissando_test.yml +71 -0
- data/samples/arrangements/hip.yml +952 -0
- data/samples/arrangements/instrument_test.yml +119 -0
- data/samples/arrangements/legato_test.yml +237 -0
- data/samples/arrangements/make_glissando_test.rb +27 -0
- data/samples/arrangements/make_hip.rb +75 -0
- data/samples/arrangements/make_instrument_test.rb +34 -0
- data/samples/arrangements/make_legato_test.rb +37 -0
- data/samples/arrangements/make_missed_connection.rb +72 -0
- data/samples/arrangements/make_portamento_test.rb +27 -0
- data/samples/arrangements/make_slur_test.rb +37 -0
- data/samples/arrangements/make_song1.rb +84 -0
- data/samples/arrangements/make_song2.rb +69 -0
- data/samples/arrangements/missed_connection.yml +481 -0
- data/samples/arrangements/portamento_test.yml +71 -0
- data/samples/arrangements/slur_test.yml +237 -0
- data/samples/arrangements/song1.yml +640 -0
- data/samples/arrangements/song2.yml +429 -0
- data/spec/instrument_config_spec.rb +47 -0
- data/spec/interval_spec.rb +38 -0
- data/spec/link_spec.rb +22 -0
- data/spec/musicality_spec.rb +7 -0
- data/spec/note_spec.rb +65 -0
- data/spec/part_spec.rb +87 -0
- data/spec/pitch_spec.rb +139 -0
- data/spec/profile_spec.rb +24 -0
- data/spec/program_spec.rb +55 -0
- data/spec/score_spec.rb +55 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/transition_spec.rb +13 -0
- data/spec/value_change_spec.rb +19 -0
- metadata +239 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Interval do
|
4
|
+
before :all do
|
5
|
+
@pitch = C4
|
6
|
+
end
|
7
|
+
|
8
|
+
context '.new' do
|
9
|
+
it "should assign :pitch parameter given during construction" do
|
10
|
+
interval = Interval.new :pitch => @pitch
|
11
|
+
interval.pitch.should eq(@pitch)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should assign :link parameter if given during construction" do
|
15
|
+
link = Link.new(:relationship => Link::RELATIONSHIP_TIE, :target_pitch => @pitch)
|
16
|
+
interval = Interval.new :pitch => @pitch, :link => link
|
17
|
+
interval.link.should eq(link)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context '#pitch=' do
|
22
|
+
it "should assign pitch" do
|
23
|
+
interval = Interval.new :pitch => @pitch
|
24
|
+
interval.pitch = Gb4
|
25
|
+
interval.pitch.should eq Gb4
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context '#link=' do
|
30
|
+
it "should assign link" do
|
31
|
+
link = Link.new(:relationship => Link::RELATIONSHIP_SLUR, :target_pitch => G2)
|
32
|
+
interval = Interval.new :pitch => @pitch
|
33
|
+
interval.link = link
|
34
|
+
interval.link.should eq(link)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/spec/link_spec.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Link do
|
4
|
+
context '.new' do
|
5
|
+
its(:relationship) { should eq(Link::RELATIONSHIP_NONE) }
|
6
|
+
its(:target_pitch) { should eq(Pitch.new) }
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should assign the given relationship' do
|
10
|
+
Link::RELATIONSHIPS.each do |relationship|
|
11
|
+
link = Link.new(:relationship => relationship)
|
12
|
+
link.relationship.should eq(relationship)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should assign the given target pitch' do
|
17
|
+
[A0, B0].each do |pitch|
|
18
|
+
link = Link.new(:target_pitch => pitch)
|
19
|
+
link.target_pitch.should eq(pitch)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/spec/note_spec.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Note do
|
4
|
+
before :all do
|
5
|
+
@pitch = C4
|
6
|
+
end
|
7
|
+
|
8
|
+
context '.new' do
|
9
|
+
it 'should assign :duration that is given during construction' do
|
10
|
+
note = Note.new :duration => 2
|
11
|
+
note.duration.should eq(2)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should assign :sustain, :attack, and :separation parameters if given during construction" do
|
15
|
+
note = Note.new :duration => 2, :sustain => 0.1, :attack => 0.2, :separation => 0.3
|
16
|
+
note.sustain.should eq(0.1)
|
17
|
+
note.attack.should eq(0.2)
|
18
|
+
note.separation.should eq(0.3)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should have no intervals if not given' do
|
22
|
+
Note.new(:duration => 2).intervals.should be_empty
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should assign intervals when given' do
|
26
|
+
intervals = [
|
27
|
+
Interval.new(:pitch => C2),
|
28
|
+
Interval.new(:pitch => D2),
|
29
|
+
]
|
30
|
+
Note.new(:duration => 2, :intervals => intervals).intervals.should eq(intervals)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context '#duration=' do
|
35
|
+
it 'should assign duration' do
|
36
|
+
note = Note.new :pitch => @pitch, :duration => 2
|
37
|
+
note.duration = 3
|
38
|
+
note.duration.should eq 3
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context '#sustain=' do
|
43
|
+
it "should assign sustain" do
|
44
|
+
note = Note.new :pitch => @pitch, :duration => 2
|
45
|
+
note.sustain = 0.123
|
46
|
+
note.sustain.should eq 0.123
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context '#attack=' do
|
51
|
+
it "should assign attack" do
|
52
|
+
note = Note.new :pitch => @pitch, :duration => 2
|
53
|
+
note.attack = 0.123
|
54
|
+
note.attack.should eq 0.123
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context '#separation=' do
|
59
|
+
it "should assign separation" do
|
60
|
+
note = Note.new :pitch => @pitch, :duration => 2
|
61
|
+
note.separation = 0.123
|
62
|
+
note.separation.should eq 0.123
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/spec/part_spec.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Part do
|
4
|
+
context '.new' do
|
5
|
+
its(:offset) { should eq(0) }
|
6
|
+
its(:notes) { should be_empty }
|
7
|
+
|
8
|
+
it "should assign loudness_profile profile given during construction" do
|
9
|
+
loudness_profile = Profile.new(
|
10
|
+
:start_value => 0.5,
|
11
|
+
:value_changes => {
|
12
|
+
1.0 => linear_change(1.0, 2.0)
|
13
|
+
}
|
14
|
+
)
|
15
|
+
part = Part.new :loudness_profile => loudness_profile
|
16
|
+
part.loudness_profile.should eq(loudness_profile)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should assign notes given during construction" do
|
20
|
+
notes = [
|
21
|
+
Note.new(
|
22
|
+
:duration => 0.25,
|
23
|
+
:intervals => [
|
24
|
+
Interval.new(:pitch => C1),
|
25
|
+
Interval.new(:pitch => D1),
|
26
|
+
]
|
27
|
+
)
|
28
|
+
]
|
29
|
+
|
30
|
+
part = Part.new :notes => notes
|
31
|
+
part.notes.should eq(notes)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe PartFile do
|
37
|
+
describe '.new' do
|
38
|
+
before :all do
|
39
|
+
@part_hash = {
|
40
|
+
:notes => [
|
41
|
+
Note.new(
|
42
|
+
:duration => 0.25,
|
43
|
+
:intervals => [
|
44
|
+
Interval.new(:pitch => C1),
|
45
|
+
Interval.new(:pitch => D1) ]
|
46
|
+
),
|
47
|
+
Note.new(
|
48
|
+
:duration => 0.125,
|
49
|
+
:intervals => [
|
50
|
+
Interval.new(:pitch => E2) ]
|
51
|
+
),
|
52
|
+
],
|
53
|
+
:loudness_profile => Profile.new(
|
54
|
+
:start_value => 0.6
|
55
|
+
)
|
56
|
+
}
|
57
|
+
|
58
|
+
@path = 'temp.yml'
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'hash of part stored in YAML file' do
|
62
|
+
it 'should load part from file' do
|
63
|
+
File.open(@path, 'w') do |file|
|
64
|
+
file.write @part_hash.to_yaml
|
65
|
+
end
|
66
|
+
part = Part.new @part_hash
|
67
|
+
part_from_file = PartFile.new(:file_path => @path)
|
68
|
+
part_from_file.should eq part
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'part stored in YAML file' do
|
73
|
+
it 'should load part from file' do
|
74
|
+
part = Part.new @part_hash
|
75
|
+
File.open(@path, 'w') do |file|
|
76
|
+
file.write part.to_yaml
|
77
|
+
end
|
78
|
+
part_from_file = PartFile.new(:file_path => @path)
|
79
|
+
part_from_file.should eq part
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
after :all do
|
84
|
+
File.delete @path
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/spec/pitch_spec.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Pitch do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@cases =
|
7
|
+
[
|
8
|
+
{ :octave => 1, :semitone => 0, :cent => 0, :ratio => 2.0, :total_cent => 1200 },
|
9
|
+
{ :octave => 2, :semitone => 0, :cent => 0, :ratio => 4.0, :total_cent => 2400 },
|
10
|
+
{ :octave => 1, :semitone => 6, :cent => 0, :ratio => 2.8284, :total_cent => 1800 },
|
11
|
+
{ :octave => 2, :semitone => 6, :cent => 0, :ratio => 5.6569, :total_cent => 3000 },
|
12
|
+
{ :octave => 1, :semitone => 6, :cent => 20, :ratio => 2.8613, :total_cent => 1820 },
|
13
|
+
{ :octave => 2, :semitone => 6, :cent => 20, :ratio => 5.7226, :total_cent => 3020 },
|
14
|
+
{ :octave => 3, :semitone => 7, :cent => 77, :ratio => 12.5316, :total_cent => 4377 },
|
15
|
+
{ :octave => -1, :semitone => 0, :cent => 0, :ratio => 0.5, :total_cent => -1200 },
|
16
|
+
{ :octave => -2, :semitone => 0, :cent => 0, :ratio => 0.25, :total_cent => -2400 },
|
17
|
+
{ :octave => -2, :semitone => 7, :cent => 55, :ratio => 0.3867, :total_cent => -1645 },
|
18
|
+
{ :octave => -1, :semitone => 9, :cent => 23, :ratio => 0.8521, :total_cent => -277 },
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be constructible with no parameters (no error raised)" do
|
23
|
+
lambda { Pitch.new }.should_not raise_error
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should be hash-makeable" do
|
27
|
+
obj = Pitch.new :octave => 4, :semitone => 3
|
28
|
+
obj.octave.should eq(4)
|
29
|
+
obj.semitone.should eq(3)
|
30
|
+
obj.cent.should eq(0)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should use default octave, semitone, and cent in none is given" do
|
34
|
+
p = Pitch.new
|
35
|
+
p.ratio.should be_within(0.01).of(1.0)
|
36
|
+
p.total_cent.should eq(0)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should use the octave, semitone, and cent given during construction" do
|
40
|
+
@cases.each do |case_data|
|
41
|
+
p = Pitch.new :octave => case_data[:octave], :semitone => case_data[:semitone], :cent => case_data[:cent]
|
42
|
+
p.ratio.should be_within(0.01).of case_data[:ratio]
|
43
|
+
p.total_cent.should be case_data[:total_cent]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should allow setting by ratio" do
|
48
|
+
@cases.each do |case_data|
|
49
|
+
p = Pitch.new
|
50
|
+
p.ratio = case_data[:ratio]
|
51
|
+
|
52
|
+
p.octave.should eq case_data[:octave]
|
53
|
+
p.semitone.should eq case_data[:semitone]
|
54
|
+
p.cent.should eq case_data[:cent]
|
55
|
+
p.total_cent.should eq case_data[:total_cent]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should setting by total_cent" do
|
60
|
+
@cases.each do |case_data|
|
61
|
+
p = Pitch.new
|
62
|
+
p.total_cent = case_data[:total_cent]
|
63
|
+
|
64
|
+
p.octave.should eq case_data[:octave]
|
65
|
+
p.semitone.should eq case_data[:semitone]
|
66
|
+
p.cent.should eq case_data[:cent]
|
67
|
+
p.total_cent.should eq case_data[:total_cent]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should be comparable to other pitches" do
|
72
|
+
p1 = Pitch.new :semitone => 1
|
73
|
+
p2 = Pitch.new :semitone => 2
|
74
|
+
p3 = Pitch.new :semitone => 3
|
75
|
+
|
76
|
+
p1.should eq(Pitch.new :semitone => 1)
|
77
|
+
p2.should eq(Pitch.new :semitone => 2)
|
78
|
+
p3.should eq(Pitch.new :semitone => 3)
|
79
|
+
|
80
|
+
p1.should be < p2
|
81
|
+
p1.should be < p3
|
82
|
+
p2.should be < p3
|
83
|
+
p3.should be > p2
|
84
|
+
p3.should be > p1
|
85
|
+
p2.should be > p1
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should be addable and subtractable with other pitches" do
|
89
|
+
p1 = Pitch.new :semitone => 1
|
90
|
+
p2 = Pitch.new :semitone => 2
|
91
|
+
p3 = Pitch.new :semitone => 3
|
92
|
+
|
93
|
+
(p1 + p2).should eq(Pitch.new :semitone => 3)
|
94
|
+
(p1 + p3).should eq(Pitch.new :semitone => 4)
|
95
|
+
(p2 + p3).should eq(Pitch.new :semitone => 5)
|
96
|
+
|
97
|
+
(p1 - p2).should eq(Pitch.new :semitone => -1)
|
98
|
+
(p1 - p3).should eq(Pitch.new :semitone => -2)
|
99
|
+
(p2 - p3).should eq(Pitch.new :semitone => -1)
|
100
|
+
(p3 - p2).should eq(Pitch.new :semitone => 1)
|
101
|
+
(p3 - p1).should eq(Pitch.new :semitone => 2)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should have freq of 440 for A4" do
|
105
|
+
a4 = Pitch.new :octave => 4, :semitone => 9
|
106
|
+
a4.freq.should be_within(0.01).of(440.0)
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'String#to_pitch' do
|
110
|
+
it 'should create a Pitch object that matches the musical note' do
|
111
|
+
{
|
112
|
+
"Ab2" => Pitch.new(:octave => 2, :semitone => 8),
|
113
|
+
"C0" => Pitch.new(:octave => 0, :semitone => 0),
|
114
|
+
"db4" => Pitch.new(:octave => 4, :semitone => 1),
|
115
|
+
"F#12" => Pitch.new(:octave => 12, :semitone => 6),
|
116
|
+
"E#7" => Pitch.new(:octave => 7, :semitone => 5),
|
117
|
+
"G9" => Pitch.new(:octave => 9, :semitone => 7),
|
118
|
+
"Bb10" => Pitch.new(:octave => 10, :semitone => 10),
|
119
|
+
}.each do |str, expected_pitch|
|
120
|
+
str.to_pitch.should eq(expected_pitch)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context '.make_from_freq' do
|
126
|
+
it 'should make a pitch whose freq is approximately the given freq' do
|
127
|
+
one_cent = Pitch.new(:cent => 1)
|
128
|
+
[1.0, 25.0, 200.0, 3500.0].each do |given_freq|
|
129
|
+
pitch = Pitch.make_from_freq given_freq
|
130
|
+
freq = pitch.freq
|
131
|
+
if freq > given_freq
|
132
|
+
(freq / given_freq).should be < one_cent.ratio
|
133
|
+
elsif freq < given_freq
|
134
|
+
(given_freq / freq).should be < one_cent.ratio
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Profile do
|
4
|
+
|
5
|
+
context '.new' do
|
6
|
+
it "should assign start value given during construction" do
|
7
|
+
p = Profile.new(:start_value => 0.2)
|
8
|
+
p.start_value.should eq(0.2)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should assign settings given during construction" do
|
12
|
+
p = Profile.new(
|
13
|
+
:start_value => 0.2,
|
14
|
+
:value_changes => {
|
15
|
+
1.0 => ValueChange.new(:value => 0.5),
|
16
|
+
1.5 => ValueChange.new(:value => 1.0)
|
17
|
+
}
|
18
|
+
)
|
19
|
+
p.value_changes[1.0].value.should eq(0.5)
|
20
|
+
p.value_changes[1.5].value.should eq(1.0)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Program do
|
4
|
+
|
5
|
+
it "should assign the segments given during initialization" do
|
6
|
+
segments = [ 0.0...5.0, 0.0...4.0, 5.0...10.0 ]
|
7
|
+
program = Program.new :segments => segments
|
8
|
+
program.segments.should eq(segments.clone)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#include?" do
|
12
|
+
it "should return true for any offset which would be encountered" do
|
13
|
+
segments = [ 0.0...5.0, 0.0...4.0, 5.0...10.0 ]
|
14
|
+
program = Program.new :segments => segments
|
15
|
+
|
16
|
+
[0.0, 4.0, 5.0, 9.999].each do |offset|
|
17
|
+
program.include?(offset).should be_true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return false for any offset which would not be encountered" do
|
22
|
+
segments = [ 0.0...5.0, 0.0...4.0, 5.0...10.0 ]
|
23
|
+
program = Program.new :segments => segments
|
24
|
+
|
25
|
+
[-0.000001, 10.000001].each do |offset|
|
26
|
+
program.include?(offset).should be_false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#note_elapsed_at" do
|
32
|
+
before :each do
|
33
|
+
segments = [ 0.0...5.0, 0.0...4.0, 5.0..10.0 ]
|
34
|
+
@program = Program.new :segments => segments
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return 0.0 at program start" do
|
38
|
+
@program.note_elapsed_at(@program.start).should eq(0.0)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should return program length at program stop" do
|
42
|
+
@program.note_elapsed_at(@program.stop).should eq(@program.length)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should return correct note elapsed for any included offset" do
|
46
|
+
@program.note_elapsed_at(2.5).should eq(2.5)
|
47
|
+
@program.note_elapsed_at(5.5).should eq(9.5)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should raise error if offset is not included" do
|
51
|
+
lambda { @program.note_elapsed_at(-0.000001) }.should raise_error
|
52
|
+
lambda { @program.note_elapsed_at(10.000001) }.should raise_error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/score_spec.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Score do
|
4
|
+
before :each do
|
5
|
+
@parts = { "piano (LH)" => Samples::SAMPLE_PART }
|
6
|
+
@program = Program.new :segments => [0...0.75, 0...0.75]
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '.new' do
|
10
|
+
context "no args given" do
|
11
|
+
let(:score) { Score.new }
|
12
|
+
subject { score }
|
13
|
+
its(:program) { should eq(Program.new) }
|
14
|
+
its(:parts) { should be_empty }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'args given' do
|
18
|
+
it "should assign parts given during construction" do
|
19
|
+
score = Score.new :program => @program, :parts => @parts
|
20
|
+
score.parts.should eq(@parts)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should assign program given during construction" do
|
24
|
+
score = Score.new :program => @program
|
25
|
+
score.program.should eq(@program)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe TempoScore do
|
32
|
+
before :each do
|
33
|
+
@parts = { "piano (LH)" => Samples::SAMPLE_PART }
|
34
|
+
@program = Program.new :segments => [0...0.75, 0...0.75]
|
35
|
+
@tempo_profile = Profile.new(
|
36
|
+
:start_value => tempo(120),
|
37
|
+
:value_changes => {
|
38
|
+
0.5 => linear_change(tempo(60), 0.25)
|
39
|
+
}
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '.new' do
|
44
|
+
it "should assign tempo profile given during construction" do
|
45
|
+
score = TempoScore.new :tempo_profile => @tempo_profile
|
46
|
+
score.tempo_profile.should eq(@tempo_profile)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should assign part and program given during construction" do
|
50
|
+
score = TempoScore.new :tempo_profile => @tempo_profile, :parts => @parts, :program => @program
|
51
|
+
score.parts.should eq(@parts)
|
52
|
+
score.program.should eq(@program)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|