Class: HeadMusic::Style::Guidelines::AllowedRhythmicValuesForFifthSpecies
- Inherits:
-
Annotation
- Object
- Annotation
- HeadMusic::Style::Guidelines::AllowedRhythmicValuesForFifthSpecies
show all
- Defined in:
- lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb
Overview
Validates that counterpoint notes use only permitted rhythmic values for fifth species.
Whole notes (final bar only), half notes, quarter notes, and paired stepwise eighth notes
on weak beats are allowed. No dotted rhythms.
Constant Summary
collapse
- MESSAGE =
"Use only permitted rhythmic values: whole (final bar only), half, quarter, " \
"or paired stepwise eighth notes on weak beats."
- PERMITTED_UNIT_NAMES =
%w[whole half quarter eighth].freeze
Instance Method Summary
collapse
Instance Method Details
#bars_with_excess_eighth_pairs ⇒ Object
83
84
85
86
87
88
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 83
def bars_with_excess_eighth_pairs
eighth_notes
.group_by { |note| note.position.bar_number }
.select { |_bar, bar_eighths| bar_eighths.length > 2 }
.keys
end
|
#disallowed_unit_marks ⇒ Object
26
27
28
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 26
def disallowed_unit_marks
mark_each(notes.reject { |note| PERMITTED_UNIT_NAMES.include?(note.rhythmic_value.unit_name) })
end
|
#dotted_rhythm_marks ⇒ Object
30
31
32
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 30
def dotted_rhythm_marks
mark_each(notes.select { |note| note.rhythmic_value.dots > 0 })
end
|
#eighth_notes ⇒ Object
64
65
66
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 64
def eighth_notes
@eighth_notes ||= notes.select { |note| note.rhythmic_value.unit_name == "eighth" }
end
|
#eighth_notes_in_bar(bar_number) ⇒ Object
90
91
92
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 90
def eighth_notes_in_bar(bar_number)
eighth_notes.select { |note| note.position.bar_number == bar_number }
end
|
#excess_eighth_note_pair_marks ⇒ Object
54
55
56
57
58
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 54
def excess_eighth_note_pair_marks
bars_with_excess_eighth_pairs.flat_map do |bar_number|
mark_each(eighth_notes_in_bar(bar_number)[2..])
end
end
|
#final_bar_number ⇒ Object
94
95
96
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 94
def final_bar_number
last_note&.position&.bar_number
end
|
#following_note(note) ⇒ Object
103
104
105
106
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 103
def following_note(note)
index = notes.index(note)
notes[index + 1] if index && index < notes.length - 1
end
|
#mark_each(violating_notes) ⇒ Object
60
61
62
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 60
def mark_each(violating_notes)
violating_notes.map { |note| HeadMusic::Style::Mark.for(note) }
end
|
#marks ⇒ Object
13
14
15
16
17
18
19
20
21
22
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 13
def marks
[
*disallowed_unit_marks,
*dotted_rhythm_marks,
*whole_note_not_in_final_bar_marks,
*unpaired_eighth_note_marks,
*non_stepwise_eighth_note_marks,
*excess_eighth_note_pair_marks
]
end
|
#non_stepwise_eighth_note_marks ⇒ Object
46
47
48
49
50
51
52
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 46
def non_stepwise_eighth_note_marks
mark_each(
eighth_notes
.select { |note| paired_eighth?(note) }
.reject { |note| stepwise_eighth?(note) }
)
end
|
#paired_eighth?(note) ⇒ Boolean
68
69
70
71
72
73
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 68
def paired_eighth?(note)
prev = preceding_note(note)
foll = following_note(note)
(prev && prev.rhythmic_value.unit_name == "eighth") ||
(foll && foll.rhythmic_value.unit_name == "eighth")
end
|
#preceding_note(note) ⇒ Object
98
99
100
101
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 98
def preceding_note(note)
index = notes.index(note)
notes[index - 1] if index && index > 0
end
|
#stepwise_eighth?(note) ⇒ Boolean
75
76
77
78
79
80
81
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 75
def stepwise_eighth?(note)
prev = preceding_note(note)
foll = following_note(note)
stepwise_from_prev = prev && HeadMusic::Analysis::MelodicInterval.new(prev, note).step?
stepwise_to_foll = foll && HeadMusic::Analysis::MelodicInterval.new(note, foll).step?
stepwise_from_prev || stepwise_to_foll
end
|
#unpaired_eighth_note_marks ⇒ Object
42
43
44
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 42
def unpaired_eighth_note_marks
mark_each(eighth_notes.reject { |note| paired_eighth?(note) })
end
|
#whole_note_not_in_final_bar_marks ⇒ Object
34
35
36
37
38
39
40
|
# File 'lib/head_music/style/guidelines/allowed_rhythmic_values_for_fifth_species.rb', line 34
def whole_note_not_in_final_bar_marks
mark_each(
notes
.select { |note| note.rhythmic_value.unit_name == "whole" }
.reject { |note| note.position.bar_number == final_bar_number }
)
end
|