music-transcription 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2519d2fe69e6b6d5944695bae502dece8dd456c9
4
- data.tar.gz: b4da4b389692c5eb70bb2505d003a783fd565833
3
+ metadata.gz: 2b53782c68a60ec01fd23022b00fa7ee67a76c6c
4
+ data.tar.gz: 22433554e9566a3841800f4ab757268160e2b5f1
5
5
  SHA512:
6
- metadata.gz: 80a849288ffc1c279b5083ea6d878bb7de606d9f69b6885263945a5b95e1617a5c33cea586639fa8560c6ef72c4669892c2a4c913a0a0234d2b38d46693d36dd
7
- data.tar.gz: a4ca68fad70b5cee5939fa319e23a0fc3580ed0b3016e03b2046ea3e56f1f84d5610c9857f31ac29f409c8b673f4b6b4d3b762f02366dd02132bd72543a1c995
6
+ metadata.gz: b6fc8591be37735700427c607dac2cc71706287eb704e9179a4077c99a92d6a7f03c70ee3c9ded54115f5f0a54ad444640bc8cb85c206be849a0e32261fdc34c
7
+ data.tar.gz: 5c9bc76ed55f0f729fbf0caf384c7aaad4aa0e3f9f72961995d1bb3cf2f78604b0f3ffcc268bacb2f7eae055a63e9736f265e1377f0cbc8ece39bab2af20616a
@@ -18,8 +18,12 @@ class Link
18
18
  self.class == other.class
19
19
  end
20
20
 
21
+ def transpose diff
22
+ self.clone.transpose! diff
23
+ end
24
+
21
25
  def transpose! diff
22
- # do nothing, of course
26
+ return self
23
27
  end
24
28
 
25
29
  def to_s; "="; end
@@ -37,8 +41,12 @@ class Link
37
41
  self.class == other.class && @target_pitch == other.target_pitch
38
42
  end
39
43
 
44
+ def transpose diff
45
+ self.clone.transpose! diff
46
+ end
47
+
40
48
  def transpose! diff
41
- @target_pitch += diff
49
+ @target_pitch = @target_pitch.transpose(diff)
42
50
  end
43
51
 
44
52
  def to_s
@@ -43,17 +43,10 @@ class Note
43
43
  end
44
44
 
45
45
  def transpose! diff
46
- unless diff.is_a?(Pitch)
47
- diff = Pitch.from_semitones(diff)
48
- end
49
-
50
- @pitches = @pitches.map {|pitch| pitch + diff}
51
- new_links = {}
52
- @links.each_pair do |k,v|
53
- v.transpose! diff
54
- new_links[k + diff] = v
55
- end
56
- @links = new_links
46
+ @pitches = @pitches.map {|pitch| pitch.transpose(diff) }
47
+ @links = Hash[ @links.map do |k,v|
48
+ [ k.transpose(diff), v.transpose(diff) ]
49
+ end ]
57
50
  return self
58
51
  end
59
52
 
@@ -20,7 +20,7 @@ module Transcription
20
20
  #
21
21
  class Pitch
22
22
  include Comparable
23
- attr_reader :octave, :semitone
23
+ attr_reader :octave, :semitone, :total_semitone
24
24
 
25
25
  #The default number of semitones per octave is 12, corresponding to
26
26
  # the twelve-tone equal temperment tuning system.
@@ -33,6 +33,7 @@ class Pitch
33
33
  @octave = octave
34
34
  @semitone = semitone
35
35
  normalize!
36
+ @total_semitone = @octave*SEMITONES_PER_OCTAVE + @semitone
36
37
  end
37
38
 
38
39
  # Return the pitch's frequency, which is determined by multiplying the base
@@ -43,40 +44,22 @@ class Pitch
43
44
  return self.ratio() * BASE_FREQ
44
45
  end
45
46
 
46
- # Calculate the total semitone count. Converts octave to semitone count
47
- # before adding to existing semitone count.
48
- # @return [Fixnum] total semitone count
49
- def total_semitone
50
- return (@octave * SEMITONES_PER_OCTAVE) + @semitone
51
- end
52
-
53
47
  # Calculate the pitch ratio. Raises 2 to the power of the total semitone
54
48
  # count divided by semitones-per-octave.
55
49
  # @return [Float] ratio
56
50
  def ratio
57
- 2.0**(self.total_semitone.to_f / SEMITONES_PER_OCTAVE)
58
- end
59
-
60
- # Round to the nearest semitone.
61
- def round
62
- self.clone.round!
63
- end
64
-
65
- # Calculates the number of semitones which would represent the pitch's
66
- # octave and semitone count
67
- def total_semitone
68
- return (@octave * SEMITONES_PER_OCTAVE) + @semitone
51
+ 2.0**(@total_semitone.to_f / SEMITONES_PER_OCTAVE)
69
52
  end
70
53
 
71
54
  # Override default hash method.
72
55
  def hash
73
- return self.total_semitone
56
+ return @total_semitone
74
57
  end
75
58
 
76
59
  # Compare pitch equality using total semitone
77
60
  def ==(other)
78
61
  return (self.class == other.class &&
79
- self.total_semitone == other.total_semitone)
62
+ @total_semitone == other.total_semitone)
80
63
  end
81
64
 
82
65
  def eql?(other)
@@ -86,29 +69,15 @@ class Pitch
86
69
  # Compare pitches. A higher ratio or total semitone is considered larger.
87
70
  # @param [Pitch] other The pitch object to compare.
88
71
  def <=> (other)
89
- self.total_semitone <=> other.total_semitone
72
+ @total_semitone <=> other.total_semitone
90
73
  end
91
-
92
- # Add pitches by adding the total semitone count of each.
93
- # @param [Pitch] other The pitch object to add.
94
- def + (other)
95
- if other.is_a? Integer
96
- return Pitch.new(octave: @octave, semitone: @semitone + other)
97
- else
98
- return Pitch.new(octave: (@octave + other.octave),
99
- semitone: (@semitone + other.semitone))
100
- end
74
+
75
+ def diff other
76
+ @total_semitone - other.total_semitone
101
77
  end
102
-
103
- # Add pitches by subtracting the total semitone count.
104
- # @param [Pitch] other The pitch object to subtract.
105
- def - (other)
106
- if other.is_a? Integer
107
- return Pitch.new(octave: @octave, semitone: @semitone - other)
108
- else
109
- return Pitch.new(octave: (@octave - other.octave),
110
- semitone: (@semitone - other.semitone))
111
- end
78
+
79
+ def transpose interval
80
+ Pitch.from_semitones @total_semitone + interval
112
81
  end
113
82
 
114
83
  # Produce an identical Pitch object.
@@ -2,6 +2,6 @@
2
2
  module Music
3
3
  module Transcription
4
4
  # music-transcription version
5
- VERSION = "0.14.0"
5
+ VERSION = "0.15.0"
6
6
  end
7
7
  end
@@ -64,61 +64,44 @@ describe Note do
64
64
  end
65
65
  end
66
66
 
67
- describe '#transpose!' do
67
+ describe '#transpose' do
68
68
  context 'given pitch diff' do
69
69
  before(:all) do
70
- @note = Note::quarter([C2,F2], links:{C2=>Link::Glissando.new(D2)})
71
- @diff = Pitch.new(semitone: 4)
72
- @note.transpose! @diff
70
+ @note1 = Note::quarter([C2,F2], links:{C2=>Link::Glissando.new(D2)})
71
+ @interval = 4
72
+ @note2 = @note1.transpose(@interval)
73
73
  end
74
74
 
75
75
  it 'should modifiy pitches by adding pitch diff' do
76
- @note.pitches[0].should eq E2
77
- @note.pitches[1].should eq A2
76
+ @note2.pitches.each_with_index do |p,i|
77
+ p.diff(@note1.pitches[i]).should eq(@interval)
78
+ end
78
79
  end
79
80
 
80
81
  it 'should also affect link targets' do
81
- @note.links.should have_key(E2)
82
- @note.links[E2].target_pitch.should eq(Gb2)
83
- end
84
- end
85
-
86
- context 'given integer diff' do
87
- it 'should transpose the given number of semitones' do
88
- Note::quarter([C2]).transpose!(4).pitches[0].should eq(E2)
82
+ @note1.links.each do |k,v|
83
+ kt = k.transpose(@interval)
84
+ @note2.links.should have_key kt
85
+ @note2.links[kt].target_pitch.should eq(v.target_pitch.transpose(@interval))
86
+ end
89
87
  end
90
88
  end
91
89
 
92
90
  context 'with links that have no target pitch' do
93
91
  it 'should not raise error' do
94
92
  n = Note::half([E2],links: {E2 => Link::Tie.new})
95
- expect { n.transpose!(1) }.to_not raise_error
93
+ expect { n.transpose(1) }.to_not raise_error
96
94
  end
97
95
  end
98
-
99
- it 'should return self' do
100
- n = Note::quarter
101
- n.transpose!(0).should eq n
102
- end
103
96
  end
104
97
 
105
- describe '#stretch!' do
98
+ describe '#stretch' do
106
99
  it 'should multiply note duration by ratio' do
107
- note = Note::quarter
108
- note.stretch!(2)
100
+ note = Note::quarter.stretch(2)
109
101
  note.duration.should eq(Rational(1,2))
110
102
 
111
- note = Note::quarter
112
- note.stretch!(Rational(1,2))
103
+ note = Note::quarter.stretch(Rational(1,2))
113
104
  note.duration.should eq(Rational(1,8))
114
- note = Note::quarter
115
- note.stretch!(2)
116
- note.duration.should eq(Rational(1,2))
117
- end
118
-
119
- it 'should return self' do
120
- note = Note::quarter
121
- note.stretch!(1).should be note
122
105
  end
123
106
  end
124
107
 
@@ -40,6 +40,23 @@ describe Pitch do
40
40
  p.total_semitone.should be case_data[:total_semitone]
41
41
  end
42
42
  end
43
+
44
+ describe '#diff' do
45
+ it 'should return the difference between the given pitch, in semitones' do
46
+ C5.diff(C4).should eq(12)
47
+ C5.diff(D5).should eq(-2)
48
+ D5.diff(C5).should eq(2)
49
+ end
50
+ end
51
+
52
+ describe '#transpose' do
53
+ it 'should add the given interval to total semitones' do
54
+ [0,1,2,5,12,13,-1,-2,-5,-12,-13].each do |interval|
55
+ pitch = Eb3.transpose(interval)
56
+ pitch.diff(Eb3).should eq(interval)
57
+ end
58
+ end
59
+ end
43
60
 
44
61
  describe '.from_ratio' do
45
62
  it 'should return a Pitch with given ratio' do
@@ -90,38 +107,6 @@ describe Pitch do
90
107
  p3.should be > p1
91
108
  p2.should be > p1
92
109
  end
93
-
94
- it "should be addable and subtractable with other pitches" do
95
- p1 = Pitch.new semitone: 1
96
- p2 = Pitch.new semitone: 2
97
- p3 = Pitch.new semitone: 3
98
-
99
- (p1 + p2).should eq(Pitch.new semitone: 3)
100
- (p1 + p3).should eq(Pitch.new semitone: 4)
101
- (p2 + p3).should eq(Pitch.new semitone: 5)
102
-
103
- (p1 - p2).should eq(Pitch.new semitone: -1)
104
- (p1 - p3).should eq(Pitch.new semitone: -2)
105
- (p2 - p3).should eq(Pitch.new semitone: -1)
106
- (p3 - p2).should eq(Pitch.new semitone: 1)
107
- (p3 - p1).should eq(Pitch.new semitone: 2)
108
- end
109
-
110
- it "should be addable and subtractable with integers" do
111
- p1 = Pitch.new semitone: 1
112
- p2 = Pitch.new semitone: 2
113
- p3 = Pitch.new semitone: 3
114
-
115
- (p1 + 2).should eq(Pitch.new semitone: 3)
116
- (p1 + 3).should eq(Pitch.new semitone: 4)
117
- (p2 + 3).should eq(Pitch.new semitone: 5)
118
-
119
- (p1 - 2).should eq(Pitch.new semitone: -1)
120
- (p1 - 3).should eq(Pitch.new semitone: -2)
121
- (p2 - 3).should eq(Pitch.new semitone: -1)
122
- (p3 - 2).should eq(Pitch.new semitone: 1)
123
- (p3 - 1).should eq(Pitch.new semitone: 2)
124
- end
125
110
 
126
111
  it "should have freq of 440 for A4" do
127
112
  a4 = Pitch.new octave: 4, semitone: 9
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: music-transcription
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Tunnell