Class: HeadMusic::Rudiment::ScaleType

Inherits:
Base
  • Object
show all
Defined in:
lib/head_music/rudiment/scale_type.rb

Overview

A ScaleType represents a particular scale pattern, such as major, lydian, or minor pentatonic.

Constant Summary collapse

H =

TODO: load scale types from yaml configuration file Include a system of aliasing, e.g. :natural_minor, :aeolian Include ascending and descending intervals for scales that differ

1
W =

half step

2
I =

Modal

[W, W, H, W, W, W, H].freeze
II =
I.rotate
III =
I.rotate(2)
IV =
I.rotate(3)
V =
I.rotate(4)
VI =
I.rotate(5)
VII =
I.rotate(6)
HARMONIC_MINOR =

Tonal

[W, H, W, W, H, 3, H].freeze
MELODIC_MINOR_ASCENDING =
[W, H, W, W, W, W, H].freeze
MODE_NAMES =
{
  i: i[ionian major],
  ii: [:dorian],
  iii: [:phrygian],
  iv: [:lydian],
  v: [:mixolydian],
  vi: i[aeolian minor natural_minor],
  vii: [:locrian]
}.freeze
CHROMATIC =
([H] * 12)
MINOR_PENTATONIC =
[3, 2, 2, 3, 2].freeze
DEFAULT =
:major
SCALE_TYPES =
{}.tap do |scales|
  scales.merge!(_modes)
  scales.merge!(_minor_scales)
  scales.merge!(_chromatic_scales)
  scales.merge!(_pentatonic_scales)
  scales.merge!(_exotic_scales)
end.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, attributes) ⇒ ScaleType

Returns a new instance of ScaleType.



113
114
115
116
117
118
# File 'lib/head_music/rudiment/scale_type.rb', line 113

def initialize(name, attributes)
  @name = name
  @ascending_intervals = attributes[:ascending]
  @descending_intervals = attributes[:descending] || ascending_intervals.reverse
  @parent_name = attributes[:parent_name]
end

Instance Attribute Details

#ascending_intervalsObject (readonly) Also known as: intervals

Returns the value of attribute ascending_intervals.



108
109
110
# File 'lib/head_music/rudiment/scale_type.rb', line 108

def ascending_intervals
  @ascending_intervals
end

#descending_intervalsObject (readonly)

Returns the value of attribute descending_intervals.



108
109
110
# File 'lib/head_music/rudiment/scale_type.rb', line 108

def descending_intervals
  @descending_intervals
end

#nameObject (readonly)

Returns the value of attribute name.



108
109
110
# File 'lib/head_music/rudiment/scale_type.rb', line 108

def name
  @name
end

#parent_nameObject (readonly)

Returns the value of attribute parent_name.



108
109
110
# File 'lib/head_music/rudiment/scale_type.rb', line 108

def parent_name
  @parent_name
end

Class Method Details

._chromatic_scalesObject



59
60
61
# File 'lib/head_music/rudiment/scale_type.rb', line 59

def self._chromatic_scales
  {chromatic: {ascending: CHROMATIC}}
end

._exotic_scalesObject



73
74
75
76
77
78
79
# File 'lib/head_music/rudiment/scale_type.rb', line 73

def self._exotic_scales
  # 'octatonic' is also called the 'whole-half diminished scale'
  {
    octatonic: {ascending: [W, H, W, H, W, H, W, H]},
    whole_tone: {ascending: [W, W, W, W, W, W]}
  }
end

._minor_scalesObject



52
53
54
55
56
57
# File 'lib/head_music/rudiment/scale_type.rb', line 52

def self._minor_scales
  {
    harmonic_minor: {ascending: HARMONIC_MINOR},
    melodic_minor: {ascending: MELODIC_MINOR_ASCENDING, descending: VI.reverse}
  }
end

._modesObject



42
43
44
45
46
47
48
49
50
# File 'lib/head_music/rudiment/scale_type.rb', line 42

def self._modes
  {}.tap do |modes|
    MODE_NAMES.each do |roman_numeral, aliases|
      intervals = {ascending: const_get(roman_numeral.upcase)}
      modes[roman_numeral] = intervals
      aliases.each { |name| modes[name] = intervals }
    end
  end
end

._pentatonic_scalesObject



63
64
65
66
67
68
69
70
71
# File 'lib/head_music/rudiment/scale_type.rb', line 63

def self._pentatonic_scales
  {
    minor_pentatonic: {ascending: MINOR_PENTATONIC, parent_name: :minor},
    major_pentatonic: {ascending: MINOR_PENTATONIC.rotate, parent_name: :major},
    egyptian_pentatonic: {ascending: MINOR_PENTATONIC.rotate(2), parent_name: :minor},
    blues_minor_pentatonic: {ascending: MINOR_PENTATONIC.rotate(3), parent_name: :minor},
    blues_major_pentatonic: {ascending: MINOR_PENTATONIC.rotate(4), parent_name: :major}
  }
end

.defaultObject



104
105
106
# File 'lib/head_music/rudiment/scale_type.rb', line 104

def self.default
  get(:major)
end

.get(name) ⇒ Object



97
98
99
100
101
102
# File 'lib/head_music/rudiment/scale_type.rb', line 97

def self.get(name)
  @scale_types ||= {}
  identifier = HeadMusic::Utilities::HashKey.for(name)
  attributes = SCALE_TYPES[identifier]
  @scale_types[identifier] ||= new(identifier, attributes)
end

Instance Method Details

#==(other) ⇒ Object



120
121
122
# File 'lib/head_music/rudiment/scale_type.rb', line 120

def ==(other)
  state == other.state
end

#chromatic?Boolean

Returns:

  • (Boolean)


144
145
146
# File 'lib/head_music/rudiment/scale_type.rb', line 144

def chromatic?
  intervals.length == 12
end

#diatonic?Boolean

Returns:

  • (Boolean)


132
133
134
# File 'lib/head_music/rudiment/scale_type.rb', line 132

def diatonic?
  intervals.length == 7
end

#parentObject



128
129
130
# File 'lib/head_music/rudiment/scale_type.rb', line 128

def parent
  @parent ||= self.class.get(parent_name) if parent_name
end

#pentatonic?Boolean

Returns:

  • (Boolean)


140
141
142
# File 'lib/head_music/rudiment/scale_type.rb', line 140

def pentatonic?
  intervals.length == 5
end

#stateObject



124
125
126
# File 'lib/head_music/rudiment/scale_type.rb', line 124

def state
  [ascending_intervals, descending_intervals]
end

#whole_tone?Boolean

Returns:

  • (Boolean)


136
137
138
# File 'lib/head_music/rudiment/scale_type.rb', line 136

def whole_tone?
  intervals.length == 6 && intervals.uniq == [2]
end