Class: HeadMusic::Pitch

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

Overview

A pitch is a named frequency represented by a spelling and a register.

Defined Under Namespace

Classes: EnharmonicEquivalence, OctaveEquivalence

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(spelling, register) ⇒ Pitch

Returns a new instance of Pitch.



87
88
89
90
# File 'lib/head_music/pitch.rb', line 87

def initialize(spelling, register)
  @spelling = HeadMusic::Spelling.get(spelling.to_s)
  @register = register.to_i
end

Instance Attribute Details

#registerObject (readonly)

Returns the value of attribute register.



7
8
9
# File 'lib/head_music/pitch.rb', line 7

def register
  @register
end

#spellingObject (readonly)

Returns the value of attribute spelling.



7
8
9
# File 'lib/head_music/pitch.rb', line 7

def spelling
  @spelling
end

Class Method Details

.concert_aObject



40
41
42
# File 'lib/head_music/pitch.rb', line 40

def self.concert_a
  get("A4")
end

.fetch_or_create(spelling, register = nil) ⇒ Object



78
79
80
81
82
83
84
85
# File 'lib/head_music/pitch.rb', line 78

def self.fetch_or_create(spelling, register = nil)
  register ||= HeadMusic::Register::DEFAULT
  return unless spelling && (-1..9).cover?(register)

  @pitches ||= {}
  hash_key = [spelling, register].join
  @pitches[hash_key] ||= new(spelling, register)
end

.from_name(name) ⇒ Object



50
51
52
53
54
# File 'lib/head_music/pitch.rb', line 50

def self.from_name(name)
  return nil unless name == name.to_s

  fetch_or_create(HeadMusic::Spelling.get(name), HeadMusic::Register.get(name).to_i)
end

.from_number(number) ⇒ Object



56
57
58
59
60
# File 'lib/head_music/pitch.rb', line 56

def self.from_number(number)
  return nil unless number == number.to_i

  fetch_or_create(HeadMusic::Spelling.from_number(number), (number.to_i / 12) - 1)
end

.from_number_and_letter(number, letter_name) ⇒ Object



62
63
64
65
66
67
68
69
# File 'lib/head_music/pitch.rb', line 62

def self.from_number_and_letter(number, letter_name)
  letter_name = HeadMusic::LetterName.get(letter_name)
  natural_letter_pitch = natural_letter_pitch(number, letter_name)
  sign_interval = natural_letter_pitch.smallest_interval_to(HeadMusic::PitchClass.get(number))
  sign = HeadMusic::Sign.by(:semitones, sign_interval) if sign_interval != 0
  spelling = HeadMusic::Spelling.fetch_or_create(letter_name, sign)
  fetch_or_create(spelling, natural_letter_pitch.register)
end

.from_pitch_class(pitch_class) ⇒ Object



44
45
46
47
48
# File 'lib/head_music/pitch.rb', line 44

def self.from_pitch_class(pitch_class)
  return nil unless pitch_class.is_a?(HeadMusic::PitchClass)

  fetch_or_create(pitch_class.sharp_spelling)
end

.get(value) ⇒ Object

Fetches a pitch identified by the information passed in.

Accepts:

- a Pitch instance
- a PitchClass instance
- a name string, such as 'Ab4'
- a number corresponding to the midi note number


30
31
32
33
34
# File 'lib/head_music/pitch.rb', line 30

def self.get(value)
  from_pitch_class(value) ||
    from_name(value) ||
    from_number(value)
end

.middle_cObject



36
37
38
# File 'lib/head_music/pitch.rb', line 36

def self.middle_c
  get("C4")
end

.natural_letter_pitch(number, letter_name) ⇒ Object



71
72
73
74
75
76
# File 'lib/head_music/pitch.rb', line 71

def self.natural_letter_pitch(number, letter_name)
  natural_letter_pitch = get(HeadMusic::LetterName.get(letter_name).pitch_class)
  natural_letter_pitch += 12 while (number.to_i - natural_letter_pitch.to_i) >= 6
  natural_letter_pitch -= 12 while (number.to_i - natural_letter_pitch.to_i) <= -6
  get(natural_letter_pitch)
end

Instance Method Details

#+(other) ⇒ Object



119
120
121
122
123
124
125
126
127
# File 'lib/head_music/pitch.rb', line 119

def +(other)
  if other.is_a?(HeadMusic::DiatonicInterval)
    # return a pitch
    other.above(self)
  else
    # assume value represents an interval in semitones and return another pitch
    HeadMusic::Pitch.get(to_i + other.to_i)
  end
end

#-(other) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/head_music/pitch.rb', line 129

def -(other)
  case other
  when HeadMusic::DiatonicInterval
    # return a pitch
    other.below(self)
  when HeadMusic::Pitch
    # return an interval
    HeadMusic::ChromaticInterval.get(to_i - other.to_i)
  else
    # assume value represents an interval in semitones and return another pitch
    HeadMusic::Pitch.get(to_i - other.to_i)
  end
end

#<=>(other) ⇒ Object



148
149
150
# File 'lib/head_music/pitch.rb', line 148

def <=>(other)
  midi_note_number <=> other.midi_note_number
end

#==(other) ⇒ Object



143
144
145
146
# File 'lib/head_music/pitch.rb', line 143

def ==(other)
  other = HeadMusic::Pitch.get(other)
  to_s == other.to_s
end

#frequencyObject



160
161
162
# File 'lib/head_music/pitch.rb', line 160

def frequency
  tuning.frequency_for(self)
end

#helmholtz_notationObject



111
112
113
# File 'lib/head_music/pitch.rb', line 111

def helmholtz_notation
  helmholtz_letter_name + helmholtz_marks
end

#midi_note_numberObject Also known as: midi, number



96
97
98
# File 'lib/head_music/pitch.rb', line 96

def midi_note_number
  (register + 1) * 12 + letter_name.pitch_class.to_i + sign_semitones.to_i
end

#nameObject



92
93
94
# File 'lib/head_music/pitch.rb', line 92

def name
  [spelling, register].join
end

#naturalObject



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

def natural
  HeadMusic::Pitch.get(to_s.gsub(HeadMusic::Sign.matcher, ""))
end

#natural_steps(num_steps) ⇒ Object



156
157
158
# File 'lib/head_music/pitch.rb', line 156

def natural_steps(num_steps)
  HeadMusic::Pitch.get([target_letter_name(num_steps), register + octaves_delta(num_steps)].join)
end

#scale(scale_type_name = nil) ⇒ Object



152
153
154
# File 'lib/head_music/pitch.rb', line 152

def scale(scale_type_name = nil)
  HeadMusic::Scale.get(self, scale_type_name)
end

#steps_to(other) ⇒ Object



164
165
166
167
# File 'lib/head_music/pitch.rb', line 164

def steps_to(other)
  other = HeadMusic::Pitch.get(other)
  letter_name_steps_to(other) + 7 * octave_changes_to(other)
end

#to_iObject



107
108
109
# File 'lib/head_music/pitch.rb', line 107

def to_i
  midi_note_number
end

#to_sObject



103
104
105
# File 'lib/head_music/pitch.rb', line 103

def to_s
  name
end