Class: HeadMusic::Style::Guidelines::SecondSpeciesBreak
Overview
A counterpoint guideline for fourth species counterpoint.
The syncopated texture is occasionally broken: the counterpoint moves on the
downbeat instead of sustaining. When this happens, a dissonant off-beat note
is permitted only if it is a passing tone. Breaks should be infrequent.
Constant Summary
collapse
- MESSAGE =
"Use only passing tones when breaking the syncopated texture. Breaks should be infrequent."
- MAX_BREAK_RATIO =
0.25
Instance Method Summary
collapse
Instance Method Details
#break_bar?(bar) ⇒ Boolean
44
45
46
47
|
# File 'lib/head_music/style/guidelines/second_species_break.rb', line 44
def break_bar?(bar)
downbeats, off_beats = notes_in_bar(bar).partition { |note| downbeat_position?(note.position) }
downbeats.any? && off_beats.any?
end
|
#break_bar_off_beat_notes ⇒ Object
49
50
51
|
# File 'lib/head_music/style/guidelines/second_species_break.rb', line 49
def break_bar_off_beat_notes
break_bars.flat_map { |bar| notes_in_bar(bar).reject { |note| downbeat_position?(note.position) } }
end
|
#break_bars ⇒ Object
40
41
42
|
# File 'lib/head_music/style/guidelines/second_species_break.rb', line 40
def break_bars
@break_bars ||= (first_bar..last_bar).select { |bar| break_bar?(bar) }
end
|
#dissonance_marks ⇒ Object
21
22
23
24
25
26
|
# File 'lib/head_music/style/guidelines/second_species_break.rb', line 21
def dissonance_marks
break_bar_off_beat_notes
.select { |note| dissonant_with_cantus?(note) }
.reject { |note| passing_tone?(note) }
.map { |note| HeadMusic::Style::Mark.for(note) }
end
|
#first_bar ⇒ Object
61
62
63
|
# File 'lib/head_music/style/guidelines/second_species_break.rb', line 61
def first_bar
cantus_firmus.notes.first.position.bar_number
end
|
#frequency_marks ⇒ Object
32
33
34
35
36
37
38
|
# File 'lib/head_music/style/guidelines/second_species_break.rb', line 32
def frequency_marks
return [] if total_bars <= 0
return [] if break_bars.length <= total_bars * max_break_ratio
break_bar_notes = break_bars.flat_map { |bar| notes_in_bar(bar) }
[HeadMusic::Style::Mark.for_all(break_bar_notes, fitness: HeadMusic::SMALL_PENALTY_FACTOR)]
end
|
#last_bar ⇒ Object
65
66
67
|
# File 'lib/head_music/style/guidelines/second_species_break.rb', line 65
def last_bar
cantus_firmus.notes.last.position.bar_number
end
|
#marks ⇒ Object
13
14
15
16
17
|
# File 'lib/head_music/style/guidelines/second_species_break.rb', line 13
def marks
return [] unless cantus_firmus&.notes&.any?
dissonance_marks + frequency_marks
end
|
#max_break_ratio ⇒ Object
28
29
30
|
# File 'lib/head_music/style/guidelines/second_species_break.rb', line 28
def max_break_ratio
options.fetch(:max_break_ratio) { self.class::MAX_BREAK_RATIO }
end
|
#notes_in_bar(bar) ⇒ Object
53
54
55
|
# File 'lib/head_music/style/guidelines/second_species_break.rb', line 53
def notes_in_bar(bar)
notes.select { |note| note.position.bar_number == bar }
end
|
#total_bars ⇒ Object
57
58
59
|
# File 'lib/head_music/style/guidelines/second_species_break.rb', line 57
def total_bars
last_bar - first_bar + 1
end
|