Class: HeadMusic::Analysis::PitchSet
- Inherits:
-
Object
- Object
- HeadMusic::Analysis::PitchSet
- Defined in:
- lib/head_music/analysis/pitch_set.rb
Overview
A PitchSet is a collection of one or more pitches. 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
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) ⇒ PitchSet
constructor
A new instance of PitchSet.
- #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
- #tertian? ⇒ Boolean
- #third_inversion_seventh_chord? ⇒ Boolean
- #thirteenth_chord? ⇒ Boolean
- #to_s ⇒ Object
- #triad? ⇒ Boolean
- #uninvert ⇒ Object
Constructor Details
#initialize(pitches) ⇒ PitchSet
25 26 27 |
# File 'lib/head_music/analysis/pitch_set.rb', line 25 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.
16 17 18 |
# File 'lib/head_music/analysis/pitch_set.rb', line 16 def pitches @pitches end |
Instance Method Details
#==(other) ⇒ Object
91 92 93 |
# File 'lib/head_music/analysis/pitch_set.rb', line 91 def ==(other) pitches.sort == other.pitches.sort end |
#augmented_triad? ⇒ Boolean
123 124 125 |
# File 'lib/head_music/analysis/pitch_set.rb', line 123 def augmented_triad? [%w[M3 M3], %w[M3 d4], %w[d4 M3]].include? reduction_diatonic_intervals.map(&:shorthand) end |
#bass_pitch ⇒ Object
79 80 81 |
# File 'lib/head_music/analysis/pitch_set.rb', line 79 def bass_pitch @bass_pitch ||= pitches.first end |
#consonant_triad? ⇒ Boolean
107 108 109 |
# File 'lib/head_music/analysis/pitch_set.rb', line 107 def consonant_triad? major_triad? || minor_triad? end |
#diatonic_intervals ⇒ Object
41 42 43 44 45 |
# File 'lib/head_music/analysis/pitch_set.rb', line 41 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
47 48 49 50 51 |
# File 'lib/head_music/analysis/pitch_set.rb', line 47 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
119 120 121 |
# File 'lib/head_music/analysis/pitch_set.rb', line 119 def diminished_triad? [%w[m3 m3], %w[m3 A4], %w[A4 m3]].include? reduction_diatonic_intervals.map(&:shorthand) end |
#eleventh_chord? ⇒ Boolean
163 164 165 |
# File 'lib/head_music/analysis/pitch_set.rb', line 163 def eleventh_chord? hexachord? && tertian? end |
#equivalent?(other) ⇒ Boolean
95 96 97 |
# File 'lib/head_music/analysis/pitch_set.rb', line 95 def equivalent?(other) pitch_classes.sort == other.pitch_classes.sort end |
#first_inversion_seventh_chord? ⇒ Boolean
147 148 149 |
# File 'lib/head_music/analysis/pitch_set.rb', line 147 def first_inversion_seventh_chord? tetrachord? && reduction.uninvert.diatonic_intervals.all?(&:third?) end |
#first_inversion_triad? ⇒ Boolean
131 132 133 |
# File 'lib/head_music/analysis/pitch_set.rb', line 131 def first_inversion_triad? trichord? && reduction.uninvert.diatonic_intervals.all?(&:third?) end |
#inspect ⇒ Object
83 84 85 |
# File 'lib/head_music/analysis/pitch_set.rb', line 83 def inspect pitches.map(&:to_s).join(" ") end |
#integer_notation ⇒ Object
57 58 59 60 61 62 63 64 65 |
# File 'lib/head_music/analysis/pitch_set.rb', line 57 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
67 68 69 70 71 |
# File 'lib/head_music/analysis/pitch_set.rb', line 67 def invert inverted_pitch = pitches[0] + HeadMusic::Analysis::DiatonicInterval.get("perfect octave") new_pitches = pitches.drop(1) + [inverted_pitch] HeadMusic::Analysis::PitchSet.new(new_pitches) end |
#major_triad? ⇒ Boolean
111 112 113 |
# File 'lib/head_music/analysis/pitch_set.rb', line 111 def major_triad? [%w[M3 m3], %w[m3 P4], %w[P4 M3]].include? reduction_diatonic_intervals.map(&:shorthand) end |
#minor_triad? ⇒ Boolean
115 116 117 |
# File 'lib/head_music/analysis/pitch_set.rb', line 115 def minor_triad? [%w[m3 M3], %w[M3 P4], %w[P4 m3]].include? reduction_diatonic_intervals.map(&:shorthand) end |
#ninth_chord? ⇒ Boolean
159 160 161 |
# File 'lib/head_music/analysis/pitch_set.rb', line 159 def ninth_chord? pentachord? && tertian? end |
#pitch_class_set ⇒ Object
33 34 35 |
# File 'lib/head_music/analysis/pitch_set.rb', line 33 def pitch_class_set @pitch_class_set ||= HeadMusic::Analysis::PitchClassSet.new(pitch_classes) end |
#pitch_classes ⇒ Object
29 30 31 |
# File 'lib/head_music/analysis/pitch_set.rb', line 29 def pitch_classes @pitch_classes ||= reduction_pitches.map(&:pitch_class).uniq end |
#pitches_above_bass_pitch ⇒ Object
53 54 55 |
# File 'lib/head_music/analysis/pitch_set.rb', line 53 def pitches_above_bass_pitch @pitches_above_bass_pitch ||= pitches.drop(1) end |
#reduction ⇒ Object
37 38 39 |
# File 'lib/head_music/analysis/pitch_set.rb', line 37 def reduction @reduction ||= HeadMusic::Analysis::PitchSet.new(reduction_pitches) end |
#reduction_pitches ⇒ Object (private)
192 193 194 195 196 197 |
# File 'lib/head_music/analysis/pitch_set.rb', line 192 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
143 144 145 |
# File 'lib/head_music/analysis/pitch_set.rb', line 143 def root_position_seventh_chord? tetrachord? && reduction_diatonic_intervals.all?(&:third?) end |
#root_position_triad? ⇒ Boolean
127 128 129 |
# File 'lib/head_music/analysis/pitch_set.rb', line 127 def root_position_triad? trichord? && reduction_diatonic_intervals.all?(&:third?) end |
#scale_degrees ⇒ Object
182 183 184 |
# File 'lib/head_music/analysis/pitch_set.rb', line 182 def scale_degrees @scale_degrees ||= pitches.empty? ? [] : scale_degrees_above_bass_pitch.unshift(1) end |
#scale_degrees_above_bass_pitch ⇒ Object
186 187 188 |
# File 'lib/head_music/analysis/pitch_set.rb', line 186 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
151 152 153 |
# File 'lib/head_music/analysis/pitch_set.rb', line 151 def second_inversion_seventh_chord? tetrachord? && reduction.uninvert.uninvert.diatonic_intervals.all?(&:third?) end |
#second_inversion_triad? ⇒ Boolean
135 136 137 |
# File 'lib/head_music/analysis/pitch_set.rb', line 135 def second_inversion_triad? trichord? && reduction.invert.diatonic_intervals.all?(&:third?) end |
#seventh_chord? ⇒ Boolean
139 140 141 |
# File 'lib/head_music/analysis/pitch_set.rb', line 139 def seventh_chord? tetrachord? && tertian? end |
#size ⇒ Object
99 100 101 |
# File 'lib/head_music/analysis/pitch_set.rb', line 99 def size pitches.length end |
#tertian? ⇒ Boolean
171 172 173 174 175 176 177 178 179 180 |
# File 'lib/head_music/analysis/pitch_set.rb', line 171 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
155 156 157 |
# File 'lib/head_music/analysis/pitch_set.rb', line 155 def third_inversion_seventh_chord? tetrachord? && reduction.invert.diatonic_intervals.all?(&:third?) end |
#thirteenth_chord? ⇒ Boolean
167 168 169 |
# File 'lib/head_music/analysis/pitch_set.rb', line 167 def thirteenth_chord? heptachord? && tertian? end |
#to_s ⇒ Object
87 88 89 |
# File 'lib/head_music/analysis/pitch_set.rb', line 87 def to_s pitches.map(&:to_s).join(" ") end |
#triad? ⇒ Boolean
103 104 105 |
# File 'lib/head_music/analysis/pitch_set.rb', line 103 def triad? trichord? && tertian? end |
#uninvert ⇒ Object
73 74 75 76 77 |
# File 'lib/head_music/analysis/pitch_set.rb', line 73 def uninvert inverted_pitch = pitches[-1] - HeadMusic::Analysis::DiatonicInterval.get("perfect octave") new_pitches = [inverted_pitch] + pitches[0..-2] HeadMusic::Analysis::PitchSet.new(new_pitches) end |