Class: HeadMusic::Analysis::ChordAnalysis

Inherits:
Object
  • Object
show all
Defined in:
lib/head_music/analysis/chord_analysis.rb

Overview

Classifies a PitchCollection as a tertian chord: whether it is a triad, seventh, or extended chord; its triad quality (major/minor/diminished/ augmented); and its inversion. “Tertian” means the pitches, once reduced to within an octave and rotated, stack in thirds.

Constant Summary collapse

TERTIAN_SONORITIES =

Scale-degree signatures (above the bass) of each tertian chord size, used to recognize a stack of thirds in any rotation.

{
  implied_triad: [3],
  triad: [3, 5],
  seventh_chord: [3, 5, 7],
  ninth_chord: [2, 3, 5, 7],
  eleventh_chord: [2, 3, 4, 5, 7],
  thirteenth_chord: [2, 3, 4, 5, 6, 7] # a.k.a. diatonic scale
}.freeze
TRIAD_PATTERNS =

The interval-shorthand pairs (bass-to-third, third-to-fifth) that spell each triad quality, in every inversion.

{
  major: [%w[M3 m3], %w[m3 P4], %w[P4 M3]],
  minor: [%w[m3 M3], %w[M3 P4], %w[P4 m3]],
  diminished: [%w[m3 m3], %w[m3 A4], %w[A4 m3]],
  augmented: [%w[M3 M3], %w[M3 d4], %w[d4 M3]]
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(collection) ⇒ ChordAnalysis

Returns a new instance of ChordAnalysis.



31
32
33
# File 'lib/head_music/analysis/chord_analysis.rb', line 31

def initialize(collection)
  @collection = collection
end

Instance Attribute Details

#collectionObject (readonly)

Returns the value of attribute collection.



29
30
31
# File 'lib/head_music/analysis/chord_analysis.rb', line 29

def collection
  @collection
end

Instance Method Details

#augmented_triad?Boolean

Returns:

  • (Boolean)


55
56
57
# File 'lib/head_music/analysis/chord_analysis.rb', line 55

def augmented_triad?
  triad_type?(:augmented)
end

#consonant_triad?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/head_music/analysis/chord_analysis.rb', line 39

def consonant_triad?
  major_triad? || minor_triad?
end

#diminished_triad?Boolean

Returns:

  • (Boolean)


51
52
53
# File 'lib/head_music/analysis/chord_analysis.rb', line 51

def diminished_triad?
  triad_type?(:diminished)
end

#eleventh_chord?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/head_music/analysis/chord_analysis.rb', line 95

def eleventh_chord?
  collection.hexachord? && tertian?
end

#first_inversion_seventh_chord?Boolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/head_music/analysis/chord_analysis.rb', line 79

def first_inversion_seventh_chord?
  collection.tetrachord? && stacked_in_thirds?(collection.reduction.uninvert)
end

#first_inversion_triad?Boolean

Returns:

  • (Boolean)


63
64
65
# File 'lib/head_music/analysis/chord_analysis.rb', line 63

def first_inversion_triad?
  collection.trichord? && stacked_in_thirds?(collection.reduction.uninvert)
end

#major_triad?Boolean

Returns:

  • (Boolean)


43
44
45
# File 'lib/head_music/analysis/chord_analysis.rb', line 43

def major_triad?
  triad_type?(:major)
end

#minor_triad?Boolean

Returns:

  • (Boolean)


47
48
49
# File 'lib/head_music/analysis/chord_analysis.rb', line 47

def minor_triad?
  triad_type?(:minor)
end

#ninth_chord?Boolean

Returns:

  • (Boolean)


91
92
93
# File 'lib/head_music/analysis/chord_analysis.rb', line 91

def ninth_chord?
  collection.pentachord? && tertian?
end

#root_position_seventh_chord?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/head_music/analysis/chord_analysis.rb', line 75

def root_position_seventh_chord?
  collection.tetrachord? && stacked_in_thirds?(collection.reduction)
end

#root_position_triad?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/head_music/analysis/chord_analysis.rb', line 59

def root_position_triad?
  collection.trichord? && stacked_in_thirds?(collection.reduction)
end

#second_inversion_seventh_chord?Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/head_music/analysis/chord_analysis.rb', line 83

def second_inversion_seventh_chord?
  collection.tetrachord? && stacked_in_thirds?(collection.reduction.uninvert.uninvert)
end

#second_inversion_triad?Boolean

Returns:

  • (Boolean)


67
68
69
# File 'lib/head_music/analysis/chord_analysis.rb', line 67

def second_inversion_triad?
  collection.trichord? && stacked_in_thirds?(collection.reduction.invert)
end

#seventh_chord?Boolean

Returns:

  • (Boolean)


71
72
73
# File 'lib/head_music/analysis/chord_analysis.rb', line 71

def seventh_chord?
  collection.tetrachord? && tertian?
end

#stacked_in_thirds?(reduced_collection) ⇒ Boolean (private)

Returns:

  • (Boolean)


120
121
122
# File 'lib/head_music/analysis/chord_analysis.rb', line 120

def stacked_in_thirds?(reduced_collection)
  reduced_collection.diatonic_intervals.all?(&:third?)
end

#tertian?Boolean

Returns:

  • (Boolean)


103
104
105
106
107
108
109
110
111
112
# File 'lib/head_music/analysis/chord_analysis.rb', line 103

def tertian?
  return false unless collection.diatonic_intervals.any?

  inversion = collection.reduction
  collection.pitches.length.times do
    return true if TERTIAN_SONORITIES.value?(inversion.scale_degrees_above_bass_pitch)
    inversion = inversion.invert
  end
  false
end

#third_inversion_seventh_chord?Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/head_music/analysis/chord_analysis.rb', line 87

def third_inversion_seventh_chord?
  collection.tetrachord? && stacked_in_thirds?(collection.reduction.invert)
end

#thirteenth_chord?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/head_music/analysis/chord_analysis.rb', line 99

def thirteenth_chord?
  collection.heptachord? && tertian?
end

#triad?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/head_music/analysis/chord_analysis.rb', line 35

def triad?
  collection.trichord? && tertian?
end

#triad_type?(type) ⇒ Boolean (private)

Returns:

  • (Boolean)


116
117
118
# File 'lib/head_music/analysis/chord_analysis.rb', line 116

def triad_type?(type)
  TRIAD_PATTERNS[type].include?(collection.reduction_diatonic_intervals.map(&:shorthand))
end