class Music::Note
Constants
- ACCIDENTALS
- CHROMATIC_SCALE
- DIATONIC_SCALE
- REGEXP
Attributes
accidental[R]
# or ♭.
@return [String]
letter[R]
C, D, E, F, G, A or B.
@return [String]
octave[R]
An integer.
@return [Integer]
Public Class Methods
new(name)
click to toggle source
@param name [String] Consists of a letter (C, D, E, F, G, A, B),
accidental (# or ♭) and octave (any integer).
@example
Note.new("C") Note.new("C#") Note.new("C♭") #=> or Note.new("Cb") Note.new("C1") Note.new("B-1")
# File lib/music/note.rb, line 51 def initialize(name) unless match = name.match(/^#{REGEXP}$/) raise ArgumentError, "invalid note name: #{name} (example: C#1)" end @letter = match[:letter] @accidental = match[:accidental].sub("b", "♭") unless match[:accidental].empty? @octave = match[:octave].to_i unless match[:octave].empty? end
Public Instance Methods
-(other)
click to toggle source
@param other [Music::Note] @return [Music::Interval] @example
Note.new("E") - Note.new("C") #=> #<Music::Interval @number=3, @quality=:major>
# File lib/music/note.rb, line 130 def -(other) number = (self.diatonic_idx - other.diatonic_idx).abs + 1 number += (self.octave - other.octave).abs * DIATONIC_SCALE.size unless octave.nil? distance = (self.pitch - other.pitch).abs quality = Interval::QUALITIES.find do |quality| begin; Interval.new(number, quality).size == distance; rescue ArgumentError; end end interval = Interval.new(number, quality) self >= other ? interval : -interval end
<=>(other)
click to toggle source
Compares notes by their pitch.
@param other [Music::Note] @example
Note.new("C#") == Note.new("D♭") #=> true Note.new("C") < Note.new("D") #=> true Note.new("C2") > Note.new("C1") #=> true
# File lib/music/note.rb, line 75 def <=>(other) self.pitch <=> other.pitch end
name()
click to toggle source
# File lib/music/note.rb, line 61 def name [letter, accidental, octave].join end
Also aliased as: to_s
transpose_by(interval)
click to toggle source
@param interval [Music::Interval] @return [Music::Note] @example
major_third = Interval.new(3, :major) Note.new("C").transpose_by(major_third) == Note.new("E") #=> true Note.new("E").transpose_by(-major_third) == Note.new("C") #=> true
# File lib/music/note.rb, line 87 def transpose_by(interval) transposed_pitch = pitch + interval.size transposed_pitch %= CHROMATIC_SCALE.size if octave.nil? transposed_diatonic_idx = (diatonic_idx + interval.diff) % DIATONIC_SCALE.size transposed_letter = DIATONIC_SCALE.fetch(transposed_diatonic_idx) transposed_octave = octave + (diatonic_idx + interval.diff) / DIATONIC_SCALE.size if octave transposed_accidental = ACCIDENTALS.find do |accidental| note = Note.new [transposed_letter, accidental, transposed_octave].join note.pitch == transposed_pitch end Note.new [transposed_letter, transposed_accidental, transposed_octave].join end
transpose_down(interval)
click to toggle source
@param (see transpose_by
) @return (see transpose_by
)
@see transpose_by
# File lib/music/note.rb, line 120 def transpose_down(interval) transpose_by(-interval) end
transpose_up(interval)
click to toggle source
@param (see transpose_by
) @return (see transpose_by
)
@see transpose_by
# File lib/music/note.rb, line 110 def transpose_up(interval) transpose_by(interval) end
Protected Instance Methods
chromatic_idx()
click to toggle source
@return [Integer] An integer from 0 to 11
# File lib/music/note.rb, line 166 def chromatic_idx accidental_effect = {"#" => +1, "♭" => -1}.fetch(accidental, 0) CHROMATIC_SCALE.index(letter) + accidental_effect end
diatonic_idx()
click to toggle source
@return [Integer] An integer from 0 to 6
# File lib/music/note.rb, line 159 def diatonic_idx DIATONIC_SCALE.index(letter) end
pitch()
click to toggle source
Internal integer representation on the note.
@return [Integer]
# File lib/music/note.rb, line 150 def pitch result = chromatic_idx + (octave.to_i * CHROMATIC_SCALE.size) result %= CHROMATIC_SCALE.size if octave.nil? result end