music-transcription 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,6 @@
2
2
  module Music
3
3
  module Transcription
4
4
  # music-transcription version
5
- VERSION = "0.3.0"
5
+ VERSION = "0.4.0"
6
6
  end
7
7
  end
@@ -13,23 +13,18 @@ a common representation enables composition and performance.
13
13
  DESCRIPTION
14
14
  gem.license = "MIT"
15
15
  gem.authors = ["James Tunnell"]
16
- gem.email = "jamestunnell@lavabit.com"
16
+ gem.email = "jamestunnell@gmail.com"
17
17
  gem.homepage = "https://github.com/jamestunnell/music-transcription"
18
18
 
19
19
  gem.files = `git ls-files`.split($/)
20
20
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
21
21
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
22
22
  gem.require_paths = ['lib']
23
-
24
- gem.add_dependency 'hashmake'
25
- # gem.add_dependency 'spnet'
26
- # gem.add_dependency 'spcore'
27
- # gem.add_dependency 'micro-optparse'
28
- # gem.add_dependency 'wavefile'
29
23
 
30
- gem.add_development_dependency 'bundler', '~> 1.0'
31
- gem.add_development_dependency 'rake', '~> 0.8'
32
- gem.add_development_dependency 'rspec', '~> 2.4'
24
+ gem.add_development_dependency 'bundler', '~> 1.5'
25
+ gem.add_development_dependency 'rubygems-bundler', '~> 1.4'
26
+ gem.add_development_dependency 'rake', '~> 10.1'
27
+ gem.add_development_dependency 'rspec', '~> 2.14'
33
28
  gem.add_development_dependency 'yard', '~> 0.8'
34
29
  gem.add_development_dependency 'pry'
35
30
  gem.add_development_dependency 'pry-nav'
data/spec/link_spec.rb CHANGED
@@ -2,21 +2,25 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe Link do
4
4
  context '.new' do
5
- its(:relationship) { should eq(Link::RELATIONSHIP_NONE) }
6
- its(:target_pitch) { should eq(Pitch.new) }
5
+ it 'should assign the given pitch to :target_pitch' do
6
+ Link.new(C2).target_pitch.should eq(C2)
7
+ end
7
8
  end
8
9
 
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)
10
+ describe '==' do
11
+ it 'should return true if two links have the same target pitch' do
12
+ Link.new(C2).should eq(Link.new(C2))
13
+ end
14
+
15
+ it 'should return false if two links do not have the same target pitch' do
16
+ Link.new(C2).should_not eq(Link.new(F5))
13
17
  end
14
18
  end
15
19
 
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
+ describe 'clone' do
21
+ it 'should return a link with the same target pitch' do
22
+ l = Link.new(C4)
23
+ l.clone.should eq(l)
20
24
  end
21
25
  end
22
26
  end
data/spec/note_spec.rb CHANGED
@@ -7,59 +7,32 @@ describe Note do
7
7
 
8
8
  context '.new' do
9
9
  it 'should assign :duration that is given during construction' do
10
- note = Note.new :duration => 2
10
+ note = Note.new 2
11
11
  note.duration.should eq(2)
12
12
  end
13
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)
14
+ it "should assign :accent parameter if given during construction" do
15
+ note = Note.new 2, accent: Accent::Stacatto.new
16
+ note.accent.class.should eq(Accent::Stacatto)
19
17
  end
20
18
 
21
- it 'should have no intervals if not given' do
22
- Note.new(:duration => 2).intervals.should be_empty
19
+ it 'should have no pitches if not given' do
20
+ Note.new(2).pitches.should be_empty
23
21
  end
24
22
 
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)
23
+ it 'should assign pitches when given' do
24
+ pitches = [ C2, D2 ]
25
+ n = Note.new(2, pitches)
26
+ n.pitches.should include(pitches[0])
27
+ n.pitches.should include(pitches[1])
31
28
  end
32
29
  end
33
30
 
34
31
  context '#duration=' do
35
32
  it 'should assign duration' do
36
- note = Note.new :pitch => @pitch, :duration => 2
33
+ note = Note.new 2, [@pitch]
37
34
  note.duration = 3
38
35
  note.duration.should eq 3
39
36
  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
37
+ end
65
38
  end
data/spec/part_spec.rb CHANGED
@@ -2,86 +2,18 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe Part do
4
4
  context '.new' do
5
- its(:offset) { should eq(0) }
6
5
  its(:notes) { should be_empty }
7
6
 
8
7
  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
8
+ loudness_profile = Profile.new(0.5, 1.0 => linear_change(1.0, 2.0))
9
+ part = Part.new loudness_profile: loudness_profile
16
10
  part.loudness_profile.should eq(loudness_profile)
17
11
  end
18
12
 
19
13
  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
14
+ notes = [ Note.new(0.25, [C1,D1]) ]
15
+ part = Part.new notes: notes
31
16
  part.notes.should eq(notes)
32
17
  end
33
18
  end
34
19
  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 CHANGED
@@ -5,17 +5,17 @@ describe Pitch do
5
5
  before :each do
6
6
  @cases =
7
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 },
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
19
  ]
20
20
  end
21
21
 
@@ -24,7 +24,7 @@ describe Pitch do
24
24
  end
25
25
 
26
26
  it "should be hash-makeable" do
27
- obj = Pitch.new :octave => 4, :semitone => 3
27
+ obj = Pitch.new octave: 4, semitone: 3
28
28
  obj.octave.should eq(4)
29
29
  obj.semitone.should eq(3)
30
30
  obj.cent.should eq(0)
@@ -38,7 +38,7 @@ describe Pitch do
38
38
 
39
39
  it "should use the octave, semitone, and cent given during construction" do
40
40
  @cases.each do |case_data|
41
- p = Pitch.new :octave => case_data[:octave], :semitone => case_data[:semitone], :cent => case_data[:cent]
41
+ p = Pitch.new octave: case_data[:octave], semitone: case_data[:semitone], cent: case_data[:cent]
42
42
  p.ratio.should be_within(0.01).of case_data[:ratio]
43
43
  p.total_cent.should be case_data[:total_cent]
44
44
  end
@@ -69,13 +69,13 @@ describe Pitch do
69
69
  end
70
70
 
71
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
72
+ p1 = Pitch.new semitone: 1
73
+ p2 = Pitch.new semitone: 2
74
+ p3 = Pitch.new semitone: 3
75
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)
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
79
 
80
80
  p1.should be < p2
81
81
  p1.should be < p3
@@ -86,36 +86,36 @@ describe Pitch do
86
86
  end
87
87
 
88
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
89
+ p1 = Pitch.new semitone: 1
90
+ p2 = Pitch.new semitone: 2
91
+ p3 = Pitch.new semitone: 3
92
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)
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
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)
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
102
  end
103
103
 
104
104
  it "should have freq of 440 for A4" do
105
- a4 = Pitch.new :octave => 4, :semitone => 9
105
+ a4 = Pitch.new octave: 4, semitone: 9
106
106
  a4.freq.should be_within(0.01).of(440.0)
107
107
  end
108
108
 
109
109
  context 'String#to_pitch' do
110
110
  it 'should create a Pitch object that matches the musical note' do
111
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),
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
119
  }.each do |str, expected_pitch|
120
120
  str.to_pitch.should eq(expected_pitch)
121
121
  end
@@ -124,7 +124,7 @@ describe Pitch do
124
124
 
125
125
  context '.make_from_freq' do
126
126
  it 'should make a pitch whose freq is approximately the given freq' do
127
- one_cent = Pitch.new(:cent => 1)
127
+ one_cent = Pitch.new(cent: 1)
128
128
  [1.0, 25.0, 200.0, 3500.0].each do |given_freq|
129
129
  pitch = Pitch.make_from_freq given_freq
130
130
  freq = pitch.freq
data/spec/profile_spec.rb CHANGED
@@ -4,17 +4,14 @@ describe Profile do
4
4
 
5
5
  context '.new' do
6
6
  it "should assign start value given during construction" do
7
- p = Profile.new(:start_value => 0.2)
7
+ p = Profile.new(0.2)
8
8
  p.start_value.should eq(0.2)
9
9
  end
10
10
 
11
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
- }
12
+ p = Profile.new(0.2,
13
+ 1.0 => ValueChange.new(0.5),
14
+ 1.5 => ValueChange.new(1.0)
18
15
  )
19
16
  p.value_changes[1.0].value.should eq(0.5)
20
17
  p.value_changes[1.5].value.should eq(1.0)
data/spec/program_spec.rb CHANGED
@@ -4,14 +4,14 @@ describe Program do
4
4
 
5
5
  it "should assign the segments given during initialization" do
6
6
  segments = [ 0.0...5.0, 0.0...4.0, 5.0...10.0 ]
7
- program = Program.new :segments => segments
7
+ program = Program.new segments
8
8
  program.segments.should eq(segments.clone)
9
9
  end
10
10
 
11
11
  describe "#include?" do
12
12
  it "should return true for any offset which would be encountered" do
13
13
  segments = [ 0.0...5.0, 0.0...4.0, 5.0...10.0 ]
14
- program = Program.new :segments => segments
14
+ program = Program.new segments
15
15
 
16
16
  [0.0, 4.0, 5.0, 9.999].each do |offset|
17
17
  program.include?(offset).should be_true
@@ -20,7 +20,7 @@ describe Program do
20
20
 
21
21
  it "should return false for any offset which would not be encountered" do
22
22
  segments = [ 0.0...5.0, 0.0...4.0, 5.0...10.0 ]
23
- program = Program.new :segments => segments
23
+ program = Program.new segments
24
24
 
25
25
  [-0.000001, 10.000001].each do |offset|
26
26
  program.include?(offset).should be_false
@@ -31,15 +31,15 @@ describe Program do
31
31
  describe "#note_elapsed_at" do
32
32
  before :each do
33
33
  segments = [ 0.0...5.0, 0.0...4.0, 5.0..10.0 ]
34
- @program = Program.new :segments => segments
34
+ @program = Program.new segments
35
35
  end
36
36
 
37
37
  it "should return 0.0 at program start" do
38
- @program.note_elapsed_at(@program.start).should eq(0.0)
38
+ @program.note_elapsed_at(@program.segments.first.first).should eq(0.0)
39
39
  end
40
40
 
41
41
  it "should return program length at program stop" do
42
- @program.note_elapsed_at(@program.stop).should eq(@program.length)
42
+ @program.note_elapsed_at(@program.segments.last.last).should eq(@program.length)
43
43
  end
44
44
 
45
45
  it "should return correct note elapsed for any included offset" do
data/spec/score_spec.rb CHANGED
@@ -1,14 +1,14 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe Score do
3
+ describe TimeScore do
4
4
  before :each do
5
5
  @parts = { "piano (LH)" => Samples::SAMPLE_PART }
6
- @program = Program.new :segments => [0...0.75, 0...0.75]
6
+ @program = Program.new [0...0.75, 0...0.75]
7
7
  end
8
8
 
9
9
  describe '.new' do
10
10
  context "no args given" do
11
- let(:score) { Score.new }
11
+ let(:score) { TimeScore.new }
12
12
  subject { score }
13
13
  its(:program) { should eq(Program.new) }
14
14
  its(:parts) { should be_empty }
@@ -16,12 +16,12 @@ describe Score do
16
16
 
17
17
  context 'args given' do
18
18
  it "should assign parts given during construction" do
19
- score = Score.new :program => @program, :parts => @parts
19
+ score = TimeScore.new :program => @program, :parts => @parts
20
20
  score.parts.should eq(@parts)
21
21
  end
22
22
 
23
23
  it "should assign program given during construction" do
24
- score = Score.new :program => @program
24
+ score = TimeScore.new :program => @program
25
25
  score.program.should eq(@program)
26
26
  end
27
27
  end
@@ -31,23 +31,18 @@ end
31
31
  describe TempoScore do
32
32
  before :each do
33
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
- )
34
+ @program = Program.new [0...0.75, 0...0.75]
35
+ @tempo_profile = Profile.new(Tempo.new(120), 0.5 => linear_change(Tempo.new(60), 0.25))
41
36
  end
42
37
 
43
38
  describe '.new' do
44
39
  it "should assign tempo profile given during construction" do
45
- score = TempoScore.new :tempo_profile => @tempo_profile
40
+ score = TempoScore.new @tempo_profile
46
41
  score.tempo_profile.should eq(@tempo_profile)
47
42
  end
48
43
 
49
44
  it "should assign part and program given during construction" do
50
- score = TempoScore.new :tempo_profile => @tempo_profile, :parts => @parts, :program => @program
45
+ score = TempoScore.new @tempo_profile, parts: @parts, program: @program
51
46
  score.parts.should eq(@parts)
52
47
  score.program.should eq(@program)
53
48
  end