class MultimediaParadise::Note
Constants
- ARRAY_NOTES
#¶ ↑
ARRAY_NOTES
¶ ↑#¶ ↑
- CHORD_ALIASES
#¶ ↑
CHORD_ALIASES
¶ ↑#¶ ↑
- CHORD_INTERVALS
#¶ ↑
CHORD_INTERVALS
¶ ↑#¶ ↑
- NOTE_STRINGS
#¶ ↑
NOTE_STRINGS
¶ ↑MultimediaParadise::NOTE_STRINGS
#¶ ↑
Attributes
Public Class Methods
#¶ ↑
calculate_frequency
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 435 def calculate_frequency(*args) case args.size when 1 letter, accidental, octave = parse_note_string(args[0]) when 2 letter, accidental, octave = parse_note_string(args[0], args[1]) when 3 letter, accidental, octave = args else raise ArgumentError, "Invalid octave of arguments" end distance = note_distance('A4', "#{letter}#{accidental}#{octave}") frequency_adjustment(440.0, distance) end
#¶ ↑
calculate_note
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 453 def calculate_note( frequency, give_flat = false ) # ===================================================================== # # We could use #log(frequency / 440.0, 2), but then this is # possibly not supported in Ruby 1.8 anymore. # ===================================================================== # frequency_log_base_2 = Math.log(frequency / 440.0) / Math.log(2) distance = (ARRAY_NOTES.size * frequency_log_base_2).round index = 9 + distance # 9 is index for A octave = 4 + (index / ARRAY_NOTES.size) # 4 is because we're using A4 index = (index % ARRAY_NOTES.size) parts = ARRAY_NOTES[index].split('/') note = if give_flat parts.last else parts.first end # "#{note}#{octave}" note_parts = note.split('') note_parts + (note_parts.size == 1 ? [nil] : []) + [octave.to_i] end
#¶ ↑
frequency_adjustment
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 426 def frequency_adjustment(start_frequency, distance) result = (start_frequency * (2.0 ** (distance.to_f / ARRAY_NOTES.size))) # Would like to use #round(2), but want to support Ruby 1.8 (result * 100.0).round / 100.0 end
#¶ ↑
initialize¶ ↑
This class will create a new note.
Usage examples:
note = MultimediaParadise::Note.new(698.46) # Creates a note object with the frequency 698.46 note = MultimediaParadise::Note.new('F#6') # Creates an F sharp note in the 6th octave
@param [String, Numeric] descriptor Either a string describing the note (e.g. ‘C#4’) or a number giving the note’s frequency (e.g. 440) @param [Numeric, nil] assumed_octave If no octive is given in the descriptor, use this @returns [Note] Note
specified
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 151 def initialize(descriptor, assumed_octave = nil) reset self.frequency = if descriptor.is_a? Numeric Note.nearest_note_frequency(descriptor) else Note.calculate_frequency(descriptor, assumed_octave) end end
#¶ ↑
note_distance
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 401 def note_distance(note_string1, note_string2) letter1, accidental1, octave1 = parse_note_string(note_string1) letter2, accidental2, octave2 = parse_note_string(note_string2) get_index = Proc.new { |letter, accidental| ARRAY_NOTES.index { |note| regex = case accidental when '#' then /^#{letter}#/ when 'b' then /#{letter}b$/ else /^#{letter}$/ end note.match(regex) } } index1 = get_index.call(letter1, accidental1) index2 = get_index.call(letter2, accidental2) (index2 - index1) + ((octave2.to_i - octave1.to_i) * ARRAY_NOTES.size) end
# File lib/multimedia_paradise/multimedia/note.rb, line 382 def parse_note_string(note_string, assumed_octave = nil) match = note_string.match(/^([A-Ga-g])([#b]?)([0-8]?)$/) unless match raise ArgumentError, "Could not recognize the note string: #{note_string}. It may be invalid." end if match[3].empty? && assumed_octave.nil? raise ArgumentError, "No octave found or specified" end if match[3].to_i > 8 || (assumed_octave && !(0..8).include?(assumed_octave)) raise ArgumentError end octave = match[3].empty? ? assumed_octave : match[3] [match[1].upcase, match[2] == '' ? nil : match[2], octave.to_i] end
Public Instance Methods
#¶ ↑
accidental¶ ↑
Returns the accidental portion of the note e.g. ‘#’ or ‘b’
@param [boolean] give_flat Should the result give a flat? (defaults
to giving a sharp)
@return [String] The resulting accidental.
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 238 def accidental(give_flat = false) Note.calculate_note(self.frequency, give_flat)[1] end
#¶ ↑
adjust_by_semitones
¶ ↑
Return another note adjusted by a given interval
@param [Fixnum] interval Number of semitones to adjust by @return [Note] Resulting note after adjustment.
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 294 def adjust_by_semitones(interval) Note.new( Note.frequency_adjustment(self.frequency, interval) ) end
#¶ ↑
chord¶ ↑
The first argument is the chord description.
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 359 def chord(description) description = :major if description.to_s.empty? description = description.to_s description.downcase! unless %w( M M7 ).include? description description.gsub!(/[\s\-]+/, '_') description = description.to_sym intervals = CHORD_INTERVALS[description] || CHORD_INTERVALS[CHORD_ALIASES[description]] if intervals Chord.new([self] + intervals.collect {|interval| self.send(interval) }) end end
#¶ ↑
letter¶ ↑
Returns the letter portion of the note e.g. ‘C’
@param [boolean] give_flat Should the result be based on
giving a flat? (defaults to giving a sharp)
@return [String] The resulting note letter
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 225 def letter(give_flat = false) Note.calculate_note(self.frequency, give_flat).first end
#¶ ↑
major_scale
¶ ↑
Uses note as key to give major scale
@returns [Array<Note>] Notes in major scale.
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 325 def major_scale [self, self.major_second, self.major_third, self.perfect_fourth, self.perfect_fifth, self.major_sixth, self.major_seventh, ] end
#¶ ↑
minor_scale
¶ ↑
Uses note as key to give minor scale
@returns [Array<Note>] Notes in minor scale.
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 343 def minor_scale [self, self.major_second, self.minor_third, self.perfect_fourth, self.perfect_fifth, self.minor_sixth, self.minor_seventh, ] end
#¶ ↑
note_string
¶ ↑
Returns string representing note with letter, accidental, and octave number e.g. ‘C#5’
@param [boolean] give_flat Should the result give a flat? (defaults to giving a sharp) @return [String] The resulting note string.
#¶ ↑
# File lib/multimedia_paradise/multimedia/note.rb, line 212 def note_string(give_flat = false) Note.calculate_note(self.frequency, give_flat).join end