class Music::Transcription::Pitch

@author James Tunnell

@!attribute [r] octave

@return [Fixnum] The pitch octave.

@!attribute [r] semitone

@return [Fixnum] The pitch semitone.

Constants

BASE_FREQ

The base ferquency is C0

CENTS_PER_OCTAVE
CENTS_PER_SEMITONE
CONVERSION_METHOD
PARSER
SEMITONES_PER_OCTAVE

The default number of semitones per octave is 12, corresponding to

the twelve-tone equal temperment tuning system.

Attributes

cent[R]
octave[R]
semitone[R]
total_cents[R]

Public Class Methods

from_freq(freq) click to toggle source
# File lib/music-transcription/model/pitch.rb, line 143
def self.from_freq freq
  from_ratio(freq / BASE_FREQ)
end
from_ratio(ratio) click to toggle source
# File lib/music-transcription/model/pitch.rb, line 137
def self.from_ratio ratio
  raise NonPositiveError, "ratio #{ratio} is not > 0" unless ratio > 0
  x = Math.log2 ratio
  new(cent: (x * CENTS_PER_OCTAVE).round)
end
from_semitones(semitones) click to toggle source
# File lib/music-transcription/model/pitch.rb, line 104
def self.from_semitones semitones
  Pitch.new(cent: (semitones * CENTS_PER_SEMITONE).round)
end
new(octave:0, semitone:0, cent: 0) click to toggle source
# File lib/music-transcription/model/pitch.rb, line 34
def initialize octave:0, semitone:0, cent: 0
  raise NonIntegerError, "octave #{octave} is not an integer" unless octave.is_a?(Integer)
  raise NonIntegerError, "semitone #{semitone} is not an integer" unless semitone.is_a?(Integer)
  raise NonIntegerError, "cent #{cent} is not an integer" unless cent.is_a?(Integer)
  
  @octave = octave
  @semitone = semitone
  @cent = cent
  @total_cents = (@octave*SEMITONES_PER_OCTAVE + @semitone)*CENTS_PER_SEMITONE + @cent
  balance!
end

Public Instance Methods

<=>(other) click to toggle source

Compare pitches. A higher ratio or total semitone is considered larger. @param [Pitch] other The pitch object to compare.

# File lib/music-transcription/model/pitch.rb, line 78
def <=> (other)
  @total_cents <=> other.total_cents
end
==(other) click to toggle source

Compare pitch equality using total semitone

# File lib/music-transcription/model/pitch.rb, line 67
def ==(other)
  return (self.class == other.class &&
    @total_cents == other.total_cents)
end
clone() click to toggle source
# File lib/music-transcription/model/pitch.rb, line 108
def clone
  Pitch.new(cent: @total_cents)
end
diff(other) click to toggle source

diff in (rounded) semitones

# File lib/music-transcription/model/pitch.rb, line 92
def diff other
  Rational(@total_cents - other.total_cents, CENTS_PER_SEMITONE)
end
eql?(other) click to toggle source
# File lib/music-transcription/model/pitch.rb, line 72
def eql?(other)
  self == other
end
freq() click to toggle source

Return the pitch’s frequency, which is determined by multiplying the base frequency and the pitch ratio. Base frequency defaults to DEFAULT_BASE_FREQ, but can be set during initialization to something else by specifying the :base_freq key.

# File lib/music-transcription/model/pitch.rb, line 50
def freq
  return self.ratio() * BASE_FREQ
end
hash() click to toggle source

Override default hash method.

# File lib/music-transcription/model/pitch.rb, line 62
def hash
  return @total_cents
end
ratio() click to toggle source

Calculate the pitch ratio. Raises 2 to the power of the total cent count divided by cents-per-octave. @return [Float] ratio

# File lib/music-transcription/model/pitch.rb, line 57
def ratio
  2.0**(@total_cents.to_f / CENTS_PER_OCTAVE)
end
round() click to toggle source

rounds to the nearest semitone

# File lib/music-transcription/model/pitch.rb, line 83
def round
  if @cent == 0
    self.clone
  else
    Pitch.new(semitone: (@total_cents / CENTS_PER_SEMITONE.to_f).round)
  end
end
to_s(sharpit = false) click to toggle source
# File lib/music-transcription/model/pitch.rb, line 112
def to_s(sharpit = false)
  letter = case semitone
  when 0 then "C"
  when 1 then sharpit  ? "C#" : "Db"
  when 2 then "D"
  when 3 then sharpit  ? "D#" : "Eb"
  when 4 then "E"
  when 5 then "F"
  when 6 then sharpit  ? "F#" : "Gb"
  when 7 then "G"
  when 8 then sharpit  ? "G#" : "Ab"
  when 9 then "A"
  when 10 then sharpit  ? "A#" : "Bb"
  when 11 then "B"
  end
  
  if @cent == 0
    return letter + octave.to_s
  elsif @cent > 0
    return letter + octave.to_s + "+" + @cent.to_s
  else
    return letter + octave.to_s + @cent.to_s
  end
end
total_semitones() click to toggle source
# File lib/music-transcription/model/pitch.rb, line 100
def total_semitones
  Rational(@total_cents, CENTS_PER_SEMITONE)
end
transpose(semitones) click to toggle source
# File lib/music-transcription/model/pitch.rb, line 96
def transpose semitones
  Pitch.new(cent: (@total_cents + semitones * CENTS_PER_SEMITONE).round)
end

Private Instance Methods

balance!() click to toggle source

Balance out the octave and semitone count.

# File lib/music-transcription/model/pitch.rb, line 150
def balance!
  centsTotal = @total_cents
  
  @octave = centsTotal / CENTS_PER_OCTAVE
  centsTotal -= @octave * CENTS_PER_OCTAVE
  
  @semitone = centsTotal / CENTS_PER_SEMITONE
  centsTotal -= @semitone * CENTS_PER_SEMITONE
  
  @cent = centsTotal
  return self
end