Class: Tonal::Midi::Note

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/tonal/midi.rb

Constant Summary collapse

A4_MIDI_NUMBER =
69
C4_MIDI_NUMBER =
60
DEFAULT_MODULO =
12

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(number: nil, frequency: nil, modulo: DEFAULT_MODULO, reference_number: A4_MIDI_NUMBER, reference_frequency: Tonal::Hertz::REFERENCE_FREQUENCY) ⇒ Tonal::Midi::Note

Examples:

Tonal::Midi::Note.new(number: 60) => 60 MIDI
Tonal::Midi::Note.new(frequency: 261.63) => 60 MIDI

Parameters:

  • number (Integer, nil) (defaults to: nil)

    the MIDI note number. Mutually exclusive with frequency:

  • frequency (Numeric, Tonal::Hertz, nil) (defaults to: nil)

    the frequency in Hz. Mutually exclusive with number:

  • modulo (Integer) (defaults to: DEFAULT_MODULO)

    the number of steps per octave

  • reference_number (Integer) (defaults to: A4_MIDI_NUMBER)

    the MIDI note number that anchors the number/frequency conversion

  • reference_frequency (Numeric) (defaults to: Tonal::Hertz::REFERENCE_FREQUENCY)

    the frequency (Hz) that anchors the number/frequency conversion

Raises:

  • (ArgumentError)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/tonal/midi.rb', line 21

def initialize(number: nil, frequency: nil, modulo: DEFAULT_MODULO, reference_number: A4_MIDI_NUMBER, reference_frequency: Tonal::Hertz::REFERENCE_FREQUENCY)
  raise ArgumentError, "Provide either number: or frequency:, not both" if number && frequency

  @modulo = modulo
  @reference_number = reference_number
  @reference_frequency = reference_frequency.to_f
  if frequency
    raise ArgumentError, "Frequency argument is not Numeric or Tonal::Hertz" unless frequency.kind_of?(Numeric) || frequency.kind_of?(Tonal::Hertz)
    @frequency = Tonal::Hertz.new(frequency)
    @number = (@reference_number + modulo * Math.log2(frequency.to_f / @reference_frequency)).round
  else
    number = @reference_number if number.nil?
    raise ArgumentError, "Number argument is not Integer" unless number.kind_of?(Integer)
    @number = number
    @frequency = Tonal::Hertz.new(@reference_frequency * (2 ** ((number - @reference_number) / modulo.to_f)))
  end
end

Instance Attribute Details

#moduloObject (readonly)

Returns the value of attribute modulo.



9
10
11
# File 'lib/tonal/midi.rb', line 9

def modulo
  @modulo
end

#numberObject (readonly) Also known as: value

Returns the value of attribute number.



9
10
11
# File 'lib/tonal/midi.rb', line 9

def number
  @number
end

#reference_frequencyObject (readonly)

Returns the value of attribute reference_frequency.



9
10
11
# File 'lib/tonal/midi.rb', line 9

def reference_frequency
  @reference_frequency
end

#reference_numberObject (readonly)

Returns the value of attribute reference_number.



9
10
11
# File 'lib/tonal/midi.rb', line 9

def reference_number
  @reference_number
end

Instance Method Details

#<=>(other) ⇒ Object



55
56
57
# File 'lib/tonal/midi.rb', line 55

def <=>(other)
  number <=> (other.kind_of?(self.class) ? other.number : other)
end

#frequency(round: nil) ⇒ Float

Returns the frequency corresponding to the MIDI note number.

Examples:

Tonal::Midi::Note.new(number:60).frequency => 261.6255653005986

Parameters:

  • round (Integer, nil) (defaults to: nil)

    the number of decimal places to round the frequency to, or nil for no rounding

Returns:

  • (Float)

    the frequency corresponding to the MIDI note number



46
47
48
# File 'lib/tonal/midi.rb', line 46

def frequency(round: nil)
  round ? @frequency.to_f.round(round) : @frequency.to_f
end

#inspectString

Returns representation of self.

Returns:

  • (String)

    representation of self



51
52
53
# File 'lib/tonal/midi.rb', line 51

def inspect
  "#{number} MIDI"
end