Class: HeadMusic::Analysis::PitchCollection
- Inherits:
-
Object
- Object
- HeadMusic::Analysis::PitchCollection
- Defined in:
- lib/head_music/analysis/pitch_collection.rb
Overview
A PitchCollection is a collection of one or more pitches with specific registers. In music theory, "pitch collection" refers to an ordered or unordered group of actual pitches, as distinct from a "pitch-class set" which abstracts away register and octave equivalence. See also: PitchClassSet
Constant Summary collapse
- TERTIAN_SONORITIES =
{ 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 =
{ 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
-
#pitches ⇒ Object
readonly
Returns the value of attribute pitches.
Instance Method Summary collapse
- #==(other) ⇒ Object
- #augmented_triad? ⇒ Boolean
- #bass_pitch ⇒ Object
- #consonant_triad? ⇒ Boolean
- #diatonic_intervals ⇒ Object
- #diatonic_intervals_above_bass_pitch ⇒ Object
- #diminished_triad? ⇒ Boolean
- #eleventh_chord? ⇒ Boolean
- #equivalent?(other) ⇒ Boolean
- #first_inversion_seventh_chord? ⇒ Boolean
- #first_inversion_triad? ⇒ Boolean
-
#initialize(pitches) ⇒ PitchCollection
constructor
A new instance of PitchCollection.
- #inspect ⇒ Object
- #integer_notation ⇒ Object
- #invert ⇒ Object
- #major_triad? ⇒ Boolean
- #minor_triad? ⇒ Boolean
- #ninth_chord? ⇒ Boolean
- #pitch_class_set ⇒ Object
- #pitch_classes ⇒ Object
- #pitches_above_bass_pitch ⇒ Object
- #reduction ⇒ Object
- #reduction_pitches ⇒ Object private
- #root_position_seventh_chord? ⇒ Boolean
- #root_position_triad? ⇒ Boolean
- #scale_degrees ⇒ Object
- #scale_degrees_above_bass_pitch ⇒ Object
- #second_inversion_seventh_chord? ⇒ Boolean
- #second_inversion_triad? ⇒ Boolean
- #seventh_chord? ⇒ Boolean
- #size ⇒ Object
- #sonority ⇒ Object
- #tertian? ⇒ Boolean
- #third_inversion_seventh_chord? ⇒ Boolean
- #thirteenth_chord? ⇒ Boolean
- #to_s ⇒ Object
- #triad? ⇒ Boolean
- #triad_type?(type) ⇒ Boolean private
- #uninvert ⇒ Object
Constructor Details
#initialize(pitches) ⇒ PitchCollection
Returns a new instance of PitchCollection.
27 28 29 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 27 def initialize(pitches) @pitches = pitches.map { |pitch| HeadMusic::Rudiment::Pitch.get(pitch) }.sort.uniq end |
Instance Attribute Details
#pitches ⇒ Object (readonly)
Returns the value of attribute pitches.
18 19 20 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 18 def pitches @pitches end |
Instance Method Details
#==(other) ⇒ Object
93 94 95 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 93 def ==(other) pitches.sort == other.pitches.sort end |
#augmented_triad? ⇒ Boolean
132 133 134 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 132 def augmented_triad? triad_type?(:augmented) end |
#bass_pitch ⇒ Object
81 82 83 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 81 def bass_pitch @bass_pitch ||= pitches.first end |
#consonant_triad? ⇒ Boolean
109 110 111 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 109 def consonant_triad? major_triad? || minor_triad? end |
#diatonic_intervals ⇒ Object
43 44 45 46 47 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 43 def diatonic_intervals @diatonic_intervals ||= pitches.each_cons(2).map do |pitch_pair| HeadMusic::Analysis::DiatonicInterval.new(*pitch_pair) end end |
#diatonic_intervals_above_bass_pitch ⇒ Object
49 50 51 52 53 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 49 def diatonic_intervals_above_bass_pitch @diatonic_intervals_above_bass_pitch ||= pitches_above_bass_pitch.map do |pitch| HeadMusic::Analysis::DiatonicInterval.new(bass_pitch, pitch) end end |
#diminished_triad? ⇒ Boolean
128 129 130 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 128 def diminished_triad? triad_type?(:diminished) end |
#eleventh_chord? ⇒ Boolean
172 173 174 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 172 def eleventh_chord? hexachord? && tertian? end |
#equivalent?(other) ⇒ Boolean
97 98 99 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 97 def equivalent?(other) pitch_classes.sort == other.pitch_classes.sort end |
#first_inversion_seventh_chord? ⇒ Boolean
156 157 158 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 156 def first_inversion_seventh_chord? tetrachord? && reduction.uninvert.diatonic_intervals.all?(&:third?) end |
#first_inversion_triad? ⇒ Boolean
140 141 142 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 140 def first_inversion_triad? trichord? && reduction.uninvert.diatonic_intervals.all?(&:third?) end |
#inspect ⇒ Object
85 86 87 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 85 def inspect pitches.map(&:to_s).join(" ") end |
#integer_notation ⇒ Object
59 60 61 62 63 64 65 66 67 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 59 def integer_notation # questions: # - should this be absolute? 0 = C? # - should there be both absolute and relative versions? @integer_notation ||= begin return [] if pitches.empty? diatonic_intervals_above_bass_pitch.map { |interval| interval.semitones % 12 }.flatten.sort.unshift(0).uniq end end |
#invert ⇒ Object
69 70 71 72 73 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 69 def invert inverted_pitch = pitches[0] + HeadMusic::Analysis::DiatonicInterval.get("perfect octave") new_pitches = pitches.drop(1) + [inverted_pitch] HeadMusic::Analysis::PitchCollection.new(new_pitches) end |
#major_triad? ⇒ Boolean
120 121 122 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 120 def major_triad? triad_type?(:major) end |
#minor_triad? ⇒ Boolean
124 125 126 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 124 def minor_triad? triad_type?(:minor) end |
#ninth_chord? ⇒ Boolean
168 169 170 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 168 def ninth_chord? pentachord? && tertian? end |
#pitch_class_set ⇒ Object
35 36 37 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 35 def pitch_class_set @pitch_class_set ||= HeadMusic::Analysis::PitchClassSet.new(pitch_classes) end |
#pitch_classes ⇒ Object
31 32 33 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 31 def pitch_classes @pitch_classes ||= reduction_pitches.map(&:pitch_class).uniq end |
#pitches_above_bass_pitch ⇒ Object
55 56 57 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 55 def pitches_above_bass_pitch @pitches_above_bass_pitch ||= pitches.drop(1) end |
#reduction ⇒ Object
39 40 41 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 39 def reduction @reduction ||= HeadMusic::Analysis::PitchCollection.new(reduction_pitches) end |
#reduction_pitches ⇒ Object (private)
209 210 211 212 213 214 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 209 def reduction_pitches pitches.map do |pitch| pitch = HeadMusic::Rudiment::Pitch.fetch_or_create(pitch.spelling, pitch.register - 1) while pitch > bass_pitch + 12 pitch end.sort end |
#root_position_seventh_chord? ⇒ Boolean
152 153 154 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 152 def root_position_seventh_chord? tetrachord? && reduction_diatonic_intervals.all?(&:third?) end |
#root_position_triad? ⇒ Boolean
136 137 138 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 136 def root_position_triad? trichord? && reduction_diatonic_intervals.all?(&:third?) end |
#scale_degrees ⇒ Object
191 192 193 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 191 def scale_degrees @scale_degrees ||= pitches.empty? ? [] : scale_degrees_above_bass_pitch.unshift(1) end |
#scale_degrees_above_bass_pitch ⇒ Object
195 196 197 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 195 def scale_degrees_above_bass_pitch @scale_degrees_above_bass_pitch ||= diatonic_intervals_above_bass_pitch.map(&:simple_number).sort - [8] end |
#second_inversion_seventh_chord? ⇒ Boolean
160 161 162 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 160 def second_inversion_seventh_chord? tetrachord? && reduction.uninvert.uninvert.diatonic_intervals.all?(&:third?) end |
#second_inversion_triad? ⇒ Boolean
144 145 146 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 144 def second_inversion_triad? trichord? && reduction.invert.diatonic_intervals.all?(&:third?) end |
#seventh_chord? ⇒ Boolean
148 149 150 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 148 def seventh_chord? tetrachord? && tertian? end |
#size ⇒ Object
101 102 103 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 101 def size pitches.length end |
#sonority ⇒ Object
199 200 201 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 199 def sonority @sonority ||= HeadMusic::Analysis::Sonority.new(self) end |
#tertian? ⇒ Boolean
180 181 182 183 184 185 186 187 188 189 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 180 def tertian? return false unless diatonic_intervals.any? inversion = reduction 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
164 165 166 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 164 def third_inversion_seventh_chord? tetrachord? && reduction.invert.diatonic_intervals.all?(&:third?) end |
#thirteenth_chord? ⇒ Boolean
176 177 178 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 176 def thirteenth_chord? heptachord? && tertian? end |
#to_s ⇒ Object
89 90 91 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 89 def to_s pitches.map(&:to_s).join(" ") end |
#triad? ⇒ Boolean
105 106 107 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 105 def triad? trichord? && tertian? end |
#triad_type?(type) ⇒ Boolean (private)
205 206 207 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 205 def triad_type?(type) TRIAD_PATTERNS[type].include?(reduction_diatonic_intervals.map(&:shorthand)) end |
#uninvert ⇒ Object
75 76 77 78 79 |
# File 'lib/head_music/analysis/pitch_collection.rb', line 75 def uninvert inverted_pitch = pitches[-1] - HeadMusic::Analysis::DiatonicInterval.get("perfect octave") new_pitches = [inverted_pitch] + pitches[0..-2] HeadMusic::Analysis::PitchCollection.new(new_pitches) end |