head_music 12.0.1 → 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/head_music/style/guidelines/first_bar_entry.rb +48 -0
- data/lib/head_music/style/guidelines/first_bar_half_notes.rb +13 -0
- data/lib/head_music/style/guidelines/first_bar_quarter_notes.rb +13 -0
- data/lib/head_music/style/guidelines/first_bar_whole_note.rb +13 -0
- data/lib/head_music/style/guidelines/four_per_bar.rb +18 -0
- data/lib/head_music/style/guidelines/note_count_per_bar.rb +6 -26
- data/lib/head_music/style/guidelines/note_fills_final_bar.rb +35 -0
- data/lib/head_music/style/guidelines/one_per_bar.rb +18 -0
- data/lib/head_music/style/guidelines/three_per_bar.rb +18 -0
- data/lib/head_music/style/guidelines/two_per_bar.rb +18 -0
- data/lib/head_music/style/guides/first_species_melody.rb +3 -2
- data/lib/head_music/style/guides/second_species_melody.rb +3 -1
- data/lib/head_music/style/guides/third_species_melody.rb +3 -1
- data/lib/head_music/style/guides/third_species_triple_meter_melody.rb +3 -1
- data/lib/head_music/version.rb +1 -1
- data/lib/head_music.rb +9 -3
- metadata +11 -5
- data/lib/head_music/style/guidelines/four_to_one.rb +0 -45
- data/lib/head_music/style/guidelines/three_to_one.rb +0 -57
- data/lib/head_music/style/guidelines/two_to_one.rb +0 -46
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c8f4f677c163723dfa35c168e4094f6dfb883b2817808e0f15fcef4753a2d003
|
|
4
|
+
data.tar.gz: a9f85adca12a56dbba4f28da4cb44790a793ec9e27de78c3c63900f9b461bac3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2ac3464d2b14802c85b7779a11cbd95d8b849ea03b4992501eab1c40b2406e9411c1667de276ae1e95bb996b60f2d0a4e9d3f3b04973b539ba6df4c2462a302e
|
|
7
|
+
data.tar.gz: 3b6afff57cdcd7fcd343d5da25aad78fa7cbb0a05a74f86197e80b41dee8cf7585170af37ec71aa2da4dfa3ade9e3bcc708e6e6a4d3565507be9ea62d9e9ee79
|
data/Gemfile.lock
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Module for style guidelines.
|
|
2
|
+
module HeadMusic::Style::Guidelines; end
|
|
3
|
+
|
|
4
|
+
# Base class for first-bar guidelines.
|
|
5
|
+
# Rules: (a) at least one note, (b) each note is the correct beat unit,
|
|
6
|
+
# (c) at most one rest, and only on the first beat.
|
|
7
|
+
class HeadMusic::Style::Guidelines::FirstBarEntry < HeadMusic::Style::Annotation
|
|
8
|
+
def marks
|
|
9
|
+
return unless notes.any?
|
|
10
|
+
|
|
11
|
+
bar_notes = notes_in_first_bar
|
|
12
|
+
bar_rests = rests_in_first_bar
|
|
13
|
+
return if valid_first_bar?(bar_notes, bar_rests)
|
|
14
|
+
|
|
15
|
+
HeadMusic::Style::Mark.for_all(bar_notes.any? ? bar_notes : [first_note])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def expected_rhythmic_value
|
|
21
|
+
raise NotImplementedError
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def valid_first_bar?(bar_notes, bar_rests)
|
|
25
|
+
bar_notes.any? &&
|
|
26
|
+
all_correct_beat_unit?(bar_notes) &&
|
|
27
|
+
valid_rests?(bar_rests)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def all_correct_beat_unit?(bar_notes)
|
|
31
|
+
bar_notes.all? { |note| note.rhythmic_value == expected_rhythmic_value }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def valid_rests?(bar_rests)
|
|
35
|
+
bar_rests.empty? ||
|
|
36
|
+
(bar_rests.length == 1 &&
|
|
37
|
+
bar_rests.first.position.count == 1 &&
|
|
38
|
+
bar_rests.first.rhythmic_value == expected_rhythmic_value)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def notes_in_first_bar
|
|
42
|
+
notes.select { |note| note.position.bar_number == 1 }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def rests_in_first_bar
|
|
46
|
+
rests.select { |rest| rest.position.bar_number == 1 }
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Module for style guidelines.
|
|
2
|
+
module HeadMusic::Style::Guidelines; end
|
|
3
|
+
|
|
4
|
+
# Checks that the first bar contains half notes, with an optional half rest on beat one.
|
|
5
|
+
class HeadMusic::Style::Guidelines::FirstBarHalfNotes < HeadMusic::Style::Guidelines::FirstBarEntry
|
|
6
|
+
MESSAGE = "Begin the first bar with half notes, or enter after a half rest."
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def expected_rhythmic_value
|
|
11
|
+
HeadMusic::Rudiment::RhythmicValue.get(:half)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Module for style guidelines.
|
|
2
|
+
module HeadMusic::Style::Guidelines; end
|
|
3
|
+
|
|
4
|
+
# Checks that the first bar contains quarter notes, with an optional quarter rest on beat one.
|
|
5
|
+
class HeadMusic::Style::Guidelines::FirstBarQuarterNotes < HeadMusic::Style::Guidelines::FirstBarEntry
|
|
6
|
+
MESSAGE = "Begin the first bar with quarter notes, or enter after a quarter rest."
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def expected_rhythmic_value
|
|
11
|
+
HeadMusic::Rudiment::RhythmicValue.get(:quarter)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Module for style guidelines.
|
|
2
|
+
module HeadMusic::Style::Guidelines; end
|
|
3
|
+
|
|
4
|
+
# Checks that the first bar contains a whole note.
|
|
5
|
+
class HeadMusic::Style::Guidelines::FirstBarWholeNote < HeadMusic::Style::Guidelines::FirstBarEntry
|
|
6
|
+
MESSAGE = "Begin with a whole note in the first bar."
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def expected_rhythmic_value
|
|
11
|
+
HeadMusic::Rudiment::RhythmicValue.get(:whole)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Module for style guidelines.
|
|
2
|
+
module HeadMusic::Style::Guidelines; end
|
|
3
|
+
|
|
4
|
+
# Checks that each middle bar contains exactly four quarter notes.
|
|
5
|
+
class HeadMusic::Style::Guidelines::FourPerBar < HeadMusic::Style::Guidelines::NoteCountPerBar
|
|
6
|
+
MESSAGE = "Use four quarter notes in each middle bar."
|
|
7
|
+
|
|
8
|
+
QUARTER = HeadMusic::Rudiment::RhythmicValue.get(:quarter)
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def check_middle_bar(bar_number)
|
|
13
|
+
bar_notes = notes_in_bar(bar_number)
|
|
14
|
+
return if bar_notes.length == 4 && bar_notes.all? { |note| note.rhythmic_value == QUARTER }
|
|
15
|
+
|
|
16
|
+
mark_bar(bar_number)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,47 +1,27 @@
|
|
|
1
1
|
# Module for style guidelines.
|
|
2
2
|
module HeadMusic::Style::Guidelines; end
|
|
3
3
|
|
|
4
|
-
# Base class for guidelines that check note counts
|
|
4
|
+
# Base class for guidelines that check note counts in middle bars (not first or last).
|
|
5
5
|
class HeadMusic::Style::Guidelines::NoteCountPerBar < HeadMusic::Style::Annotation
|
|
6
|
-
WHOLE = HeadMusic::Rudiment::RhythmicValue.get(:whole)
|
|
7
|
-
|
|
8
6
|
def marks
|
|
9
7
|
return [] unless cantus_firmus&.notes&.any?
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
cf_notes.each_with_index.filter_map do |cf_note, index|
|
|
13
|
-
bar_number = cf_note.position.bar_number
|
|
14
|
-
if index == cf_notes.length - 1
|
|
15
|
-
check_final_bar(bar_number)
|
|
16
|
-
elsif index == 0
|
|
17
|
-
check_first_bar(bar_number)
|
|
18
|
-
else
|
|
19
|
-
check_middle_bar(bar_number)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
9
|
+
middle_bars.filter_map { |bar_number| check_middle_bar(bar_number) }
|
|
22
10
|
end
|
|
23
11
|
|
|
24
12
|
private
|
|
25
13
|
|
|
26
|
-
def
|
|
27
|
-
|
|
28
|
-
return if
|
|
29
|
-
|
|
30
|
-
mark_bar(bar_number)
|
|
31
|
-
end
|
|
14
|
+
def middle_bars
|
|
15
|
+
cf_notes = cantus_firmus.notes
|
|
16
|
+
return [] if cf_notes.length <= 2
|
|
32
17
|
|
|
33
|
-
|
|
34
|
-
bar_notes.length == 1 && bar_notes.first.rhythmic_value == WHOLE
|
|
18
|
+
cf_notes[1..-2].map { |note| note.position.bar_number }
|
|
35
19
|
end
|
|
36
20
|
|
|
37
21
|
def notes_in_bar(bar_number)
|
|
38
22
|
notes.select { |note| note.position.bar_number == bar_number }
|
|
39
23
|
end
|
|
40
24
|
|
|
41
|
-
def rests_in_bar(bar_number)
|
|
42
|
-
rests.select { |rest| rest.position.bar_number == bar_number }
|
|
43
|
-
end
|
|
44
|
-
|
|
45
25
|
def mark_bar(bar_number)
|
|
46
26
|
bar_placements = notes_in_bar(bar_number)
|
|
47
27
|
if bar_placements.any?
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Module for style guidelines.
|
|
2
|
+
module HeadMusic::Style::Guidelines; end
|
|
3
|
+
|
|
4
|
+
# Checks that the final bar contains a single note that fills the entire measure.
|
|
5
|
+
class HeadMusic::Style::Guidelines::NoteFillsFinalBar < HeadMusic::Style::Annotation
|
|
6
|
+
MESSAGE = "End with a single note that fills the final bar."
|
|
7
|
+
|
|
8
|
+
def marks
|
|
9
|
+
return unless notes.any?
|
|
10
|
+
|
|
11
|
+
bar_notes = notes_in_final_bar
|
|
12
|
+
return if bar_notes.length == 1 && fills_bar?(bar_notes.first)
|
|
13
|
+
|
|
14
|
+
HeadMusic::Style::Mark.for_all(bar_notes.any? ? bar_notes : [last_note])
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def notes_in_final_bar
|
|
20
|
+
notes.select { |note| note.position.bar_number == final_bar_number }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def final_bar_number
|
|
24
|
+
last_note.position.bar_number
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def fills_bar?(note)
|
|
28
|
+
note.rhythmic_value.total_value == bar_duration
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def bar_duration
|
|
32
|
+
meter = composition.meter_at(final_bar_number)
|
|
33
|
+
meter.count_unit.relative_value * meter.counts_per_bar
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Module for style guidelines.
|
|
2
|
+
module HeadMusic::Style::Guidelines; end
|
|
3
|
+
|
|
4
|
+
# Checks that each middle bar contains exactly one whole note.
|
|
5
|
+
class HeadMusic::Style::Guidelines::OnePerBar < HeadMusic::Style::Guidelines::NoteCountPerBar
|
|
6
|
+
MESSAGE = "Use one whole note in each middle bar."
|
|
7
|
+
|
|
8
|
+
WHOLE = HeadMusic::Rudiment::RhythmicValue.get(:whole)
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def check_middle_bar(bar_number)
|
|
13
|
+
bar_notes = notes_in_bar(bar_number)
|
|
14
|
+
return if bar_notes.length == 1 && bar_notes.first.rhythmic_value == WHOLE
|
|
15
|
+
|
|
16
|
+
mark_bar(bar_number)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Module for style guidelines.
|
|
2
|
+
module HeadMusic::Style::Guidelines; end
|
|
3
|
+
|
|
4
|
+
# Checks that each middle bar contains exactly three quarter notes.
|
|
5
|
+
class HeadMusic::Style::Guidelines::ThreePerBar < HeadMusic::Style::Guidelines::NoteCountPerBar
|
|
6
|
+
MESSAGE = "Use three quarter notes in each middle bar."
|
|
7
|
+
|
|
8
|
+
QUARTER = HeadMusic::Rudiment::RhythmicValue.get(:quarter)
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def check_middle_bar(bar_number)
|
|
13
|
+
bar_notes = notes_in_bar(bar_number)
|
|
14
|
+
return if bar_notes.length == 3 && bar_notes.all? { |note| note.rhythmic_value == QUARTER }
|
|
15
|
+
|
|
16
|
+
mark_bar(bar_number)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Module for style guidelines.
|
|
2
|
+
module HeadMusic::Style::Guidelines; end
|
|
3
|
+
|
|
4
|
+
# Checks that each middle bar contains exactly two half notes.
|
|
5
|
+
class HeadMusic::Style::Guidelines::TwoPerBar < HeadMusic::Style::Guidelines::NoteCountPerBar
|
|
6
|
+
MESSAGE = "Use two half notes in each middle bar."
|
|
7
|
+
|
|
8
|
+
HALF = HeadMusic::Rudiment::RhythmicValue.get(:half)
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def check_middle_bar(bar_number)
|
|
13
|
+
bar_notes = notes_in_bar(bar_number)
|
|
14
|
+
return if bar_notes.length == 2 && bar_notes.all? { |note| note.rhythmic_value == HALF }
|
|
15
|
+
|
|
16
|
+
mark_bar(bar_number)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -7,11 +7,12 @@ class HeadMusic::Style::Guides::FirstSpeciesMelody < HeadMusic::Style::Guides::S
|
|
|
7
7
|
HeadMusic::Style::Guidelines::ConsonantClimax,
|
|
8
8
|
HeadMusic::Style::Guidelines::Diatonic,
|
|
9
9
|
HeadMusic::Style::Guidelines::EndOnTonic,
|
|
10
|
+
HeadMusic::Style::Guidelines::NoteFillsFinalBar,
|
|
11
|
+
HeadMusic::Style::Guidelines::FirstBarWholeNote,
|
|
10
12
|
HeadMusic::Style::Guidelines::FrequentDirectionChanges,
|
|
11
13
|
HeadMusic::Style::Guidelines::LimitOctaveLeaps,
|
|
12
14
|
HeadMusic::Style::Guidelines::MostlyConjunct,
|
|
13
|
-
HeadMusic::Style::Guidelines::
|
|
14
|
-
HeadMusic::Style::Guidelines::NotesSameLength,
|
|
15
|
+
HeadMusic::Style::Guidelines::OnePerBar,
|
|
15
16
|
HeadMusic::Style::Guidelines::PrepareOctaveLeaps,
|
|
16
17
|
HeadMusic::Style::Guidelines::SingableIntervals,
|
|
17
18
|
HeadMusic::Style::Guidelines::SingableRange,
|
|
@@ -8,6 +8,8 @@ class HeadMusic::Style::Guides::SecondSpeciesMelody < HeadMusic::Style::Guides::
|
|
|
8
8
|
HeadMusic::Style::Guidelines::ConsonantClimax,
|
|
9
9
|
HeadMusic::Style::Guidelines::Diatonic,
|
|
10
10
|
HeadMusic::Style::Guidelines::EndOnTonic,
|
|
11
|
+
HeadMusic::Style::Guidelines::NoteFillsFinalBar,
|
|
12
|
+
HeadMusic::Style::Guidelines::FirstBarHalfNotes,
|
|
11
13
|
HeadMusic::Style::Guidelines::FrequentDirectionChanges,
|
|
12
14
|
HeadMusic::Style::Guidelines::LimitOctaveLeaps,
|
|
13
15
|
HeadMusic::Style::Guidelines::MostlyConjunct,
|
|
@@ -17,6 +19,6 @@ class HeadMusic::Style::Guides::SecondSpeciesMelody < HeadMusic::Style::Guides::
|
|
|
17
19
|
HeadMusic::Style::Guidelines::StartOnPerfectConsonance,
|
|
18
20
|
HeadMusic::Style::Guidelines::StepOutOfUnison,
|
|
19
21
|
HeadMusic::Style::Guidelines::StepUpToFinalNote,
|
|
20
|
-
HeadMusic::Style::Guidelines::
|
|
22
|
+
HeadMusic::Style::Guidelines::TwoPerBar
|
|
21
23
|
].freeze
|
|
22
24
|
end
|
|
@@ -8,7 +8,9 @@ class HeadMusic::Style::Guides::ThirdSpeciesMelody < HeadMusic::Style::Guides::S
|
|
|
8
8
|
HeadMusic::Style::Guidelines::ConsonantClimax,
|
|
9
9
|
HeadMusic::Style::Guidelines::Diatonic,
|
|
10
10
|
HeadMusic::Style::Guidelines::EndOnTonic,
|
|
11
|
-
HeadMusic::Style::Guidelines::
|
|
11
|
+
HeadMusic::Style::Guidelines::NoteFillsFinalBar,
|
|
12
|
+
HeadMusic::Style::Guidelines::FirstBarQuarterNotes,
|
|
13
|
+
HeadMusic::Style::Guidelines::FourPerBar,
|
|
12
14
|
HeadMusic::Style::Guidelines::FrequentDirectionChanges,
|
|
13
15
|
HeadMusic::Style::Guidelines::LimitOctaveLeaps,
|
|
14
16
|
HeadMusic::Style::Guidelines::MostlyConjunct,
|
|
@@ -8,6 +8,8 @@ class HeadMusic::Style::Guides::ThirdSpeciesTripleMeterMelody < HeadMusic::Style
|
|
|
8
8
|
HeadMusic::Style::Guidelines::ConsonantClimax,
|
|
9
9
|
HeadMusic::Style::Guidelines::Diatonic,
|
|
10
10
|
HeadMusic::Style::Guidelines::EndOnTonic,
|
|
11
|
+
HeadMusic::Style::Guidelines::NoteFillsFinalBar,
|
|
12
|
+
HeadMusic::Style::Guidelines::FirstBarQuarterNotes,
|
|
11
13
|
HeadMusic::Style::Guidelines::FrequentDirectionChanges,
|
|
12
14
|
HeadMusic::Style::Guidelines::LimitOctaveLeaps,
|
|
13
15
|
HeadMusic::Style::Guidelines::MostlyConjunct,
|
|
@@ -17,6 +19,6 @@ class HeadMusic::Style::Guides::ThirdSpeciesTripleMeterMelody < HeadMusic::Style
|
|
|
17
19
|
HeadMusic::Style::Guidelines::StartOnPerfectConsonance,
|
|
18
20
|
HeadMusic::Style::Guidelines::StepOutOfUnison,
|
|
19
21
|
HeadMusic::Style::Guidelines::StepUpToFinalNote,
|
|
20
|
-
HeadMusic::Style::Guidelines::
|
|
22
|
+
HeadMusic::Style::Guidelines::ThreePerBar
|
|
21
23
|
].freeze
|
|
22
24
|
end
|
data/lib/head_music/version.rb
CHANGED
data/lib/head_music.rb
CHANGED
|
@@ -161,8 +161,14 @@ require "head_music/style/guidelines/diatonic"
|
|
|
161
161
|
require "head_music/style/guidelines/direction_changes"
|
|
162
162
|
require "head_music/style/guidelines/end_on_perfect_consonance"
|
|
163
163
|
require "head_music/style/guidelines/end_on_tonic"
|
|
164
|
+
require "head_music/style/guidelines/note_fills_final_bar"
|
|
165
|
+
require "head_music/style/guidelines/first_bar_entry"
|
|
166
|
+
require "head_music/style/guidelines/first_bar_half_notes"
|
|
167
|
+
require "head_music/style/guidelines/first_bar_quarter_notes"
|
|
168
|
+
require "head_music/style/guidelines/first_bar_whole_note"
|
|
164
169
|
require "head_music/style/guidelines/note_count_per_bar"
|
|
165
|
-
require "head_music/style/guidelines/
|
|
170
|
+
require "head_music/style/guidelines/one_per_bar"
|
|
171
|
+
require "head_music/style/guidelines/four_per_bar"
|
|
166
172
|
require "head_music/style/guidelines/frequent_direction_changes"
|
|
167
173
|
require "head_music/style/guidelines/limit_octave_leaps"
|
|
168
174
|
require "head_music/style/guidelines/moderate_direction_changes"
|
|
@@ -188,8 +194,8 @@ require "head_music/style/guidelines/step_down_to_final_note"
|
|
|
188
194
|
require "head_music/style/guidelines/step_out_of_unison"
|
|
189
195
|
require "head_music/style/guidelines/step_to_final_note"
|
|
190
196
|
require "head_music/style/guidelines/step_up_to_final_note"
|
|
191
|
-
require "head_music/style/guidelines/
|
|
192
|
-
require "head_music/style/guidelines/
|
|
197
|
+
require "head_music/style/guidelines/three_per_bar"
|
|
198
|
+
require "head_music/style/guidelines/two_per_bar"
|
|
193
199
|
require "head_music/style/guidelines/up_to_fourteen_notes"
|
|
194
200
|
require "head_music/style/guidelines/weak_beat_dissonance_treatment"
|
|
195
201
|
require "head_music/style/guidelines/third_species_dissonance_treatment"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: head_music
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 12.0
|
|
4
|
+
version: 12.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rob Head
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -280,7 +280,11 @@ files:
|
|
|
280
280
|
- lib/head_music/style/guidelines/directional_step_to_final_note.rb
|
|
281
281
|
- lib/head_music/style/guidelines/end_on_perfect_consonance.rb
|
|
282
282
|
- lib/head_music/style/guidelines/end_on_tonic.rb
|
|
283
|
-
- lib/head_music/style/guidelines/
|
|
283
|
+
- lib/head_music/style/guidelines/first_bar_entry.rb
|
|
284
|
+
- lib/head_music/style/guidelines/first_bar_half_notes.rb
|
|
285
|
+
- lib/head_music/style/guidelines/first_bar_quarter_notes.rb
|
|
286
|
+
- lib/head_music/style/guidelines/first_bar_whole_note.rb
|
|
287
|
+
- lib/head_music/style/guidelines/four_per_bar.rb
|
|
284
288
|
- lib/head_music/style/guidelines/frequent_direction_changes.rb
|
|
285
289
|
- lib/head_music/style/guidelines/limit_octave_leaps.rb
|
|
286
290
|
- lib/head_music/style/guidelines/moderate_direction_changes.rb
|
|
@@ -291,7 +295,9 @@ files:
|
|
|
291
295
|
- lib/head_music/style/guidelines/no_strong_beat_unisons.rb
|
|
292
296
|
- lib/head_music/style/guidelines/no_unisons_in_middle.rb
|
|
293
297
|
- lib/head_music/style/guidelines/note_count_per_bar.rb
|
|
298
|
+
- lib/head_music/style/guidelines/note_fills_final_bar.rb
|
|
294
299
|
- lib/head_music/style/guidelines/notes_same_length.rb
|
|
300
|
+
- lib/head_music/style/guidelines/one_per_bar.rb
|
|
295
301
|
- lib/head_music/style/guidelines/one_to_one.rb
|
|
296
302
|
- lib/head_music/style/guidelines/prefer_contrary_motion.rb
|
|
297
303
|
- lib/head_music/style/guidelines/prefer_imperfect.rb
|
|
@@ -307,9 +313,9 @@ files:
|
|
|
307
313
|
- lib/head_music/style/guidelines/step_to_final_note.rb
|
|
308
314
|
- lib/head_music/style/guidelines/step_up_to_final_note.rb
|
|
309
315
|
- lib/head_music/style/guidelines/third_species_dissonance_treatment.rb
|
|
310
|
-
- lib/head_music/style/guidelines/
|
|
316
|
+
- lib/head_music/style/guidelines/three_per_bar.rb
|
|
311
317
|
- lib/head_music/style/guidelines/triple_meter_dissonance_treatment.rb
|
|
312
|
-
- lib/head_music/style/guidelines/
|
|
318
|
+
- lib/head_music/style/guidelines/two_per_bar.rb
|
|
313
319
|
- lib/head_music/style/guidelines/up_to_fourteen_notes.rb
|
|
314
320
|
- lib/head_music/style/guidelines/weak_beat_dissonance_treatment.rb
|
|
315
321
|
- lib/head_music/style/guides/first_species_harmony.rb
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# Module for style guidelines.
|
|
2
|
-
module HeadMusic::Style::Guidelines; end
|
|
3
|
-
|
|
4
|
-
# A counterpoint guideline
|
|
5
|
-
class HeadMusic::Style::Guidelines::FourToOne < HeadMusic::Style::Guidelines::NoteCountPerBar
|
|
6
|
-
MESSAGE = "Use four quarter notes against each whole note in the cantus firmus."
|
|
7
|
-
|
|
8
|
-
QUARTER = HeadMusic::Rudiment::RhythmicValue.get(:quarter)
|
|
9
|
-
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
def check_first_bar(bar_number)
|
|
13
|
-
bar_notes = notes_in_bar(bar_number)
|
|
14
|
-
bar_rests = rests_in_bar(bar_number)
|
|
15
|
-
return if four_quarter_notes?(bar_notes)
|
|
16
|
-
return if rest_then_three_quarter_notes?(bar_notes, bar_rests)
|
|
17
|
-
return if three_quarter_notes_after_downbeat?(bar_notes)
|
|
18
|
-
|
|
19
|
-
mark_bar(bar_number)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def check_middle_bar(bar_number)
|
|
23
|
-
bar_notes = notes_in_bar(bar_number)
|
|
24
|
-
return if four_quarter_notes?(bar_notes)
|
|
25
|
-
|
|
26
|
-
mark_bar(bar_number)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def four_quarter_notes?(bar_notes)
|
|
30
|
-
bar_notes.length == 4 && bar_notes.all? { |note| note.rhythmic_value == QUARTER }
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def rest_then_three_quarter_notes?(bar_notes, bar_rests)
|
|
34
|
-
bar_notes.length == 3 &&
|
|
35
|
-
bar_notes.all? { |note| note.rhythmic_value == QUARTER } &&
|
|
36
|
-
bar_rests.length == 1 &&
|
|
37
|
-
bar_rests.first.rhythmic_value == QUARTER
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def three_quarter_notes_after_downbeat?(bar_notes)
|
|
41
|
-
bar_notes.length == 3 &&
|
|
42
|
-
bar_notes.all? { |note| note.rhythmic_value == QUARTER } &&
|
|
43
|
-
bar_notes.first.position.count > 1
|
|
44
|
-
end
|
|
45
|
-
end
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# Module for style guidelines.
|
|
2
|
-
module HeadMusic::Style::Guidelines; end
|
|
3
|
-
|
|
4
|
-
# A counterpoint guideline
|
|
5
|
-
class HeadMusic::Style::Guidelines::ThreeToOne < HeadMusic::Style::Guidelines::NoteCountPerBar
|
|
6
|
-
MESSAGE = "Use three quarter notes against each dotted half note in the cantus firmus."
|
|
7
|
-
|
|
8
|
-
QUARTER = HeadMusic::Rudiment::RhythmicValue.get(:quarter)
|
|
9
|
-
DOTTED_HALF = HeadMusic::Rudiment::RhythmicValue.get(:dotted_half)
|
|
10
|
-
|
|
11
|
-
private
|
|
12
|
-
|
|
13
|
-
def check_first_bar(bar_number)
|
|
14
|
-
bar_notes = notes_in_bar(bar_number)
|
|
15
|
-
bar_rests = rests_in_bar(bar_number)
|
|
16
|
-
return if three_quarter_notes?(bar_notes)
|
|
17
|
-
return if rest_then_two_quarter_notes?(bar_notes, bar_rests)
|
|
18
|
-
return if two_quarter_notes_after_downbeat?(bar_notes)
|
|
19
|
-
|
|
20
|
-
mark_bar(bar_number)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def check_middle_bar(bar_number)
|
|
24
|
-
bar_notes = notes_in_bar(bar_number)
|
|
25
|
-
return if three_quarter_notes?(bar_notes)
|
|
26
|
-
|
|
27
|
-
mark_bar(bar_number)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def check_final_bar(bar_number)
|
|
31
|
-
bar_notes = notes_in_bar(bar_number)
|
|
32
|
-
return if one_dotted_half_note?(bar_notes)
|
|
33
|
-
|
|
34
|
-
mark_bar(bar_number)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def three_quarter_notes?(bar_notes)
|
|
38
|
-
bar_notes.length == 3 && bar_notes.all? { |note| note.rhythmic_value == QUARTER }
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def rest_then_two_quarter_notes?(bar_notes, bar_rests)
|
|
42
|
-
bar_notes.length == 2 &&
|
|
43
|
-
bar_notes.all? { |note| note.rhythmic_value == QUARTER } &&
|
|
44
|
-
bar_rests.length == 1 &&
|
|
45
|
-
bar_rests.first.rhythmic_value == QUARTER
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def two_quarter_notes_after_downbeat?(bar_notes)
|
|
49
|
-
bar_notes.length == 2 &&
|
|
50
|
-
bar_notes.all? { |note| note.rhythmic_value == QUARTER } &&
|
|
51
|
-
bar_notes.first.position.count > 1
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def one_dotted_half_note?(bar_notes)
|
|
55
|
-
bar_notes.length == 1 && bar_notes.first.rhythmic_value == DOTTED_HALF
|
|
56
|
-
end
|
|
57
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# Module for style guidelines.
|
|
2
|
-
module HeadMusic::Style::Guidelines; end
|
|
3
|
-
|
|
4
|
-
# A counterpoint guideline
|
|
5
|
-
class HeadMusic::Style::Guidelines::TwoToOne < HeadMusic::Style::Guidelines::NoteCountPerBar
|
|
6
|
-
MESSAGE = "Use two half notes against each whole note in the cantus firmus."
|
|
7
|
-
|
|
8
|
-
HALF = HeadMusic::Rudiment::RhythmicValue.get(:half)
|
|
9
|
-
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
def check_first_bar(bar_number)
|
|
13
|
-
bar_notes = notes_in_bar(bar_number)
|
|
14
|
-
bar_rests = rests_in_bar(bar_number)
|
|
15
|
-
return if two_half_notes?(bar_notes)
|
|
16
|
-
return if rest_then_half_note?(bar_notes, bar_rests)
|
|
17
|
-
return if single_half_note_after_downbeat?(bar_notes)
|
|
18
|
-
|
|
19
|
-
mark_bar(bar_number)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def check_middle_bar(bar_number)
|
|
23
|
-
bar_notes = notes_in_bar(bar_number)
|
|
24
|
-
return if two_half_notes?(bar_notes)
|
|
25
|
-
|
|
26
|
-
mark_bar(bar_number)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def two_half_notes?(bar_notes)
|
|
30
|
-
bar_notes.length == 2 && bar_notes.all? { |note| note.rhythmic_value == HALF }
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def rest_then_half_note?(bar_notes, bar_rests)
|
|
34
|
-
bar_notes.length == 1 &&
|
|
35
|
-
bar_notes.first.rhythmic_value == HALF &&
|
|
36
|
-
bar_rests.length == 1 &&
|
|
37
|
-
bar_rests.first.rhythmic_value == HALF
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def single_half_note_after_downbeat?(bar_notes)
|
|
41
|
-
first_note = bar_notes.first
|
|
42
|
-
bar_notes.length == 1 &&
|
|
43
|
-
first_note.rhythmic_value == HALF &&
|
|
44
|
-
first_note.position.count > 1
|
|
45
|
-
end
|
|
46
|
-
end
|