Class: HeadMusic::Style::Annotation
- Inherits:
-
Object
- Object
- HeadMusic::Style::Annotation
show all
- Defined in:
- lib/head_music/style/annotation.rb
Overview
An Annotation encapsulates an issue with or comment on a voice
Direct Known Subclasses
Guidelines::AllowedRhythmicValuesForCombined123, Guidelines::AllowedRhythmicValuesForFifthSpecies, Guidelines::AlwaysMove, Guidelines::ApproachPerfectionContrarily, Guidelines::AvoidCrossingVoices, Guidelines::AvoidOverlappingVoices, Guidelines::ConsonantClimax, Guidelines::ConsonantDownbeats, Guidelines::Diatonic, Guidelines::DirectionChanges, Guidelines::DirectionalStepToFinalNote, Guidelines::EndOnPerfectConsonance, Guidelines::EndOnTonic, Guidelines::FirstBarEntry, Guidelines::FloridDissonanceTreatment, Guidelines::LimitOctaveLeaps, Guidelines::MaximumNotes, Guidelines::MinimumNotes, Guidelines::MixedRhythmicValues, Guidelines::MostlyConjunct, Guidelines::NoParallelPerfectAcrossBarline, Guidelines::NoParallelPerfectOnDownbeats, Guidelines::NoParallelPerfectWithSyncopation, Guidelines::NoRests, Guidelines::NoRestsAfterNote, Guidelines::NoStrongBeatUnisons, Guidelines::NoUnisonsInMiddle, Guidelines::NoteCountPerBar, Guidelines::NoteFillsFinalBar, Guidelines::NotesSameLength, Guidelines::OneToOne, Guidelines::OneToOneWithTies, Guidelines::PreferContraryMotion, Guidelines::PreferImperfect, Guidelines::PrepareOctaveLeaps, Guidelines::RecoverLargeLeaps, Guidelines::SingableIntervals, Guidelines::SingableRange, Guidelines::StartOnPerfectConsonance, Guidelines::StartOnTonic, Guidelines::StepOutOfUnison, Guidelines::StepToFinalNote, Guidelines::SuspensionTreatment, Guidelines::WeakBeatDissonanceTreatment
Defined Under Namespace
Classes: Configured
Constant Summary
collapse
- MESSAGE =
"Write music."
Instance Attribute Summary collapse
Class Method Summary
collapse
-
.with(**options) ⇒ Object
Wraps a guideline class with preset options so it can live in a RULESET and still be instantiated with just a voice, e.g.
Instance Method Summary
collapse
Constructor Details
#initialize(voice, **options) ⇒ Annotation
Returns a new instance of Annotation.
26
27
28
29
|
# File 'lib/head_music/style/annotation.rb', line 26
def initialize(voice, **options)
@voice = voice
@options = options
end
|
Instance Attribute Details
#options ⇒ Object
Returns the value of attribute options.
92
93
94
|
# File 'lib/head_music/style/annotation.rb', line 92
def options
@options
end
|
#voice ⇒ Object
Returns the value of attribute voice.
5
6
7
|
# File 'lib/head_music/style/annotation.rb', line 5
def voice
@voice
end
|
Class Method Details
.with(**options) ⇒ Object
Wraps a guideline class with preset options so it can live in a RULESET
and still be instantiated with just a voice, e.g. MinimumNotes.with(minimum: 5).
33
34
35
|
# File 'lib/head_music/style/annotation.rb', line 33
def self.with(**options)
Configured.new(self, options)
end
|
Instance Method Details
#adherent? ⇒ Boolean
62
63
64
|
# File 'lib/head_music/style/annotation.rb', line 62
def adherent?
fitness == 1
end
|
#bass_voice? ⇒ Boolean
120
121
122
|
# File 'lib/head_music/style/annotation.rb', line 120
def bass_voice?
lower_voices.empty?
end
|
#cantus_firmus ⇒ Object
102
103
104
|
# File 'lib/head_music/style/annotation.rb', line 102
def cantus_firmus
@cantus_firmus ||= other_voices.detect(&:cantus_firmus?) || other_voices.first
end
|
#diatonic_interval_from_tonic(note) ⇒ Object
#downbeat_harmonic_intervals ⇒ Object
134
135
136
137
138
139
|
# File 'lib/head_music/style/annotation.rb', line 134
def downbeat_harmonic_intervals
@downbeat_harmonic_intervals ||=
cantus_firmus.notes
.map { |note| HeadMusic::Analysis::HarmonicInterval.new(note.voice, voice, note.position) }
.reject { |interval| interval.notes.length < 2 }
end
|
#end_position ⇒ Object
74
75
76
|
# File 'lib/head_music/style/annotation.rb', line 74
def end_position
[marks].flatten.compact.map(&:end_position).max
end
|
#first_note ⇒ Object
82
83
84
|
# File 'lib/head_music/style/annotation.rb', line 82
def first_note
notes.first
end
|
#fitness ⇒ Object
58
59
60
|
# File 'lib/head_music/style/annotation.rb', line 58
def fitness
[marks].flatten.compact.map(&:fitness).reduce(1, :*)
end
|
#harmonic_intervals ⇒ Object
141
142
143
144
145
146
|
# File 'lib/head_music/style/annotation.rb', line 141
def harmonic_intervals
@harmonic_intervals ||=
positions
.map { |position| HeadMusic::Analysis::HarmonicInterval.new(cantus_firmus, voice, position) }
.reject { |harmonic_interval| harmonic_interval.notes.length < 2 }
end
|
#has_notes? ⇒ Boolean
66
67
68
|
# File 'lib/head_music/style/annotation.rb', line 66
def has_notes?
!!first_note
end
|
#higher_voices ⇒ Object
106
107
108
|
# File 'lib/head_music/style/annotation.rb', line 106
def higher_voices
@higher_voices ||= unsorted_higher_voices.sort_by(&:highest_pitch).reverse
end
|
#last_note ⇒ Object
86
87
88
|
# File 'lib/head_music/style/annotation.rb', line 86
def last_note
notes.last
end
|
#lower_voices ⇒ Object
110
111
112
|
# File 'lib/head_music/style/annotation.rb', line 110
def lower_voices
@lower_voices ||= unsorted_lower_voices.sort_by(&:lowest_pitch).reverse
end
|
#message ⇒ Object
78
79
80
|
# File 'lib/head_music/style/annotation.rb', line 78
def message
self.class::MESSAGE
end
|
#motions ⇒ Object
128
129
130
131
132
|
# File 'lib/head_music/style/annotation.rb', line 128
def motions
downbeat_harmonic_intervals.each_cons(2).map do |harmonic_interval_pair|
HeadMusic::Analysis::Motion.new(*harmonic_interval_pair)
end
end
|
#other_voices ⇒ Object
98
99
100
|
# File 'lib/head_music/style/annotation.rb', line 98
def other_voices
@other_voices ||= voices.reject { |part| part == voice }
end
|
#positions ⇒ Object
148
149
150
151
|
# File 'lib/head_music/style/annotation.rb', line 148
def positions
@positions ||=
voices.map(&:notes).flatten.map(&:position).sort.uniq(&:to_s)
end
|
#start_position ⇒ Object
70
71
72
|
# File 'lib/head_music/style/annotation.rb', line 70
def start_position
[marks].flatten.compact.map(&:start_position).min
end
|
#starts_on_tonic? ⇒ Boolean
124
125
126
|
# File 'lib/head_music/style/annotation.rb', line 124
def starts_on_tonic?
tonic_spelling == first_note.spelling
end
|
#tonic_pitch ⇒ Object
161
162
163
|
# File 'lib/head_music/style/annotation.rb', line 161
def tonic_pitch
@tonic_pitch ||= HeadMusic::Rudiment::Pitch.get(tonic_spelling)
end
|
#unsorted_higher_voices ⇒ Object
153
154
155
|
# File 'lib/head_music/style/annotation.rb', line 153
def unsorted_higher_voices
other_voices.select { |part| part.highest_pitch && highest_pitch && part.highest_pitch > highest_pitch }
end
|
#unsorted_lower_voices ⇒ Object
157
158
159
|
# File 'lib/head_music/style/annotation.rb', line 157
def unsorted_lower_voices
other_voices.select { |part| part.lowest_pitch && lowest_pitch && part.lowest_pitch < lowest_pitch }
end
|
#voices ⇒ Object
94
95
96
|
# File 'lib/head_music/style/annotation.rb', line 94
def voices
@voices ||= voice.composition.voices
end
|