Class Scale
In: app/models/scale.rb
Parent: ActiveRecord::Base

A scale is an ordered collection of tones.

Creating a Scale

Scale objects should be created by indexing the Scale class directly:

  Scale['Major']

An alternative method of resolving a chord is to use the resolve method, though this is likely to become deprecated in the future when chord progression support/representation is added:

  Scale.resolve(name)

Associations

  • modes - Associated modes.
  • main_mode - Associated mode with a mode index of 1 (first mode). This sometimes
      the only defined mode such as for the whole tone scale.
    
  • tones - A collection of +ScaleTone+s.
  • notes - An array of notes (delegated through tones)
  • chords - A collection of associated chords with the first mode of this scale.

Modes

Each scale can have one or many modes, which really define the relationship to chords. Modes are accessible like so (all methods are equal):

  Scale['Major']['Dorian']
  Scale['Major'][2]
  Scale['Major'].modes['Dorian']
  Scale['Major'].modes[2]

Examples

Listing Tones in Scales

  Scale['Major'].notes
  # => ["C", "D", "E", "F", "G", "A", "B"]

  Scale['Major'].in_key_of('Eb').notes
  Scale['Eb Major'].notes  # Same as above
  # => ["Eb", "F", "G", "Ab", "Bb", "C", "D"]

Correctly Interpets Theoretical Keys (not just pitches)

  Scale['Gb Major'].notes
  # => ["Gb", "Ab", "Bb", "Cb", "Db", "Eb", "F"]
  # Note the use of Cb which is theoretically correct over enharmonic B.

Also correctly interpet tones off of enharmonic base keys:

  Scale['Gb Major'].notes
  # => ["Gb", "Ab", "Bb", "Cb", "Db", "Eb", "F"]
  Scale['F# Major'].notes
  # => ["F#", "G#", "A#", "B", "C#", "D#", "E#"]

Listing Tones within the context of a mode

  Scale['Major'].modes['Dorian']
  Scale['Major']['Dorian']  # Same as above
  # => ["D", "E", "F", "G", "A", "B", "C"]

  Scale['Melodic Minor'].modes['Super Locrian'].notes
  # => ["B", "C", "D", "Eb", "F", "G", "A"]  # aka. Altered Scale or Dim. Whole Tone

Listing Related Chords

  Scale['Major'].chords.symbols
  # => ['maj7', 'maj6', '6/9']
  Scale['Major']['Dorian'].chords.symbols
  # => ['min7', 'min6']

Methods

[]   main_mode   resolve   symmetric?   to_xml  

Included Modules

KeyContext ModeContext

External Aliases

resolve -> []

Public Class methods

[Source]

     # File app/models/scale.rb, line 87
 87:                 def resolve(symbol)
 88:                         in_key = nil
 89:                         
 90:                         return nil if symbol.nil?
 91:                         symbol = symbol.dup
 92:                         
 93:                         Key.all.each do |k|
 94:                                 if symbol.starts_with?(k.name)
 95:                                         in_key = k
 96:                                         symbol.gsub!(/^#{k.name}/, '').strip!
 97:                                         break
 98:                                 end
 99:                         end
100:                         
101:                         scale = Scale.find_by_name(symbol)
102:                         
103:                         # Perhaps the matched key was really part of the name of the chord, try that:
104:                         if scale.nil? && !in_key.nil?
105:                                 symbol = in_key.name + symbol
106:                                 scale = Scale.all.detect {|s| s.name == symbol}
107:                         end
108:                         
109:                         # If still not found, must be invalid:
110:                         return nil if scale.nil?
111:                         
112:                         scale.key = in_key
113:                         scale
114:                 end

Public Instance methods

[Source]

     # File app/models/scale.rb, line 118
118:         def [](name)
119:                 name.is_a?(String) ? self.modes.find_by_name(name) : self.modes.find_by_mode(name)
120:         end

[Source]

     # File app/models/scale.rb, line 122
122:         def main_mode
123:                 self[1]
124:         end

[Source]

     # File app/models/scale.rb, line 126
126:         def symmetric?
127:                 !self.symmetry_index.nil?
128:         end

[Source]

     # File app/models/scale.rb, line 131
131:         def to_xml(options = {})
132:                 super(options.merge(:skip_types => true))
133:         end

[Validate]