module MTK

The top level module for this library

And now that we’ve got some colors we can define colored constants

Constants

PITCH_CLASSES

All 12 pitch classes in the chromatic scale. The index of each pitch class is the pitch class’s numeric {#value}.

Public Class Methods

Chord(*anything) click to toggle source

Construct an ordered {MTK::Groups::Chord} with no duplicates. @see MTK::Groups::Chord @see MTK::Groups::Melody

# File lib/mtk/groups/chord.rb, line 51
def Chord(*anything)
  MTK::Groups::Chord.new MTK::Groups.to_pitches(*anything)
end
Duration(*anything) click to toggle source

Construct a {Duration} from any supported type

# File lib/mtk/core/duration.rb, line 217
def Duration(*anything)
  anything = anything.first if anything.length == 1
  case anything
    when Numeric then MTK::Core::Duration[anything]
    when String, Symbol then MTK::Core::Duration.from_s(anything)
    when Duration then anything
    else raise "Duration doesn't understand #{anything.class}"
  end
end
Intensity(*anything) click to toggle source

Construct a {Duration} from any supported type

# File lib/mtk/core/intensity.rb, line 149
def Intensity(*anything)
  anything = anything.first if anything.length == 1
  case anything
    when Numeric then MTK::Core::Intensity[anything]
    when String, Symbol then MTK::Core::Intensity.from_s(anything)
    when Intensity then anything
    else raise "Intensity doesn't understand #{anything.class}"
  end
end
Interval(*anything) click to toggle source

Construct a {Duration} from any supported type

# File lib/mtk/core/interval.rb, line 153
def Interval(*anything)
  anything = anything.first if anything.length == 1
  case anything
    when Numeric then MTK::Core::Interval[anything]
    when String, Symbol then MTK::Core::Interval.from_s(anything)
    when Interval then anything
    else raise "Interval doesn't understand #{anything.class}"
  end
end
MIDIFile(f) click to toggle source

Shortcut for MTK::IO::MIDIFile.new @note Only available if you require ‘mtk/midi/file’

# File lib/mtk/io/midi_file.rb, line 213
def MIDIFile(f)
  ::MTK::IO::MIDIFile.new(f)
end
Melody(*anything) click to toggle source

Construct an ordered {MTK::Groups::Melody} that allows duplicates @see MTK::Groups::Melody @see MTK::Groups::Chord

# File lib/mtk/groups/melody.rb, line 91
def Melody(*anything)
  MTK::Groups::Melody.new MTK::Groups.to_pitches(*anything)
end
Note(*anything) click to toggle source

Construct a {Events::Note} from a list of any supported type for the arguments: pitch, intensity, duration, channel

# File lib/mtk/events/note.rb, line 72
def Note(*anything)
  anything = anything.first if anything.size == 1
  case anything
    when MTK::Events::Note then anything

    when MTK::Core::Pitch then MTK::Events::Note.new(anything)

    when Array
      pitch = nil
      duration = nil
      intensity = nil
      channel = nil
      unknowns = []
      anything.each do |item|
        case item
          when MTK::Core::Pitch then pitch = item
          when MTK::Core::Duration then duration = item
          when MTK::Core::Intensity then intensity = item
          else unknowns << item
        end
      end

      pitch = MTK.Pitch(unknowns.shift) if pitch.nil? and not unknowns.empty?
      raise "MTK::Note() couldn't find a pitch in arguments: #{anything.inspect}" if pitch.nil?

      duration  = MTK.Duration(unknowns.shift)  if duration.nil?  and not unknowns.empty?
      intensity = MTK.Intensity(unknowns.shift) if intensity.nil? and not unknowns.empty?
      channel = unknowns.shift.to_i if channel.nil? and not unknowns.empty?

      duration  ||= MTK::Events::Note::DEFAULT_DURATION
      intensity ||= MTK::Events::Note::DEFAULT_INTENSITY

      MTK::Events::Note.new( pitch, duration, intensity, channel )

    else
      raise "MTK::Note() doesn't understand #{anything.class}"
  end
end
Pitch(*anything) click to toggle source

Construct a {Pitch} from any supported type

# File lib/mtk/core/pitch.rb, line 139
def Pitch(*anything)
  anything = anything.first if anything.length == 1
  case anything
    when Numeric then MTK::Core::Pitch.from_f(anything)
    when String, Symbol then MTK::Core::Pitch.from_s(anything)
    when MTK::Core::Pitch then anything
    when Array
      if anything.length == 2
        MTK::Core::Pitch[*anything]
      else
        MTK::Core::Pitch.new(*anything)
      end
    else raise ArgumentError.new("Pitch doesn't understand #{anything.class}")
  end
end
PitchClassSet(*anything) click to toggle source

Construct a {Groups::PitchClassSet} @see Groups::PitchClassSet#initialize

# File lib/mtk/groups/pitch_class_set.rb, line 158
def PitchClassSet(*anything)
  MTK::Groups::PitchClassSet.new MTK::Groups.to_pitch_classes(*anything)
end
Rest(*anything) click to toggle source

Construct a {Events::Rest} from a list of any supported type for the arguments: pitch, intensity, duration, channel

# File lib/mtk/events/rest.rb, line 54
def Rest(*anything)
  anything = anything.first if anything.size == 1
  case anything
    when MTK::Events::Rest then anything
    when MTK::Events::Event then MTK::Events::Rest.new(anything.duration, anything.channel)
    when Numeric then MTK::Events::Rest.new(anything)
    when Duration then MTK::Events::Rest.new(anything)

    when Array
      duration = nil
      channel = nil
      unknowns = []
      anything.each do |item|
        case item
          when MTK::Core::Duration then duration = item
          else unknowns << item
        end
      end

      duration  = MTK.Duration(unknowns.shift)  if duration.nil?  and not unknowns.empty?
      raise "MTK::Rest() couldn't find a duration in arguments: #{anything.inspect}" if duration.nil?
      channel = unknowns.shift.to_i if channel.nil? and not unknowns.empty?

      MTK::Events::Rest.new(duration, channel)

    else
      raise "MTK::Rest() doesn't understand #{anything.class}"
  end
end
from_f(value) click to toggle source

return the pitch class with the given float rounded to the nearest integer, mod 12 @param value [Float,#to_f]

# File lib/mtk/core/pitch_class.rb, line 112
def self.from_f(value)
  from_i value.to_f.round
end
from_i(value)
Alias for: from_value
from_name(name) click to toggle source

Lookup a PitchClass by name. @param name [String,#to_s] one of {VALID_NAMES} (case-insensitive)

# File lib/mtk/core/pitch_class.rb, line 84
def self.from_name(name)
  @flyweight[name] ||= (
    valid_name = name.to_s.capitalize
    value = VALUES_BY_NAME[valid_name] or raise ArgumentError.new("Invalid PitchClass name: #{name}")
    new(valid_name,value)
  )
end
Also aliased as: from_s
from_s(name)
Alias for: from_name
from_value(value) click to toggle source

return the pitch class with the given integer value mod 12 @param value [Integer,#to_i]

# File lib/mtk/core/pitch_class.rb, line 102
def self.from_value(value)
  PITCH_CLASSES[value.to_i % 12]
end
Also aliased as: from_i

Public Instance Methods

+(interval) click to toggle source

Transpose this pitch class by adding it’s value to the value given (mod 12) @param interval [PitchClass,Float,#to_f]

# File lib/mtk/core/pitch_class.rb, line 149
def + interval
  new_value = (value + interval.to_f).round
  self.class.from_value new_value
end
Also aliased as: transpose
-(interval) click to toggle source

Transpose this pitch class by subtracing the given value from this value (mod 12) @param interval [PitchClass,Float,#to_f]

# File lib/mtk/core/pitch_class.rb, line 157
def - interval
  new_value = (value - interval.to_f).round
  self.class.from_value new_value
end
<=>(other) click to toggle source

Compare a pitch class with another pitch class or integer value @param other [PitchClass,#to_i] @return -1, 0, or +1 depending on whether this pitch class’s value is less than, equal to, or greater than the other object’s integer value @see ruby-doc.org/core-1.9.3/Comparable.html

# File lib/mtk/core/pitch_class.rb, line 127
def <=> other
  @value <=> other.to_i
end
==(other) click to toggle source

Compare 2 pitch classes for equal values. @param other [PitchClass] @return true if this pitch class’s value is equal to the other pitch class’s value

# File lib/mtk/core/pitch_class.rb, line 119
def == other
  other.is_a? PitchClass and other.value == @value
end
distance_to(pitch_class) click to toggle source

the smallest interval in semitones that needs to be added to this PitchClass to reach the given PitchClass @param pitch_class [PitchClass,#value]

# File lib/mtk/core/pitch_class.rb, line 171
def distance_to(pitch_class)
  delta = (pitch_class.value - value) % 12
  if delta > 6
    delta -= 12
  elsif delta == 6 and to_i >= 6
    # this is a special edge case to prevent endlessly ascending pitch sequences when alternating between two pitch classes a tritone apart
    delta = -6
  end
  delta
end
invert(center) click to toggle source

Inverts (mirrors) the pitch class around the given center @param center [PitchClass,Pitch,Float,#to_f] the value to “mirror” this pitch class around

# File lib/mtk/core/pitch_class.rb, line 164
def invert(center)
  delta = (2*(center.to_f - value)).round
  self + delta
end
to_f() click to toggle source

This pitch class’s {#value} as a floating point number

# File lib/mtk/core/pitch_class.rb, line 143
def to_f
  @value.to_f
end
to_i() click to toggle source

This pitch class’s integer {#value}

# File lib/mtk/core/pitch_class.rb, line 138
def to_i
  @value.to_i
end
to_s() click to toggle source

This pitch class’s normalized {#name}. @see NAMES

# File lib/mtk/core/pitch_class.rb, line 133
def to_s
  @name.to_s
end
transpose(interval)
Alias for: +

Private Instance Methods

Chord(*anything) click to toggle source

Construct an ordered {MTK::Groups::Chord} with no duplicates. @see MTK::Groups::Chord @see MTK::Groups::Melody

# File lib/mtk/groups/chord.rb, line 51
def Chord(*anything)
  MTK::Groups::Chord.new MTK::Groups.to_pitches(*anything)
end
Duration(*anything) click to toggle source

Construct a {Duration} from any supported type

# File lib/mtk/core/duration.rb, line 217
def Duration(*anything)
  anything = anything.first if anything.length == 1
  case anything
    when Numeric then MTK::Core::Duration[anything]
    when String, Symbol then MTK::Core::Duration.from_s(anything)
    when Duration then anything
    else raise "Duration doesn't understand #{anything.class}"
  end
end
Intensity(*anything) click to toggle source

Construct a {Duration} from any supported type

# File lib/mtk/core/intensity.rb, line 149
def Intensity(*anything)
  anything = anything.first if anything.length == 1
  case anything
    when Numeric then MTK::Core::Intensity[anything]
    when String, Symbol then MTK::Core::Intensity.from_s(anything)
    when Intensity then anything
    else raise "Intensity doesn't understand #{anything.class}"
  end
end
Interval(*anything) click to toggle source

Construct a {Duration} from any supported type

# File lib/mtk/core/interval.rb, line 153
def Interval(*anything)
  anything = anything.first if anything.length == 1
  case anything
    when Numeric then MTK::Core::Interval[anything]
    when String, Symbol then MTK::Core::Interval.from_s(anything)
    when Interval then anything
    else raise "Interval doesn't understand #{anything.class}"
  end
end
MIDIFile(f) click to toggle source

Shortcut for MTK::IO::MIDIFile.new @note Only available if you require ‘mtk/midi/file’

# File lib/mtk/io/midi_file.rb, line 213
def MIDIFile(f)
  ::MTK::IO::MIDIFile.new(f)
end
Melody(*anything) click to toggle source

Construct an ordered {MTK::Groups::Melody} that allows duplicates @see MTK::Groups::Melody @see MTK::Groups::Chord

# File lib/mtk/groups/melody.rb, line 91
def Melody(*anything)
  MTK::Groups::Melody.new MTK::Groups.to_pitches(*anything)
end
Note(*anything) click to toggle source

Construct a {Events::Note} from a list of any supported type for the arguments: pitch, intensity, duration, channel

# File lib/mtk/events/note.rb, line 72
def Note(*anything)
  anything = anything.first if anything.size == 1
  case anything
    when MTK::Events::Note then anything

    when MTK::Core::Pitch then MTK::Events::Note.new(anything)

    when Array
      pitch = nil
      duration = nil
      intensity = nil
      channel = nil
      unknowns = []
      anything.each do |item|
        case item
          when MTK::Core::Pitch then pitch = item
          when MTK::Core::Duration then duration = item
          when MTK::Core::Intensity then intensity = item
          else unknowns << item
        end
      end

      pitch = MTK.Pitch(unknowns.shift) if pitch.nil? and not unknowns.empty?
      raise "MTK::Note() couldn't find a pitch in arguments: #{anything.inspect}" if pitch.nil?

      duration  = MTK.Duration(unknowns.shift)  if duration.nil?  and not unknowns.empty?
      intensity = MTK.Intensity(unknowns.shift) if intensity.nil? and not unknowns.empty?
      channel = unknowns.shift.to_i if channel.nil? and not unknowns.empty?

      duration  ||= MTK::Events::Note::DEFAULT_DURATION
      intensity ||= MTK::Events::Note::DEFAULT_INTENSITY

      MTK::Events::Note.new( pitch, duration, intensity, channel )

    else
      raise "MTK::Note() doesn't understand #{anything.class}"
  end
end
Pitch(*anything) click to toggle source

Construct a {Pitch} from any supported type

# File lib/mtk/core/pitch.rb, line 139
def Pitch(*anything)
  anything = anything.first if anything.length == 1
  case anything
    when Numeric then MTK::Core::Pitch.from_f(anything)
    when String, Symbol then MTK::Core::Pitch.from_s(anything)
    when MTK::Core::Pitch then anything
    when Array
      if anything.length == 2
        MTK::Core::Pitch[*anything]
      else
        MTK::Core::Pitch.new(*anything)
      end
    else raise ArgumentError.new("Pitch doesn't understand #{anything.class}")
  end
end
PitchClassSet(*anything) click to toggle source

Construct a {Groups::PitchClassSet} @see Groups::PitchClassSet#initialize

# File lib/mtk/groups/pitch_class_set.rb, line 158
def PitchClassSet(*anything)
  MTK::Groups::PitchClassSet.new MTK::Groups.to_pitch_classes(*anything)
end
Rest(*anything) click to toggle source

Construct a {Events::Rest} from a list of any supported type for the arguments: pitch, intensity, duration, channel

# File lib/mtk/events/rest.rb, line 54
def Rest(*anything)
  anything = anything.first if anything.size == 1
  case anything
    when MTK::Events::Rest then anything
    when MTK::Events::Event then MTK::Events::Rest.new(anything.duration, anything.channel)
    when Numeric then MTK::Events::Rest.new(anything)
    when Duration then MTK::Events::Rest.new(anything)

    when Array
      duration = nil
      channel = nil
      unknowns = []
      anything.each do |item|
        case item
          when MTK::Core::Duration then duration = item
          else unknowns << item
        end
      end

      duration  = MTK.Duration(unknowns.shift)  if duration.nil?  and not unknowns.empty?
      raise "MTK::Rest() couldn't find a duration in arguments: #{anything.inspect}" if duration.nil?
      channel = unknowns.shift.to_i if channel.nil? and not unknowns.empty?

      MTK::Events::Rest.new(duration, channel)

    else
      raise "MTK::Rest() doesn't understand #{anything.class}"
  end
end