Class: HeadMusic::Style::Guidelines::SuspensionTreatment
Overview
A counterpoint guideline for fourth species suspension treatment.
A suspension has three parts:
- Preparation: The note is consonant with the current cantus firmus note.
- Suspension: The cantus firmus moves; the counterpoint sustains, becoming dissonant.
- Resolution: The counterpoint resolves by step down to a consonance.
Instance Method Summary
collapse
Instance Method Details
#consonant_at?(position) ⇒ Boolean
62
63
64
65
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 62
def consonant_at?(position)
interval = harmonic_interval_at(position)
two_part?(interval) && interval.consonance?(:two_part_harmony)
end
|
#dissonant_at?(position) ⇒ Boolean
57
58
59
60
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 57
def dissonant_at?(position)
interval = harmonic_interval_at(position)
two_part?(interval) && interval.dissonance?(:two_part_harmony)
end
|
#dissonant_suspensions ⇒ Object
22
23
24
25
26
27
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 22
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
67
68
69
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 67
def harmonic_interval_at(position)
HeadMusic::Analysis::HarmonicInterval.new(cantus_firmus, voice, position)
end
|
#improperly_treated_suspensions ⇒ Object
18
19
20
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 18
def improperly_treated_suspensions
dissonant_suspensions.reject { |note, cf_note| properly_treated?(note, cf_note) }.map(&:first)
end
|
#marks ⇒ Object
10
11
12
13
14
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 10
def marks
return [] unless cantus_firmus&.notes&.any?
HeadMusic::Style::Mark.for_each(improperly_treated_suspensions)
end
|
#prepared?(cp_note, cf_note) ⇒ Boolean
40
41
42
43
44
45
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 40
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
75
76
77
78
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 75
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
36
37
38
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 36
def properly_treated?(cp_note, cf_note)
prepared?(cp_note, cf_note) && resolved?(cp_note, cf_note)
end
|
#resolved?(cp_note, _cf_note) ⇒ Boolean
47
48
49
50
51
52
53
54
55
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 47
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).
31
32
33
34
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 31
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
71
72
73
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 71
def two_part?(interval)
interval.notes.length == 2
end
|