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::AlwaysMove, Guidelines::ApproachPerfectionContrarily, Guidelines::AtLeastEightNotes, Guidelines::AvoidCrossingVoices, Guidelines::AvoidOverlappingVoices, Guidelines::ConsonantClimax, Guidelines::ConsonantDownbeats, Guidelines::Diatonic, Guidelines::DirectionChanges, Guidelines::EndOnPerfectConsonance, Guidelines::EndOnTonic, Guidelines::LimitOctaveLeaps, Guidelines::MostlyConjunct, Guidelines::NoRests, Guidelines::NoUnisonsInMiddle, Guidelines::NotesSameLength, Guidelines::OneToOne, Guidelines::PreferContraryMotion, Guidelines::PreferImperfect, Guidelines::PrepareOctaveLeaps, Guidelines::RecoverLargeLeaps, Guidelines::SingableIntervals, Guidelines::SingableRange, Guidelines::StartOnPerfectConsonance, Guidelines::StartOnTonic, Guidelines::StepDownToFinalNote, Guidelines::StepOutOfUnison, Guidelines::StepToFinalNote, Guidelines::StepUpToFinalNote, Guidelines::UpToFourteenNotes
Constant Summary
collapse
- MESSAGE =
"Write music."
Instance Attribute Summary collapse
Instance Method Summary
collapse
Constructor Details
#initialize(voice) ⇒ Annotation
Returns a new instance of Annotation.
26
27
28
|
# File 'lib/head_music/style/annotation.rb', line 26
def initialize(voice)
@voice = voice
end
|
Instance Attribute Details
#voice ⇒ Object
Returns the value of attribute voice.
5
6
7
|
# File 'lib/head_music/style/annotation.rb', line 5
def voice
@voice
end
|
Instance Method Details
#adherent? ⇒ Boolean
34
35
36
|
# File 'lib/head_music/style/annotation.rb', line 34
def adherent?
fitness == 1
end
|
#bass_voice? ⇒ Boolean
90
91
92
|
# File 'lib/head_music/style/annotation.rb', line 90
def bass_voice?
lower_voices.empty?
end
|
#cantus_firmus ⇒ Object
72
73
74
|
# File 'lib/head_music/style/annotation.rb', line 72
def cantus_firmus
@cantus_firmus ||= other_voices.detect(&:cantus_firmus?) || other_voices.first
end
|
#diatonic_interval_from_tonic(note) ⇒ Object
84
85
86
87
88
|
# File 'lib/head_music/style/annotation.rb', line 84
def diatonic_interval_from_tonic(note)
tonic_to_use = tonic_pitch
tonic_to_use -= HeadMusic::Rudiment::ChromaticInterval.get(:perfect_octave) while tonic_to_use > note.pitch
HeadMusic::Analysis::DiatonicInterval.new(tonic_to_use, note.pitch)
end
|
#downbeat_harmonic_intervals ⇒ Object
104
105
106
107
108
109
|
# File 'lib/head_music/style/annotation.rb', line 104
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
46
47
48
|
# File 'lib/head_music/style/annotation.rb', line 46
def end_position
[marks].flatten.compact.map(&:end_position).max
end
|
#first_note ⇒ Object
54
55
56
|
# File 'lib/head_music/style/annotation.rb', line 54
def first_note
notes.first
end
|
#fitness ⇒ Object
30
31
32
|
# File 'lib/head_music/style/annotation.rb', line 30
def fitness
[marks].flatten.compact.map(&:fitness).reduce(1, :*)
end
|
#harmonic_intervals ⇒ Object
111
112
113
114
115
116
|
# File 'lib/head_music/style/annotation.rb', line 111
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
38
39
40
|
# File 'lib/head_music/style/annotation.rb', line 38
def has_notes?
!!first_note
end
|
#higher_voices ⇒ Object
76
77
78
|
# File 'lib/head_music/style/annotation.rb', line 76
def higher_voices
@higher_voices ||= unsorted_higher_voices.sort_by(&:highest_pitch).reverse
end
|
#last_note ⇒ Object
58
59
60
|
# File 'lib/head_music/style/annotation.rb', line 58
def last_note
notes.last
end
|
#lower_voices ⇒ Object
80
81
82
|
# File 'lib/head_music/style/annotation.rb', line 80
def lower_voices
@lower_voices ||= unsorted_lower_voices.sort_by(&:lowest_pitch).reverse
end
|
#message ⇒ Object
50
51
52
|
# File 'lib/head_music/style/annotation.rb', line 50
def message
self.class::MESSAGE
end
|
#motions ⇒ Object
98
99
100
101
102
|
# File 'lib/head_music/style/annotation.rb', line 98
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
68
69
70
|
# File 'lib/head_music/style/annotation.rb', line 68
def other_voices
@other_voices ||= voices.reject { |part| part == voice }
end
|
#positions ⇒ Object
118
119
120
121
|
# File 'lib/head_music/style/annotation.rb', line 118
def positions
@positions ||=
voices.map(&:notes).flatten.map(&:position).sort.uniq(&:to_s)
end
|
#start_position ⇒ Object
42
43
44
|
# File 'lib/head_music/style/annotation.rb', line 42
def start_position
[marks].flatten.compact.map(&:start_position).min
end
|
#starts_on_tonic? ⇒ Boolean
94
95
96
|
# File 'lib/head_music/style/annotation.rb', line 94
def starts_on_tonic?
tonic_spelling == first_note.spelling
end
|
#tonic_pitch ⇒ Object
131
132
133
|
# File 'lib/head_music/style/annotation.rb', line 131
def tonic_pitch
@tonic_pitch ||= HeadMusic::Rudiment::Pitch.get(tonic_spelling)
end
|
#unsorted_higher_voices ⇒ Object
123
124
125
|
# File 'lib/head_music/style/annotation.rb', line 123
def unsorted_higher_voices
other_voices.select { |part| part.highest_pitch && highest_pitch && part.highest_pitch > highest_pitch }
end
|
#unsorted_lower_voices ⇒ Object
127
128
129
|
# File 'lib/head_music/style/annotation.rb', line 127
def unsorted_lower_voices
other_voices.select { |part| part.lowest_pitch && lowest_pitch && part.lowest_pitch < lowest_pitch }
end
|
#voices ⇒ Object
64
65
66
|
# File 'lib/head_music/style/annotation.rb', line 64
def voices
@voices ||= voice.composition.voices
end
|