Sha256: f7c4b8ea0b6966c121f4eb4ba51b7d5cdf147e6237d2e6cd48be191c1a66e01f

Contents?: true

Size: 1.73 KB

Versions: 4

Compression:

Stored size: 1.73 KB

Contents

# frozen_string_literal: true

module Coltrane
  # Describes a musical note, independent of octave (that'd be pitch)
  class Note
    include Multiton

    attr_reader :name, :number
    alias id number

    NOTES = {
      'C'  => 0,
      'C#' => 1,
      'Db' => 1,
      'D'  => 2,
      'D#' => 3,
      'Eb' => 3,
      'E'  => 4,
      'F'  => 5,
      'F#' => 6,
      'Gb' => 6,
      'G'  => 7,
      'G#' => 8,
      'Ab' => 8,
      'A'  => 9,
      'A#' => 10,
      'Bb' => 10,
      'B'  => 11
    }.freeze

    def initialize(name)
      @name = name
      @number = NOTES[name]
    end

    private_class_method :new

    def self.[](arg)
      name =
        case arg
        when Note then return arg
        when String then find_note(arg)
        when Numeric then NOTES.key(arg % 12)
        else
          raise InvalidNoteError, "Wrong type: #{arg.class}"
        end

      new(name) || (raise InvalidNoteError, arg.to_s)
    end

    def self.all
      %w[C C# D D# E F F# G G# A A# B].map { |n| Note[n] }
    end

    def self.find_note(str)
      NOTES.each_key { |k, _v| return k if str.casecmp?(k) }
      nil
    end

    def pretty_name
      @name.tr('b', "\u266D").tr('#', "\u266F")
    end

    alias to_s name

    def accident?
      [1, 3, 6, 8, 10].include?(number)
    end

    def +(other)
      case other
      when Interval then Note[number + other.semitones]
      when Numeric  then Note[number + other]
      when Note     then Chord.new(number + other.number)
      end
    end

    def -(other)
      case other
      when Numeric then Note.new(other - number)
      when Note    then Interval.new(other.number - number)
      end
    end

    def interval_to(note_name)
      Note[note_name] - self
    end
  end
end

Version data entries

4 entries across 4 versions & 1 rubygems

Version Path
coltrane-1.0.22 lib/coltrane/note.rb
coltrane-1.0.21 lib/coltrane/note.rb
coltrane-1.0.20 lib/coltrane/note.rb
coltrane-1.0.2 lib/coltrane/note.rb