Class: Deftones::Music::Note
- Inherits:
-
Object
- Object
- Deftones::Music::Note
- Defined in:
- lib/deftones/music/note.rb
Constant Summary collapse
- NOTE_NAMES =
%w[C C# D D# E F F# G G# A A# B].freeze
- FLAT_MAP =
{ "Cb" => "B", "Db" => "C#", "Eb" => "D#", "Fb" => "E", "Gb" => "F#", "Ab" => "G#", "Bb" => "A#" }.freeze
Class Method Summary collapse
- .from_frequency(frequency) ⇒ Object
- .from_midi(midi_number) ⇒ Object
- .normalize_name(token) ⇒ Object private
- .parse_note_name(note_name) ⇒ Object private
- .to_frequency(note_name) ⇒ Object
- .to_midi(note_name) ⇒ Object
- .validate_accidentals!(note_name) ⇒ Object private
Class Method Details
.from_frequency(frequency) ⇒ Object
34 35 36 37 38 39 40 |
# File 'lib/deftones/music/note.rb', line 34 def from_frequency(frequency) normalized_frequency = frequency.to_f raise Deftones::InvalidFrequencyError, "Frequency must be positive" unless normalized_frequency.positive? && normalized_frequency.finite? midi_number = (12 * Math.log2(normalized_frequency / 440.0) + 69).round from_midi(midi_number) end |
.from_midi(midi_number) ⇒ Object
28 29 30 31 32 |
# File 'lib/deftones/music/note.rb', line 28 def from_midi(midi_number) integer = midi_number.to_i octave = (integer / 12) - 1 "#{NOTE_NAMES[integer % 12]}#{octave}" end |
.normalize_name(token) ⇒ Object (private)
61 62 63 64 |
# File 'lib/deftones/music/note.rb', line 61 def normalize_name(token) canonical = token[0].upcase + token[1..] FLAT_MAP.fetch(canonical, canonical.upcase) end |
.parse_note_name(note_name) ⇒ Object (private)
44 45 46 47 48 49 50 51 52 53 |
# File 'lib/deftones/music/note.rb', line 44 def parse_note_name(note_name) validate_accidentals!(note_name) match = note_name.to_s.match(/\A([A-Ga-g][#b]?)(-?\d+)\z/) raise Deftones::InvalidNoteError, "Invalid note: #{note_name}" unless match normalized_name = normalize_name(match[1]) raise Deftones::InvalidNoteError, "Unsupported note name: #{note_name}" unless NOTE_NAMES.include?(normalized_name) [normalized_name, match[2].to_i] end |
.to_frequency(note_name) ⇒ Object
18 19 20 21 |
# File 'lib/deftones/music/note.rb', line 18 def to_frequency(note_name) midi_number = to_midi(note_name) 440.0 * (2.0**((midi_number - 69) / 12.0)) end |
.to_midi(note_name) ⇒ Object
23 24 25 26 |
# File 'lib/deftones/music/note.rb', line 23 def to_midi(note_name) name, octave = parse_note_name(note_name) NOTE_NAMES.index(name) + ((octave + 1) * 12) end |
.validate_accidentals!(note_name) ⇒ Object (private)
55 56 57 58 59 |
# File 'lib/deftones/music/note.rb', line 55 def validate_accidentals!(note_name) return unless note_name.to_s.match?(/\A[A-Ga-g](?:##|bb)/) raise Deftones::InvalidNoteError, "Double accidentals are unsupported: #{note_name}" end |