Class: HeadMusic::Style::Guidelines::SuspensionTreatment
- Inherits:
-
Annotation
- Object
- Annotation
- HeadMusic::Style::Guidelines::SuspensionTreatment
show all
- Defined in:
- lib/head_music/style/guidelines/suspension_treatment.rb
Overview
A counterpoint guideline for fourth species suspension treatment.
A suspension has three parts:
1. Preparation: The note is consonant with the current cantus firmus note.
2. Suspension: The cantus firmus moves; the counterpoint sustains, becoming dissonant.
3. Resolution: The counterpoint resolves by step down to a consonance.
Constant Summary
collapse
- MESSAGE =
"Treat suspensions with proper preparation and downward stepwise resolution."
Instance Method Summary
collapse
Instance Method Details
#consonant_at?(position) ⇒ Boolean
66
67
68
69
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 66
def consonant_at?(position)
interval = harmonic_interval_at(position)
two_part?(interval) && interval.consonance?(:two_part_harmony)
end
|
#dissonant_at?(position) ⇒ Boolean
61
62
63
64
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 61
def dissonant_at?(position)
interval = harmonic_interval_at(position)
two_part?(interval) && interval.dissonance?(:two_part_harmony)
end
|
#dissonant_suspensions ⇒ Object
26
27
28
29
30
31
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 26
def dissonant_suspensions
cantus_firmus.notes[1..].filter_map do |cf_note|
cp_note = suspended_cp_note(cf_note)
[cp_note, cf_note] if cp_note && dissonant_at?(cf_note.position)
end
end
|
#harmonic_interval_at(position) ⇒ Object
71
72
73
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 71
def harmonic_interval_at(position)
HeadMusic::Analysis::HarmonicInterval.new(cantus_firmus, voice, position)
end
|
#improperly_treated_suspensions ⇒ Object
22
23
24
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 22
def improperly_treated_suspensions
dissonant_suspensions.reject { |note, cf_note| properly_treated?(note, cf_note) }.map(&:first)
end
|
#marks ⇒ Object
12
13
14
15
16
17
18
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 12
def marks
return [] unless cantus_firmus&.notes&.any?
improperly_treated_suspensions.map do |note|
HeadMusic::Style::Mark.for(note)
end
end
|
#prepared?(cp_note, cf_note) ⇒ Boolean
44
45
46
47
48
49
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 44
def prepared?(cp_note, cf_note)
prev_cf = previous_cf_note(cf_note)
return false unless prev_cf
consonant_at?(cp_note.position)
end
|
#previous_cf_note(cf_note) ⇒ Object
79
80
81
82
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 79
def previous_cf_note(cf_note)
index = cantus_firmus.notes.index(cf_note)
cantus_firmus.notes[index - 1] if index && index > 0
end
|
#properly_treated?(cp_note, cf_note) ⇒ Boolean
40
41
42
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 40
def properly_treated?(cp_note, cf_note)
prepared?(cp_note, cf_note) && resolved?(cp_note, cf_note)
end
|
#resolved?(cp_note, _cf_note) ⇒ Boolean
51
52
53
54
55
56
57
58
59
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 51
def resolved?(cp_note, _cf_note)
next_cp = voice.note_following(cp_note.position)
return false unless next_cp
melodic = HeadMusic::Analysis::MelodicInterval.new(cp_note, next_cp)
return false unless melodic.step? && melodic.descending?
consonant_at?(next_cp.position)
end
|
#suspended_cp_note(cf_note) ⇒ Object
The counterpoint note sounding under the cantus firmus note, but only when it
began earlier (a note held over, i.e. a suspension).
35
36
37
38
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 35
def suspended_cp_note(cf_note)
cp_note = voice.note_at(cf_note.position)
cp_note if cp_note && cp_note.position < cf_note.position
end
|
#two_part?(interval) ⇒ Boolean
75
76
77
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 75
def two_part?(interval)
interval.notes.length == 2
end
|