Class: HeadMusic::Style::Guidelines::SuspensionTreatment
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.
Instance Method Summary
collapse
Instance Method Details
#consonant_at?(position) ⇒ Boolean
64
65
66
67
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 64
def consonant_at?(position)
interval = harmonic_interval_at(position)
two_part?(interval) && interval.consonance?(:two_part_harmony)
end
|
#dissonant_at?(position) ⇒ Boolean
59
60
61
62
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 59
def dissonant_at?(position)
interval = harmonic_interval_at(position)
two_part?(interval) && interval.dissonance?(:two_part_harmony)
end
|
#dissonant_suspensions ⇒ Object
24
25
26
27
28
29
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 24
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
69
70
71
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 69
def harmonic_interval_at(position)
HeadMusic::Analysis::HarmonicInterval.new(cantus_firmus, voice, position)
end
|
#improperly_treated_suspensions ⇒ Object
20
21
22
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 20
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
15
16
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 10
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
42
43
44
45
46
47
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 42
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
77
78
79
80
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 77
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
38
39
40
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 38
def properly_treated?(cp_note, cf_note)
prepared?(cp_note, cf_note) && resolved?(cp_note, cf_note)
end
|
#resolved?(cp_note, _cf_note) ⇒ Boolean
49
50
51
52
53
54
55
56
57
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 49
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).
33
34
35
36
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 33
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
73
74
75
|
# File 'lib/head_music/style/guidelines/suspension_treatment.rb', line 73
def two_part?(interval)
interval.notes.length == 2
end
|