Module: Webmidi::Music::Scale

Defined in:
lib/webmidi/music/scale.rb

Constant Summary collapse

TYPES =
{
  major: [0, 2, 4, 5, 7, 9, 11],
  minor: [0, 2, 3, 5, 7, 8, 10],
  harmonic_minor: [0, 2, 3, 5, 7, 8, 11],
  melodic_minor: [0, 2, 3, 5, 7, 9, 11],
  dorian: [0, 2, 3, 5, 7, 9, 10],
  phrygian: [0, 1, 3, 5, 7, 8, 10],
  lydian: [0, 2, 4, 6, 7, 9, 11],
  mixolydian: [0, 2, 4, 5, 7, 9, 10],
  locrian: [0, 1, 3, 5, 6, 8, 10],
  pentatonic: [0, 2, 4, 7, 9],
  minor_pentatonic: [0, 3, 5, 7, 10],
  blues: [0, 3, 5, 6, 7, 10],
  chromatic: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
  whole_tone: [0, 2, 4, 6, 8, 10],
  diminished: [0, 2, 3, 5, 6, 8, 9, 11]
}.freeze

Class Method Summary collapse

Class Method Details

.build(root, type = :major, range: :strict) ⇒ Object



28
29
30
31
32
33
34
# File 'lib/webmidi/music/scale.rb', line 28

def build(root, type = :major, range: :strict)
  root_midi = Note.to_midi(root)
  intervals = TYPES[type] || @custom_types[type]
  raise InvalidMessageError, "Unknown scale type: #{type}" unless intervals

  apply_range_policy(intervals.map { |i| root_midi + i }, range)
end

.define(name, intervals) ⇒ Object



36
37
38
39
40
# File 'lib/webmidi/music/scale.rb', line 36

def define(name, intervals)
  validate_intervals!(intervals)
  @custom_types[name] = intervals
  self
end

.degree(root, type, degree_num) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/webmidi/music/scale.rb', line 46

def degree(root, type, degree_num)
  unless degree_num.is_a?(Integer) && degree_num.positive?
    raise InvalidMessageError, "Scale degree must be a positive integer, got #{degree_num.inspect}"
  end

  root_midi = Note.to_midi(root)
  intervals = TYPES[type] || @custom_types[type]
  raise InvalidMessageError, "Unknown scale type: #{type}" unless intervals

  index = (degree_num - 1) % intervals.size
  octave = (degree_num - 1) / intervals.size
  note = root_midi + intervals[index] + (octave * 12)
  Note.validate_midi!(note)
  note
end

.typesObject



42
43
44
# File 'lib/webmidi/music/scale.rb', line 42

def types
  TYPES.keys + @custom_types.keys
end