Class: HeadMusic::Style::Annotation

Inherits:
Object
  • Object
show all
Defined in:
lib/head_music/style/annotation.rb

Overview

An Annotation encapsulates an issue with or comment on a voice

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

#voiceObject (readonly)

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

Returns:

  • (Boolean)


34
35
36
# File 'lib/head_music/style/annotation.rb', line 34

def adherent?
  fitness == 1
end

#bass_voice?Boolean (protected)

Returns:

  • (Boolean)


90
91
92
# File 'lib/head_music/style/annotation.rb', line 90

def bass_voice?
  lower_voices.empty?
end

#cantus_firmusObject (protected)



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 (protected)



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_intervalsObject (protected)



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_positionObject



46
47
48
# File 'lib/head_music/style/annotation.rb', line 46

def end_position
  [marks].flatten.compact.map(&:end_position).max
end

#first_noteObject



54
55
56
# File 'lib/head_music/style/annotation.rb', line 54

def first_note
  notes.first
end

#fitnessObject



30
31
32
# File 'lib/head_music/style/annotation.rb', line 30

def fitness
  [marks].flatten.compact.map(&:fitness).reduce(1, :*)
end

#harmonic_intervalsObject (protected)



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

Returns:

  • (Boolean)


38
39
40
# File 'lib/head_music/style/annotation.rb', line 38

def has_notes?
  !!first_note
end

#higher_voicesObject (protected)



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_noteObject



58
59
60
# File 'lib/head_music/style/annotation.rb', line 58

def last_note
  notes.last
end

#lower_voicesObject (protected)



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

#messageObject



50
51
52
# File 'lib/head_music/style/annotation.rb', line 50

def message
  self.class::MESSAGE
end

#motionsObject (protected)



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_voicesObject (protected)



68
69
70
# File 'lib/head_music/style/annotation.rb', line 68

def other_voices
  @other_voices ||= voices.reject { |part| part == voice }
end

#positionsObject (protected)



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_positionObject



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 (protected)

Returns:

  • (Boolean)


94
95
96
# File 'lib/head_music/style/annotation.rb', line 94

def starts_on_tonic?
  tonic_spelling == first_note.spelling
end

#tonic_pitchObject (protected)



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_voicesObject (protected)



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_voicesObject (protected)



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

#voicesObject (protected)



64
65
66
# File 'lib/head_music/style/annotation.rb', line 64

def voices
  @voices ||= voice.composition.voices
end