Class: HeadMusic::Analysis::DiatonicInterval

Inherits:
Object
  • Object
show all
Includes:
Comparable, Named
Defined in:
lib/head_music/analysis/diatonic_interval.rb

Overview

A diatonic interval is the distance between two spelled pitches.

Defined Under Namespace

Classes: Category, Naming, Parser, Semitones, Size

Constant Summary collapse

NUMBER_NAMES =
%w[
  unison second third fourth fifth sixth seventh octave
  ninth tenth eleventh twelfth thirteenth fourteenth fifteenth
  sixteenth seventeenth
].freeze
NAME_SUFFIXES =
Hash.new("th").merge(1 => "st", 2 => "nd", 3 => "rd").freeze
QUALITY_SEMITONES =
{
  unison: {perfect: 0},
  second: {major: 2},
  third: {major: 4},
  fourth: {perfect: 5},
  fifth: {perfect: 7},
  sixth: {major: 9},
  seventh: {major: 11},
  octave: {perfect: 12},
  ninth: {major: 14},
  tenth: {major: 16},
  eleventh: {perfect: 17},
  twelfth: {perfect: 19},
  thirteenth: {major: 21},
  fourteenth: {major: 23},
  fifteenth: {perfect: 24},
  sixteenth: {major: 26},
  seventeenth: {major: 28}
}.freeze
QUALITY_ABBREVIATIONS =
{
  P: "perfect",
  M: "major",
  m: "minor",
  d: "diminished",
  A: "augmented"
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(first_pitch, second_pitch) ⇒ DiatonicInterval

Returns a new instance of DiatonicInterval.



90
91
92
93
94
# File 'lib/head_music/analysis/diatonic_interval.rb', line 90

def initialize(first_pitch, second_pitch)
  first_pitch = HeadMusic::Rudiment::Pitch.get(first_pitch)
  second_pitch = HeadMusic::Rudiment::Pitch.get(second_pitch)
  @lower_pitch, @higher_pitch = [first_pitch, second_pitch].sort
end

Instance Attribute Details

#alias_name_keysObject (readonly) Originally defined in module Named

Returns the value of attribute alias_name_keys.

#higher_pitchObject (readonly)

Returns the value of attribute higher_pitch.



44
45
46
# File 'lib/head_music/analysis/diatonic_interval.rb', line 44

def higher_pitch
  @higher_pitch
end

#lower_pitchObject (readonly)

Returns the value of attribute lower_pitch.



44
45
46
# File 'lib/head_music/analysis/diatonic_interval.rb', line 44

def lower_pitch
  @lower_pitch
end

#name_keyObject (readonly) Originally defined in module Named

Returns the value of attribute name_key.

Class Method Details

.get(identifier) ⇒ Object

Accepts a name and returns the interval with middle c on the bottom



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/head_music/analysis/diatonic_interval.rb', line 77

def self.get(identifier)
  if identifier.is_a?(String) || identifier.is_a?(Symbol)
    name = Parser.new(identifier)
    semitones = Semitones.new(name.degree_name.to_sym, name.quality_name).count
    higher_pitch = HeadMusic::Rudiment::Pitch.from_number_and_letter(HeadMusic::Rudiment::Pitch.middle_c + semitones, name.higher_letter)
    interval = new(HeadMusic::Rudiment::Pitch.middle_c, higher_pitch)
    interval.ensure_localized_name(name: identifier.to_s)
    interval
  else
    identifier
  end
end

Instance Method Details

#<=>(other) ⇒ Object



158
159
160
161
# File 'lib/head_music/analysis/diatonic_interval.rb', line 158

def <=>(other)
  other = self.class.get(other) unless other.is_a?(HeadMusic::Analysis::DiatonicInterval)
  semitones <=> other.semitones
end

#above(pitch) ⇒ Object



136
137
138
139
# File 'lib/head_music/analysis/diatonic_interval.rb', line 136

def above(pitch)
  pitch = HeadMusic::Rudiment::Pitch.get(pitch)
  HeadMusic::Rudiment::Pitch.from_number_and_letter(pitch + semitones, pitch.letter_name.steps_up(number - 1))
end

#below(pitch) ⇒ Object



141
142
143
144
# File 'lib/head_music/analysis/diatonic_interval.rb', line 141

def below(pitch)
  pitch = HeadMusic::Rudiment::Pitch.get(pitch)
  HeadMusic::Rudiment::Pitch.from_number_and_letter(pitch - semitones, pitch.letter_name.steps_down(number - 1))
end

#categoryObject (private)



177
178
179
# File 'lib/head_music/analysis/diatonic_interval.rb', line 177

def category
  @category ||= Category.new(number)
end

#consonance(style = :standard_practice) ⇒ Object



113
114
115
116
117
# File 'lib/head_music/analysis/diatonic_interval.rb', line 113

def consonance(style = :standard_practice)
  consonance_for_perfect(style) ||
    consonance_for_major_and_minor ||
    HeadMusic::Rudiment::Consonance.get(:dissonant)
end

#consonance?(style = :standard_practice) ⇒ Boolean Also known as: consonant?

Returns:

  • (Boolean)


119
120
121
# File 'lib/head_music/analysis/diatonic_interval.rb', line 119

def consonance?(style = :standard_practice)
  consonance(style).perfect? || consonance(style).imperfect?
end

#consonance_for_major_and_minorObject (private)



189
190
191
# File 'lib/head_music/analysis/diatonic_interval.rb', line 189

def consonance_for_major_and_minor
  HeadMusic::Rudiment::Consonance.get((third_or_compound? || sixth_or_compound?) ? :imperfect : :dissonant) if major? || minor?
end

#consonance_for_perfect(style = :standard_practice) ⇒ Object (private)



185
186
187
# File 'lib/head_music/analysis/diatonic_interval.rb', line 185

def consonance_for_perfect(style = :standard_practice)
  HeadMusic::Rudiment::Consonance.get(dissonant_fourth?(style) ? :dissonant : :perfect) if perfect?
end

#dissonance?(style = :standard_practice) ⇒ Boolean

Returns:

  • (Boolean)


132
133
134
# File 'lib/head_music/analysis/diatonic_interval.rb', line 132

def dissonance?(style = :standard_practice)
  consonance(style).dissonant?
end

#dissonant_fourth?(style = :standard_practice) ⇒ Boolean (private)

Returns:

  • (Boolean)


193
194
195
# File 'lib/head_music/analysis/diatonic_interval.rb', line 193

def dissonant_fourth?(style = :standard_practice)
  fourth_or_compound? && style == :two_part_harmony
end

#ensure_localized_name(name:, locale_code: Locale::DEFAULT_CODE, abbreviation: nil) ⇒ Object Originally defined in module Named

#imperfect_consonance?(style = :standard_practice) ⇒ Boolean

Returns:

  • (Boolean)


128
129
130
# File 'lib/head_music/analysis/diatonic_interval.rb', line 128

def imperfect_consonance?(style = :standard_practice)
  consonance(style).imperfect?
end

#interval_classObject



146
147
148
# File 'lib/head_music/analysis/diatonic_interval.rb', line 146

def interval_class
  [simple_semitones, 12 - simple_semitones].min
end

#interval_class_nameObject



150
151
152
# File 'lib/head_music/analysis/diatonic_interval.rb', line 150

def interval_class_name
  "ic #{interval_class}"
end

#inversionObject Also known as: invert



104
105
106
107
108
109
110
# File 'lib/head_music/analysis/diatonic_interval.rb', line 104

def inversion
  inverted_low_pitch = lower_pitch
  while inverted_low_pitch < higher_pitch
    inverted_low_pitch = HeadMusic::Rudiment::Pitch.fetch_or_create(lower_pitch.spelling, inverted_low_pitch.register + 1)
  end
  HeadMusic::Analysis::DiatonicInterval.new(higher_pitch, inverted_low_pitch)
end

#localized_name(locale_code: Locale::DEFAULT_CODE) ⇒ Object Originally defined in module Named

#localized_name_in_default_localeObject (private) Originally defined in module Named

#localized_name_in_locale_matching_language(locale) ⇒ Object (private) Originally defined in module Named

#localized_name_in_matching_locale(locale) ⇒ Object (private) Originally defined in module Named

#localized_namesObject Originally defined in module Named

Returns an array of LocalizedName instances that are synonymous with the name.

#name(locale_code: nil) ⇒ Object

Override Named module methods to use computed name from naming



61
62
63
64
65
66
67
68
69
70
# File 'lib/head_music/analysis/diatonic_interval.rb', line 61

def name(locale_code: nil)
  if locale_code
    # Try to get translation from locale files
    name_key = naming.name.downcase.gsub(" ", "_").to_sym
    translation = I18n.translate(name_key, scope: "head_music.diatonic_intervals", locale: locale_code, default: nil)
    translation || naming.name
  else
    naming.name
  end
end

#name=(name) ⇒ Object Originally defined in module Named

#namingObject (private)



181
182
183
# File 'lib/head_music/analysis/diatonic_interval.rb', line 181

def naming
  @naming ||= Naming.new(number: number, semitones: semitones)
end

#perfect_consonance?(style = :standard_practice) ⇒ Boolean

Returns:

  • (Boolean)


124
125
126
# File 'lib/head_music/analysis/diatonic_interval.rb', line 124

def perfect_consonance?(style = :standard_practice)
  consonance(style).perfect?
end

#qualityObject



100
101
102
# File 'lib/head_music/analysis/diatonic_interval.rb', line 100

def quality
  HeadMusic::Rudiment::Quality.get(quality_name)
end

#sizeObject (private)



173
174
175
# File 'lib/head_music/analysis/diatonic_interval.rb', line 173

def size
  @size ||= Size.new(@lower_pitch, @higher_pitch)
end

#spans?(pitch) ⇒ Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/head_music/analysis/diatonic_interval.rb', line 96

def spans?(pitch)
  pitch.between?(lower_pitch, higher_pitch)
end

#to_sObject



72
73
74
# File 'lib/head_music/analysis/diatonic_interval.rb', line 72

def to_s
  name
end