Class: Mext::Music::PitchClass
- Inherits:
-
Object
- Object
- Mext::Music::PitchClass
- 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
-
.create_from_semitones(s) ⇒ Object
:doc:.
-
.find_by_anglo_name(anglo_name = 'C4') ⇒ Object
:doc:.
-
.from_freq(f) ⇒ Object
:doc:.
Instance Method Summary collapse
-
#+(other) ⇒ Object
:doc:.
-
#-(other) ⇒ Object
:doc:.
- #==(other) ⇒ Object
-
#add_semitones(semi) ⇒ Object
:doc:.
-
#add_semitones!(semi) ⇒ Object
:doc:.
- #anglo_note_name ⇒ Object
-
#initialize(fv, semi = nil) ⇒ PitchClass
constructor
Mext::Music::PitchClass.new(float_value, semi = nil):.
-
#inner_representation ⇒ Object
(also: #to_semitones)
:doc:.
-
#interval(other) ⇒ Object
:doc:.
-
#interval_proportion(prop, other) ⇒ Object
:doc:.
-
#octave ⇒ Object
:doc:.
-
#semi ⇒ Object
:doc:.
-
#to_f ⇒ Object
:doc:.
-
#to_freq ⇒ Object
:doc:.
-
#transpose(semi) ⇒ Object
:doc:.
-
#transpose!(semi) ⇒ Object
:doc:.
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
)
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 ofNumeric
, alsonegative 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 ofNumeric
, alsonegative 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_name ⇒ Object
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_representation ⇒ Object 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 |
#octave ⇒ Object
: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 |
#semi ⇒ Object
: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_f ⇒ Object
: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_freq ⇒ Object
: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 |