Class: MTK::Core::Pitch

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/mtk/core/pitch.rb

Overview

A frequency represented by a PitchClass, an integer octave, and an offset in semitones.

See Also:

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pitch_class, octave, offset = 0) ⇒ Pitch

Returns a new instance of Pitch.



13
14
15
16
# File 'lib/mtk/core/pitch.rb', line 13

def initialize( pitch_class, octave, offset=0 )
  @pitch_class, @octave, @offset = pitch_class, octave, offset
  @value = @pitch_class.to_i + 12*(@octave+1) + @offset
end

Instance Attribute Details

#octaveObject (readonly)

Returns the value of attribute octave.



11
12
13
# File 'lib/mtk/core/pitch.rb', line 11

def octave
  @octave
end

#offsetObject (readonly)

Returns the value of attribute offset.



11
12
13
# File 'lib/mtk/core/pitch.rb', line 11

def offset
  @offset
end

#pitch_classObject (readonly)

Returns the value of attribute pitch_class.



11
12
13
# File 'lib/mtk/core/pitch.rb', line 11

def pitch_class
  @pitch_class
end

Class Method Details

.[](pitch_class, octave) ⇒ Object

Return a pitch with no offset, only constructing a new instance when not already in the flyweight cache



21
22
23
24
# File 'lib/mtk/core/pitch.rb', line 21

def self.[](pitch_class, octave)
  pitch_class = MTK.PitchClass(pitch_class)
  @flyweight[[pitch_class,octave]] ||= new(pitch_class, octave)
end

.from_f(f) ⇒ Object

Convert a Numeric semitones value into a Pitch



55
56
57
58
59
60
61
62
63
64
# File 'lib/mtk/core/pitch.rb', line 55

def self.from_f( f )
  i, offset = f.floor, f%1  # split into int and fractional part
  pitch_class = PitchClass.from_i(i)
  octave = i/12 - 1
  if offset == 0
    self[pitch_class, octave]
  else
    new( pitch_class, octave, offset )
  end
end

.from_h(hash) ⇒ Object



66
67
68
# File 'lib/mtk/core/pitch.rb', line 66

def self.from_h(hash)
  new hash[:pitch_class], hash[:octave], hash.fetch(:offset,0)
end

.from_i(i) ⇒ Object

Convert a Numeric semitones value into a Pitch



71
72
73
# File 'lib/mtk/core/pitch.rb', line 71

def self.from_i( i )
  from_f( i )
end

.from_s(name) ⇒ Object Also known as: from_name

Lookup a pitch by name, which consists of any MTK::Core::PitchClass::VALID_NAMES and an octave number. The name may also be optionally suffixed by +/-###cents (where ### is any number).

Examples:

get the Pitch for middle C :

Pitch.from_s('C4')

get the Pitch for middle C + 50 cents:

Pitch.from_s('C4+50cents')

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/mtk/core/pitch.rb', line 32

def self.from_s( name )
  s = name.to_s
  s = s[0..0].upcase + s[1..-1].downcase # normalize name
  if s =~ /^([A-G](#|##|b|bb)?)(-?\d+)(\+(\d+(\.\d+)?)cents)?$/
    pitch_class = PitchClass.from_s($1)
    if pitch_class
      octave = $3.to_i
      offset_in_cents = $5.to_f
      if offset_in_cents.nil? or offset_in_cents.zero?
        return self[pitch_class, octave]
      else
        return new( pitch_class, octave, offset_in_cents/100.0 )
      end
    end
  end
  raise ArgumentError.new("Invalid pitch name: #{name.inspect}")
end

Instance Method Details

#+(interval_in_semitones) ⇒ Object Also known as: transpose



110
111
112
# File 'lib/mtk/core/pitch.rb', line 110

def + interval_in_semitones
 self.class.from_f( @value + interval_in_semitones.to_f )
end

#-(interval_in_semitones) ⇒ Object



115
116
117
# File 'lib/mtk/core/pitch.rb', line 115

def - interval_in_semitones
  self.class.from_f( @value - interval_in_semitones.to_f )
end

#<=>(other) ⇒ Object



106
107
108
# File 'lib/mtk/core/pitch.rb', line 106

def <=> other
  @value <=> other.to_f
end

#==(other) ⇒ Object



101
102
103
104
# File 'lib/mtk/core/pitch.rb', line 101

def ==( other )
  other.respond_to? :pitch_class and other.respond_to? :octave and other.respond_to? :offset and
  other.pitch_class == @pitch_class and other.octave == @octave and other.offset == @offset
end

#clone_with(hash) ⇒ Object



131
132
133
# File 'lib/mtk/core/pitch.rb', line 131

def clone_with(hash)
  self.class.from_h(to_h.merge hash)
end

#coerce(other) ⇒ Object



127
128
129
# File 'lib/mtk/core/pitch.rb', line 127

def coerce(other)
  return self.class.from_f(other.to_f), self
end

#inspectObject



97
98
99
# File 'lib/mtk/core/pitch.rb', line 97

def inspect
  "#<#{self.class}:#{object_id} @value=#{@value}>"
end

#invert(center_pitch) ⇒ Object



119
120
121
# File 'lib/mtk/core/pitch.rb', line 119

def invert(center_pitch)
  self + 2*(center_pitch.to_f - to_f)
end

#nearest(pitch_class) ⇒ Object



123
124
125
# File 'lib/mtk/core/pitch.rb', line 123

def nearest(pitch_class)
  self + self.pitch_class.distance_to(pitch_class)
end

#offset_in_centsObject



85
86
87
# File 'lib/mtk/core/pitch.rb', line 85

def offset_in_cents
  @offset * 100
end

#to_fObject

The numerical value of this pitch



76
77
78
# File 'lib/mtk/core/pitch.rb', line 76

def to_f
  @value
end

#to_hObject



89
90
91
# File 'lib/mtk/core/pitch.rb', line 89

def to_h
  {:pitch_class => @pitch_class, :octave => @octave, :offset => @offset}
end

#to_iObject

The numerical value for the nearest semitone



81
82
83
# File 'lib/mtk/core/pitch.rb', line 81

def to_i
  @value.round
end

#to_sObject



93
94
95
# File 'lib/mtk/core/pitch.rb', line 93

def to_s
  "#{@pitch_class}#{@octave}" + (@offset.zero? ? '' : "+#{offset_in_cents.round}cents")
end