Class: Mext::Music::PitchClass

Inherits:
Object
  • Object
show all
Defined in:
lib/mext/music/pitch_class.rb

Overview

Mext::Music::PitchClass

this is a representation of pitches in the usual PitchClass representation of csound and other software

Internally, the representation is in semitones. In order to be consistent with the csound representation, a PitchClass of 8.00 represents central C4 (+ca. 261.3 Hz+, depending on tuning), while a PitchClass of 0.00 is 96 semitones below (8 * 12).

The internal representation allows for floating point values, negative values etc. However, since the PitchClass is a geometric representation of pitches, it will never produce a negative frequency value (for semitones that go to -Inf., it’ll produce infinitely small positive values.

Constant Summary collapse

SEMI_NAMES =

:doc

anglo_note_name:

returns the name of the note, in anglosaxon notation, with the sharps as only enharmonics (reported as ‘s’). The octave considers central C as C4

%w(C Cs D Ds E F Fs G Gs A As B)
OCT_DIFF =
4

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fv, semi = nil) ⇒ PitchClass

Mext::Music::PitchClass.new(float_value, semi = nil):

pitch class object, where argument is:

float_value: a pitch class in float notation (i.e. 8.00 for middle C, etc.)

+or+ an octave value when given in octave, semi pair (see below)

semi: (optional) when this argument is not nil, then it is assumed

that the first argument is the octave, and this one is the
semitone value

:nodoc:



35
36
37
# File 'lib/mext/music/pitch_class.rb', line 35

def initialize(fv, semi = nil)
  @semi = semi ? setup_with_two_arguments(fv, semi) : setup_with_one_argument(fv)
end

Class Method Details

.create_from_semitones(s) ⇒ Object

:doc:

create_from_semitones

creates a PitchClass object out of a semitone representation

:nodoc:



244
245
246
# File 'lib/mext/music/pitch_class.rb', line 244

def create_from_semitones(s)
  new(0.0, s)
end

.find_by_anglo_name(anglo_name = 'C4') ⇒ Object

:doc:

find_by_anglo_name(anglo_name = ‘C4’)

creates a PitchClass object passing a note name in anglosaxon notation (where C4 corresponds to 8.00)

Raises:

  • (ArgumentError)


267
268
269
270
271
272
273
274
275
276
# File 'lib/mext/music/pitch_class.rb', line 267

def find_by_anglo_name(anglo_name = 'C4')
  anglo_name = anglo_name.upcase
  raise ArgumentError, "malformed name #{anglo_name}" unless anglo_name.match?(/\A[A-G]S?\-?\d+\Z/)
  note = anglo_name.sub(/\A([A-G]S?).*\Z/i, '\1')
  upcased_names = SEMI_NAMES.map { |n| n.upcase }
  semi = upcased_names.index(note)
  oct = anglo_name.sub(/\A[A-G]S?(\-?\d+)\Z/, '\1').to_i + OCT_DIFF
#         semi = oct <= 0 ? -semi : semi
  new(oct, semi)
end

.from_freq(f) ⇒ Object

:doc:

from_freq

returns a pitch class object from a frequency (Hz)

:nodoc:



256
257
258
# File 'lib/mext/music/pitch_class.rb', line 256

def from_freq(f)
  new(f.cpspch)
end

Instance Method Details

#+(other) ⇒ Object

:doc:

++(other)+ (operator plus)

sums two pitch classes

:nodoc:



116
117
118
# File 'lib/mext/music/pitch_class.rb', line 116

def +(other)
  self.class.create_from_semitones((self.inner_representation + other.inner_representation).cround)
end

#-(other) ⇒ Object

:doc:

-(other) (operator minus)

subtracts two pitch classes

:nodoc:



128
129
130
# File 'lib/mext/music/pitch_class.rb', line 128

def -(other)
  self.class.create_from_semitones((self.inner_representation - other.inner_representation).cround)
end

#==(other) ⇒ Object



105
106
107
# File 'lib/mext/music/pitch_class.rb', line 105

def ==(other)
  self.inner_representation.cround == other.inner_representation.cround
end

#add_semitones(semi) ⇒ Object

:doc:

add_semitones(semi):

returns a PitchClass the addition of semitones required by argument

  • semi: the semitones to add; can be any sort of Numeric, also

    negative to subtract.
    


197
198
199
# File 'lib/mext/music/pitch_class.rb', line 197

def add_semitones(semi)
  self.class.create_from_semitones((self.inner_representation + semi.to_f).cround)
end

#add_semitones!(semi) ⇒ Object

:doc:

add_semitones!(semi):

returns the addition of semitones required in the receiver’s pitch class

  • semi: the semitones to add; can be any sort of Numeric, also

    negative to subtract.
    

:nodoc:



210
211
212
213
# File 'lib/mext/music/pitch_class.rb', line 210

def add_semitones!(semi)
  @semi += semi.to_f
  self
end

#anglo_note_nameObject



227
228
229
230
231
232
233
# File 'lib/mext/music/pitch_class.rb', line 227

def anglo_note_name
  oct = self.octave - OCT_DIFF
  s = self.semi.round
  oct = self.inner_representation < 0.0 && s != 0.0 ? oct-1 : oct
  name = SEMI_NAMES[s]
  "%s%d" % [ name, oct ]
end

#inner_representationObject Also known as: to_semitones

:doc:

inner_representation

returns the inner representation in semitones (this is a public method since it is used in several comparison methods)

:no_doc:



68
69
70
# File 'lib/mext/music/pitch_class.rb', line 68

def inner_representation
  @semi
end

#interval(other) ⇒ Object

:doc:

interval(other)

computes the interval among two pitch classes (in number of semitones and fractions thereof)

:nodoc:



148
149
150
# File 'lib/mext/music/pitch_class.rb', line 148

def interval(other)
  (other - self).inner_representation
end

#interval_proportion(prop, other) ⇒ Object

:doc:

interval_proportion(prop, other):

returns the interval proportion (in semitones) given

  • prop: a proportional factor (should be in the range 0-1)

  • other: the other pitch



184
185
186
# File 'lib/mext/music/pitch_class.rb', line 184

def interval_proportion(prop, other)
  self.interval(other) * prop
end

#octaveObject

:doc:

octave

returns the octave part of the pitch class



45
46
47
48
# File 'lib/mext/music/pitch_class.rb', line 45

def octave
  res = @semi / ::Numeric::CNPO
  res >= 0.0 ? res.floor : res.ceil
end

#semiObject

:doc:

semi

returns the semitone part of the pitch class



56
57
58
# File 'lib/mext/music/pitch_class.rb', line 56

def semi
  @semi >= 0.0 ? (@semi % 12.0) : (@semi % -12.0)
end

#to_fObject

:doc:

to_f

returns the pitch class in float notation

:nodoc:



79
80
81
# File 'lib/mext/music/pitch_class.rb', line 79

def to_f
  self.inner_representation.semitopch
end

#to_freqObject

:doc:

to_freq

returns the pitch class in frequency (Hz)

:nodoc:



90
91
92
# File 'lib/mext/music/pitch_class.rb', line 90

def to_freq
  self.inner_representation.semitopch.pchcps
end

#transpose(semi) ⇒ Object

:doc:

transpose(semitones)

returns a PitchClass transposed by semitones semitones

:nodoc:



159
160
161
# File 'lib/mext/music/pitch_class.rb', line 159

def transpose(semi)
  self.class.create_from_semitones((self.inner_representation + semi).cround)
end

#transpose!(semi) ⇒ Object

:doc:

transpose!(semitones)

transposes the receiver by semitones semitones

:nodoc:



170
171
172
173
# File 'lib/mext/music/pitch_class.rb', line 170

def transpose!(semi)
  @semi += semi
  self
end