Class: HeadMusic::Analysis::PitchCollection

Inherits:
Object
  • Object
show all
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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pitches) ⇒ PitchCollection

Returns a new instance of PitchCollection.



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

def initialize(pitches)
  @pitches = pitches.map { |pitch| HeadMusic::Rudiment::Pitch.get(pitch) }.sort.uniq
end

Instance Attribute Details

#pitchesObject (readonly)

Returns the value of attribute pitches.



9
10
11
# File 'lib/head_music/analysis/pitch_collection.rb', line 9

def pitches
  @pitches
end

Instance Method Details

#==(other) ⇒ Object



92
93
94
# File 'lib/head_music/analysis/pitch_collection.rb', line 92

def ==(other)
  pitches.sort == other.pitches.sort
end

#bass_pitchObject



80
81
82
# File 'lib/head_music/analysis/pitch_collection.rb', line 80

def bass_pitch
  @bass_pitch ||= pitches.first
end

#chord_analysisObject



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

def chord_analysis
  @chord_analysis ||= HeadMusic::Analysis::ChordAnalysis.new(self)
end

#diatonic_intervalsObject



45
46
47
48
49
# File 'lib/head_music/analysis/pitch_collection.rb', line 45

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_pitchObject



51
52
53
54
55
# File 'lib/head_music/analysis/pitch_collection.rb', line 51

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

#equivalent?(other) ⇒ Boolean

Returns:

  • (Boolean)


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

def equivalent?(other)
  pitch_classes.sort == other.pitch_classes.sort
end

#folded_into_reduction(pitch) ⇒ Object (private)



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

def folded_into_reduction(pitch)
  ceiling = bass_pitch + 12
  pitch = HeadMusic::Rudiment::Pitch.fetch_or_create(pitch.spelling, pitch.register - 1) while pitch > ceiling
  pitch
end

#inspectObject



84
85
86
# File 'lib/head_music/analysis/pitch_collection.rb', line 84

def inspect
  pitches.join(" ")
end

#integer_notationObject



61
62
63
64
65
66
# File 'lib/head_music/analysis/pitch_collection.rb', line 61

def integer_notation
  # questions:
  # - should this be absolute? 0 = C?
  # - should there be both absolute and relative versions?
  @integer_notation ||= integer_notation_values
end

#integer_notation_valuesObject (private)



126
127
128
129
130
# File 'lib/head_music/analysis/pitch_collection.rb', line 126

def integer_notation_values
  return [] if pitches.empty?

  diatonic_intervals_above_bass_pitch.map { |interval| interval.semitones % 12 }.sort.unshift(0).uniq
end

#invertObject



68
69
70
71
72
# File 'lib/head_music/analysis/pitch_collection.rb', line 68

def invert
  inverted_pitch = pitches.first + octave
  new_pitches = pitches.drop(1) + [inverted_pitch]
  HeadMusic::Analysis::PitchCollection.new(new_pitches)
end

#octaveObject (private)



122
123
124
# File 'lib/head_music/analysis/pitch_collection.rb', line 122

def octave
  @octave ||= HeadMusic::Analysis::DiatonicInterval.get("perfect octave")
end

#pitch_class_setObject



37
38
39
# File 'lib/head_music/analysis/pitch_collection.rb', line 37

def pitch_class_set
  @pitch_class_set ||= HeadMusic::Analysis::PitchClassSet.new(pitch_classes)
end

#pitch_classesObject



33
34
35
# File 'lib/head_music/analysis/pitch_collection.rb', line 33

def pitch_classes
  @pitch_classes ||= reduction_pitches.map(&:pitch_class).uniq
end

#pitches_above_bass_pitchObject



57
58
59
# File 'lib/head_music/analysis/pitch_collection.rb', line 57

def pitches_above_bass_pitch
  @pitches_above_bass_pitch ||= pitches.drop(1)
end

#reductionObject



41
42
43
# File 'lib/head_music/analysis/pitch_collection.rb', line 41

def reduction
  @reduction ||= HeadMusic::Analysis::PitchCollection.new(reduction_pitches)
end

#reduction_pitchesObject (private)



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

def reduction_pitches
  pitches.map { |pitch| folded_into_reduction(pitch) }.sort
end

#scale_degreesObject



104
105
106
# File 'lib/head_music/analysis/pitch_collection.rb', line 104

def scale_degrees
  @scale_degrees ||= pitches.empty? ? [] : scale_degrees_above_bass_pitch.unshift(1)
end

#scale_degrees_above_bass_pitchObject



108
109
110
# File 'lib/head_music/analysis/pitch_collection.rb', line 108

def scale_degrees_above_bass_pitch
  @scale_degrees_above_bass_pitch ||= diatonic_intervals_above_bass_pitch.map(&:simple_number).sort - [8]
end

#sizeObject



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

def size
  pitches.length
end

#sonorityObject



112
113
114
# File 'lib/head_music/analysis/pitch_collection.rb', line 112

def sonority
  @sonority ||= HeadMusic::Analysis::Sonority.new(self)
end

#to_sObject



88
89
90
# File 'lib/head_music/analysis/pitch_collection.rb', line 88

def to_s
  pitches.join(" ")
end

#uninvertObject



74
75
76
77
78
# File 'lib/head_music/analysis/pitch_collection.rb', line 74

def uninvert
  inverted_pitch = pitches.last - octave
  new_pitches = [inverted_pitch] + pitches[0..-2]
  HeadMusic::Analysis::PitchCollection.new(new_pitches)
end