head_music 7.0.5 → 8.0.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/.ruby-version +1 -1
- data/Gemfile +1 -1
- data/lib/head_music/{diatonic_interval → analysis/diatonic_interval}/category.rb +1 -1
- data/lib/head_music/{diatonic_interval → analysis/diatonic_interval}/naming.rb +6 -6
- data/lib/head_music/{diatonic_interval → analysis/diatonic_interval}/parser.rb +4 -4
- data/lib/head_music/{diatonic_interval → analysis/diatonic_interval}/semitones.rb +4 -4
- data/lib/head_music/{diatonic_interval → analysis/diatonic_interval}/size.rb +1 -1
- data/lib/head_music/{diatonic_interval.rb → analysis/diatonic_interval.rb} +19 -16
- data/lib/head_music/{harmonic_interval.rb → analysis/harmonic_interval.rb} +5 -2
- data/lib/head_music/{melodic_interval.rb → analysis/melodic_interval.rb} +6 -3
- data/lib/head_music/{motion.rb → analysis/motion.rb} +6 -3
- data/lib/head_music/content/bar.rb +2 -2
- data/lib/head_music/content/composition.rb +3 -3
- data/lib/head_music/content/note.rb +1 -1
- data/lib/head_music/content/placement.rb +1 -1
- data/lib/head_music/content/position.rb +1 -1
- data/lib/head_music/content/rhythmic_value.rb +3 -3
- data/lib/head_music/{staff.rb → content/staff.rb} +6 -3
- data/lib/head_music/content/voice.rb +2 -2
- data/lib/head_music/{instrument.rb → instruments/instrument.rb} +10 -7
- data/lib/head_music/{data → instruments}/instrument_families.yml +49 -0
- data/lib/head_music/{instrument_family.rb → instruments/instrument_family.rb} +5 -2
- data/lib/head_music/{data → instruments}/instruments.yml +116 -0
- data/lib/head_music/{instrument → instruments}/staff.rb +5 -2
- data/lib/head_music/{instrument → instruments}/staff_scheme.rb +7 -2
- data/lib/head_music/{instrument → instruments}/variant.rb +6 -3
- data/lib/head_music/locales/en.yml +22 -0
- data/lib/head_music/{alteration.rb → rudiment/alteration.rb} +9 -6
- data/lib/head_music/{chromatic_interval.rb → rudiment/chromatic_interval.rb} +7 -4
- data/lib/head_music/{circle.rb → rudiment/circle.rb} +9 -6
- data/lib/head_music/{clef.rb → rudiment/clef.rb} +7 -4
- data/lib/head_music/{consonance.rb → rudiment/consonance.rb} +4 -1
- data/lib/head_music/{interval_cycle.rb → rudiment/interval_cycle.rb} +12 -9
- data/lib/head_music/{key_signature → rudiment/key_signature}/enharmonic_equivalence.rb +4 -4
- data/lib/head_music/{key_signature.rb → rudiment/key_signature.rb} +10 -7
- data/lib/head_music/{letter_name.rb → rudiment/letter_name.rb} +9 -6
- data/lib/head_music/{meter.rb → rudiment/meter.rb} +6 -3
- data/lib/head_music/{musical_symbol.rb → rudiment/musical_symbol.rb} +4 -1
- data/lib/head_music/{pitch → rudiment/pitch}/enharmonic_equivalence.rb +4 -4
- data/lib/head_music/{pitch → rudiment/pitch}/octave_equivalence.rb +2 -2
- data/lib/head_music/{pitch.rb → rudiment/pitch.rb} +30 -27
- data/lib/head_music/{pitch_class.rb → rudiment/pitch_class.rb} +14 -11
- data/lib/head_music/{pitch_class_set.rb → rudiment/pitch_class_set.rb} +5 -2
- data/lib/head_music/{pitch_set.rb → rudiment/pitch_set.rb} +14 -11
- data/lib/head_music/{quality.rb → rudiment/quality.rb} +4 -1
- data/lib/head_music/{reference_pitch.rb → rudiment/reference_pitch.rb} +5 -2
- data/lib/head_music/{register.rb → rudiment/register.rb} +6 -3
- data/lib/head_music/rudiment/rhythm.rb +6 -0
- data/lib/head_music/{rhythmic_unit.rb → rudiment/rhythmic_unit.rb} +5 -2
- data/lib/head_music/{scale.rb → rudiment/scale.rb} +12 -9
- data/lib/head_music/{scale_degree.rb → rudiment/scale_degree.rb} +8 -5
- data/lib/head_music/{scale_type.rb → rudiment/scale_type.rb} +4 -1
- data/lib/head_music/{solmization.rb → rudiment/solmization.rb} +4 -1
- data/lib/head_music/{sonority.rb → rudiment/sonority.rb} +7 -4
- data/lib/head_music/{spelling.rb → rudiment/spelling.rb} +20 -17
- data/lib/head_music/{tuning.rb → rudiment/tuning.rb} +6 -3
- data/lib/head_music/style/annotation.rb +6 -6
- data/lib/head_music/style/guidelines/consonant_climax.rb +4 -4
- data/lib/head_music/style/guidelines/diatonic.rb +1 -1
- data/lib/head_music/style/guidelines/step_out_of_unison.rb +1 -1
- data/lib/head_music/version.rb +1 -1
- data/lib/head_music.rb +50 -46
- metadata +51 -51
- data/lib/head_music/rhythm.rb +0 -3
- /data/lib/head_music/{data → rudiment}/clefs.yml +0 -0
- /data/lib/head_music/{solmizations.yml → rudiment/solmizations.yml} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1693c61699c2fdcf64441f532c205b8be2e3b6b2be47e772c2471d671b7712b3
|
4
|
+
data.tar.gz: 1c819eee801f19b38cfbb6bdc51177c2e885aced316ea55034bb6c99a75183c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ced29a767bab571ee4c77a14d6c108510465c8424ee66249cd3343efbceb3bec2dec8e94664a2b260a4a0716ae51948c3b796ff088d0b3aab07d40ac762ec111
|
7
|
+
data.tar.gz: 6e7bf970c65500799fa0788f468885207f531c7a8de5c6f1f6be27952435994616f7dc1f10bf1ad51a233244a47d43eca553d9d73add30e8ca89afafac300d9b
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.3.0
|
data/Gemfile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Accepts a number and number of semitones and privides the naming methods.
|
2
|
-
class HeadMusic::DiatonicInterval::Naming
|
3
|
-
QUALITY_SEMITONES = HeadMusic::DiatonicInterval::QUALITY_SEMITONES
|
4
|
-
NUMBER_NAMES = HeadMusic::DiatonicInterval::NUMBER_NAMES
|
5
|
-
NAME_SUFFIXES = HeadMusic::DiatonicInterval::NAME_SUFFIXES
|
2
|
+
class HeadMusic::Analysis::DiatonicInterval::Naming
|
3
|
+
QUALITY_SEMITONES = HeadMusic::Analysis::DiatonicInterval::QUALITY_SEMITONES
|
4
|
+
NUMBER_NAMES = HeadMusic::Analysis::DiatonicInterval::NUMBER_NAMES
|
5
|
+
NAME_SUFFIXES = HeadMusic::Analysis::DiatonicInterval::NAME_SUFFIXES
|
6
6
|
|
7
7
|
attr_reader :number, :semitones
|
8
8
|
|
@@ -23,7 +23,7 @@ class HeadMusic::DiatonicInterval::Naming
|
|
23
23
|
starting_quality = QUALITY_SEMITONES[simple_number_name.to_sym].keys.first
|
24
24
|
delta = simple_semitones - (QUALITY_SEMITONES[simple_number_name.to_sym][starting_quality] % 12)
|
25
25
|
delta -= 12 while delta >= 6
|
26
|
-
HeadMusic::Quality.from(starting_quality, delta)
|
26
|
+
HeadMusic::Rudiment::Quality.from(starting_quality, delta)
|
27
27
|
end
|
28
28
|
|
29
29
|
def simple_number_name
|
@@ -60,7 +60,7 @@ class HeadMusic::DiatonicInterval::Naming
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def quality
|
63
|
-
@quality ||= HeadMusic::Quality.get(quality_name)
|
63
|
+
@quality ||= HeadMusic::Rudiment::Quality.get(quality_name)
|
64
64
|
end
|
65
65
|
|
66
66
|
def octaves
|
@@ -1,5 +1,5 @@
|
|
1
|
-
class HeadMusic::DiatonicInterval::Parser
|
2
|
-
NUMBER_NAMES = HeadMusic::DiatonicInterval::NUMBER_NAMES
|
1
|
+
class HeadMusic::Analysis::DiatonicInterval::Parser
|
2
|
+
NUMBER_NAMES = HeadMusic::Analysis::DiatonicInterval::NUMBER_NAMES
|
3
3
|
|
4
4
|
attr_reader :identifier
|
5
5
|
|
@@ -24,7 +24,7 @@ class HeadMusic::DiatonicInterval::Parser
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def higher_letter
|
27
|
-
HeadMusic::Pitch.middle_c.letter_name.steps_up(steps)
|
27
|
+
HeadMusic::Rudiment::Pitch.middle_c.letter_name.steps_up(steps)
|
28
28
|
end
|
29
29
|
|
30
30
|
def expand(identifier)
|
@@ -36,7 +36,7 @@ class HeadMusic::DiatonicInterval::Parser
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def quality_abbreviations
|
39
|
-
HeadMusic::DiatonicInterval::QUALITY_ABBREVIATIONS
|
39
|
+
HeadMusic::Analysis::DiatonicInterval::QUALITY_ABBREVIATIONS
|
40
40
|
end
|
41
41
|
|
42
42
|
def quality_for(abbreviation)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Accepts a name and a quality and returns the number of semitones
|
2
|
-
class HeadMusic::DiatonicInterval::Semitones
|
3
|
-
QUALITY_SEMITONES = HeadMusic::DiatonicInterval::QUALITY_SEMITONES
|
2
|
+
class HeadMusic::Analysis::DiatonicInterval::Semitones
|
3
|
+
QUALITY_SEMITONES = HeadMusic::Analysis::DiatonicInterval::QUALITY_SEMITONES
|
4
4
|
|
5
5
|
attr_reader :count
|
6
6
|
|
@@ -28,9 +28,9 @@ class HeadMusic::DiatonicInterval::Semitones
|
|
28
28
|
|
29
29
|
def self._degree_quality_modifications(quality)
|
30
30
|
if quality == :perfect
|
31
|
-
HeadMusic::Quality::PERFECT_INTERVAL_MODIFICATION.invert
|
31
|
+
HeadMusic::Rudiment::Quality::PERFECT_INTERVAL_MODIFICATION.invert
|
32
32
|
else
|
33
|
-
HeadMusic::Quality::MAJOR_INTERVAL_MODIFICATION.invert
|
33
|
+
HeadMusic::Rudiment::Quality::MAJOR_INTERVAL_MODIFICATION.invert
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -1,5 +1,8 @@
|
|
1
|
+
# A module for musical analysis
|
2
|
+
module HeadMusic::Analysis; end
|
3
|
+
|
1
4
|
# A diatonic interval is the distance between two spelled pitches.
|
2
|
-
class HeadMusic::DiatonicInterval
|
5
|
+
class HeadMusic::Analysis::DiatonicInterval
|
3
6
|
include Comparable
|
4
7
|
|
5
8
|
# TODO: include Named module
|
@@ -59,33 +62,33 @@ class HeadMusic::DiatonicInterval
|
|
59
62
|
def self.get(identifier)
|
60
63
|
name = Parser.new(identifier)
|
61
64
|
semitones = Semitones.new(name.degree_name.to_sym, name.quality_name).count
|
62
|
-
higher_pitch = HeadMusic::Pitch.from_number_and_letter(HeadMusic::Pitch.middle_c + semitones, name.higher_letter)
|
63
|
-
new(HeadMusic::Pitch.middle_c, higher_pitch)
|
65
|
+
higher_pitch = HeadMusic::Rudiment::Pitch.from_number_and_letter(HeadMusic::Rudiment::Pitch.middle_c + semitones, name.higher_letter)
|
66
|
+
new(HeadMusic::Rudiment::Pitch.middle_c, higher_pitch)
|
64
67
|
end
|
65
68
|
|
66
69
|
def initialize(pitch1, pitch2)
|
67
|
-
pitch1 = HeadMusic::Pitch.get(pitch1)
|
68
|
-
pitch2 = HeadMusic::Pitch.get(pitch2)
|
70
|
+
pitch1 = HeadMusic::Rudiment::Pitch.get(pitch1)
|
71
|
+
pitch2 = HeadMusic::Rudiment::Pitch.get(pitch2)
|
69
72
|
@lower_pitch, @higher_pitch = [pitch1, pitch2].sort
|
70
73
|
end
|
71
74
|
|
72
75
|
def quality
|
73
|
-
HeadMusic::Quality.get(quality_name)
|
76
|
+
HeadMusic::Rudiment::Quality.get(quality_name)
|
74
77
|
end
|
75
78
|
|
76
79
|
def inversion
|
77
80
|
inverted_low_pitch = lower_pitch
|
78
81
|
while inverted_low_pitch < higher_pitch
|
79
|
-
inverted_low_pitch = HeadMusic::Pitch.fetch_or_create(lower_pitch.spelling, inverted_low_pitch.register + 1)
|
82
|
+
inverted_low_pitch = HeadMusic::Rudiment::Pitch.fetch_or_create(lower_pitch.spelling, inverted_low_pitch.register + 1)
|
80
83
|
end
|
81
|
-
HeadMusic::DiatonicInterval.new(higher_pitch, inverted_low_pitch)
|
84
|
+
HeadMusic::Analysis::DiatonicInterval.new(higher_pitch, inverted_low_pitch)
|
82
85
|
end
|
83
86
|
alias_method :invert, :inversion
|
84
87
|
|
85
88
|
def consonance(style = :standard_practice)
|
86
89
|
consonance_for_perfect(style) ||
|
87
90
|
consonance_for_major_and_minor ||
|
88
|
-
HeadMusic::Consonance.get(:dissonant)
|
91
|
+
HeadMusic::Rudiment::Consonance.get(:dissonant)
|
89
92
|
end
|
90
93
|
|
91
94
|
def consonance?(style = :standard_practice)
|
@@ -106,13 +109,13 @@ class HeadMusic::DiatonicInterval
|
|
106
109
|
end
|
107
110
|
|
108
111
|
def above(pitch)
|
109
|
-
pitch = HeadMusic::Pitch.get(pitch)
|
110
|
-
HeadMusic::Pitch.from_number_and_letter(pitch + semitones, pitch.letter_name.steps_up(number - 1))
|
112
|
+
pitch = HeadMusic::Rudiment::Pitch.get(pitch)
|
113
|
+
HeadMusic::Rudiment::Pitch.from_number_and_letter(pitch + semitones, pitch.letter_name.steps_up(number - 1))
|
111
114
|
end
|
112
115
|
|
113
116
|
def below(pitch)
|
114
|
-
pitch = HeadMusic::Pitch.get(pitch)
|
115
|
-
HeadMusic::Pitch.from_number_and_letter(pitch - semitones, pitch.letter_name.steps_down(number - 1))
|
117
|
+
pitch = HeadMusic::Rudiment::Pitch.get(pitch)
|
118
|
+
HeadMusic::Rudiment::Pitch.from_number_and_letter(pitch - semitones, pitch.letter_name.steps_down(number - 1))
|
116
119
|
end
|
117
120
|
|
118
121
|
def interval_class
|
@@ -128,7 +131,7 @@ class HeadMusic::DiatonicInterval
|
|
128
131
|
alias_method :diatonic_generic_interval, :simple_steps
|
129
132
|
|
130
133
|
def <=>(other)
|
131
|
-
other = self.class.get(other) unless other.is_a?(HeadMusic::DiatonicInterval)
|
134
|
+
other = self.class.get(other) unless other.is_a?(HeadMusic::Analysis::DiatonicInterval)
|
132
135
|
semitones <=> other.semitones
|
133
136
|
end
|
134
137
|
|
@@ -155,11 +158,11 @@ class HeadMusic::DiatonicInterval
|
|
155
158
|
end
|
156
159
|
|
157
160
|
def consonance_for_perfect(style = :standard_practice)
|
158
|
-
HeadMusic::Consonance.get(dissonant_fourth?(style) ? :dissonant : :perfect) if perfect?
|
161
|
+
HeadMusic::Rudiment::Consonance.get(dissonant_fourth?(style) ? :dissonant : :perfect) if perfect?
|
159
162
|
end
|
160
163
|
|
161
164
|
def consonance_for_major_and_minor
|
162
|
-
HeadMusic::Consonance.get((third_or_compound? || sixth_or_compound?) ? :imperfect : :dissonant) if major? || minor?
|
165
|
+
HeadMusic::Rudiment::Consonance.get((third_or_compound? || sixth_or_compound?) ? :imperfect : :dissonant) if major? || minor?
|
163
166
|
end
|
164
167
|
|
165
168
|
def dissonant_fourth?(style = :standard_practice)
|
@@ -1,5 +1,8 @@
|
|
1
|
+
# A module for musical analysis
|
2
|
+
module HeadMusic::Analysis; end
|
3
|
+
|
1
4
|
# A harmonic interval is the diatonic interval between two notes sounding together.
|
2
|
-
class HeadMusic::HarmonicInterval
|
5
|
+
class HeadMusic::Analysis::HarmonicInterval
|
3
6
|
attr_reader :voice1, :voice2, :position
|
4
7
|
|
5
8
|
def initialize(voice1, voice2, position)
|
@@ -9,7 +12,7 @@ class HeadMusic::HarmonicInterval
|
|
9
12
|
end
|
10
13
|
|
11
14
|
def diatonic_interval
|
12
|
-
@diatonic_interval ||= HeadMusic::DiatonicInterval.new(lower_pitch, upper_pitch)
|
15
|
+
@diatonic_interval ||= HeadMusic::Analysis::DiatonicInterval.new(lower_pitch, upper_pitch)
|
13
16
|
end
|
14
17
|
|
15
18
|
def voices
|
@@ -1,5 +1,8 @@
|
|
1
|
+
# A module for musical analysis
|
2
|
+
module HeadMusic::Analysis; end
|
3
|
+
|
1
4
|
# A melodic interval is the distance between one note and the next.
|
2
|
-
class HeadMusic::MelodicInterval
|
5
|
+
class HeadMusic::Analysis::MelodicInterval
|
3
6
|
attr_reader :first_note, :second_note
|
4
7
|
|
5
8
|
def initialize(note1, note2)
|
@@ -8,7 +11,7 @@ class HeadMusic::MelodicInterval
|
|
8
11
|
end
|
9
12
|
|
10
13
|
def diatonic_interval
|
11
|
-
@diatonic_interval ||= HeadMusic::DiatonicInterval.new(first_pitch, second_pitch)
|
14
|
+
@diatonic_interval ||= HeadMusic::Analysis::DiatonicInterval.new(first_pitch, second_pitch)
|
12
15
|
end
|
13
16
|
|
14
17
|
def position_start
|
@@ -84,7 +87,7 @@ class HeadMusic::MelodicInterval
|
|
84
87
|
combined_pitches = (pitches + other_interval.pitches).uniq
|
85
88
|
return false if combined_pitches.length < 3
|
86
89
|
|
87
|
-
HeadMusic::PitchSet.new(combined_pitches).consonant_triad?
|
90
|
+
HeadMusic::Rudiment::PitchSet.new(combined_pitches).consonant_triad?
|
88
91
|
end
|
89
92
|
|
90
93
|
def method_missing(method_name, *args, &block)
|
@@ -1,5 +1,8 @@
|
|
1
|
+
# A module for musical analysis
|
2
|
+
module HeadMusic::Analysis; end
|
3
|
+
|
1
4
|
# Motion defines the relative pitch direction of the upper and lower voices of subsequence intervals.
|
2
|
-
class HeadMusic::Motion
|
5
|
+
class HeadMusic::Analysis::Motion
|
3
6
|
attr_reader :first_harmonic_interval, :second_harmonic_interval
|
4
7
|
|
5
8
|
def initialize(first_harmonic_interval, second_harmonic_interval)
|
@@ -56,11 +59,11 @@ class HeadMusic::Motion
|
|
56
59
|
private
|
57
60
|
|
58
61
|
def upper_melodic_interval
|
59
|
-
HeadMusic::MelodicInterval.new(upper_notes.first, upper_notes.last)
|
62
|
+
HeadMusic::Analysis::MelodicInterval.new(upper_notes.first, upper_notes.last)
|
60
63
|
end
|
61
64
|
|
62
65
|
def lower_melodic_interval
|
63
|
-
HeadMusic::MelodicInterval.new(lower_notes.first, lower_notes.last)
|
66
|
+
HeadMusic::Analysis::MelodicInterval.new(lower_notes.first, lower_notes.last)
|
64
67
|
end
|
65
68
|
|
66
69
|
def upper_notes
|
@@ -9,8 +9,8 @@ class HeadMusic::Content::Bar
|
|
9
9
|
|
10
10
|
def initialize(composition, key_signature: nil, meter: nil)
|
11
11
|
@composition = composition
|
12
|
-
@key_signature = HeadMusic::KeySignature.get(key_signature) if key_signature
|
13
|
-
@meter = HeadMusic::Meter.get(meter) if meter
|
12
|
+
@key_signature = HeadMusic::Rudiment::KeySignature.get(key_signature) if key_signature
|
13
|
+
@meter = HeadMusic::Rudiment::Meter.get(meter) if meter
|
14
14
|
end
|
15
15
|
|
16
16
|
def to_s
|
@@ -65,9 +65,9 @@ class HeadMusic::Content::Composition
|
|
65
65
|
|
66
66
|
def ensure_attributes(name, key_signature, meter)
|
67
67
|
@name = name || "Composition"
|
68
|
-
@key_signature = HeadMusic::KeySignature.get(key_signature) if key_signature
|
69
|
-
@key_signature ||= HeadMusic::KeySignature.default
|
70
|
-
@meter = meter ? HeadMusic::Meter.get(meter) : HeadMusic::Meter.default
|
68
|
+
@key_signature = HeadMusic::Rudiment::KeySignature.get(key_signature) if key_signature
|
69
|
+
@key_signature ||= HeadMusic::Rudiment::KeySignature.default
|
70
|
+
@meter = meter ? HeadMusic::Rudiment::Meter.get(meter) : HeadMusic::Rudiment::Meter.default
|
71
71
|
end
|
72
72
|
|
73
73
|
def last_meter_change(bar_number)
|
@@ -10,7 +10,7 @@ class HeadMusic::Content::Note
|
|
10
10
|
attr_accessor :pitch, :rhythmic_value, :voice, :position
|
11
11
|
|
12
12
|
def initialize(pitch, rhythmic_value, voice = nil, position = nil)
|
13
|
-
@pitch = HeadMusic::Pitch.get(pitch)
|
13
|
+
@pitch = HeadMusic::Rudiment::Pitch.get(pitch)
|
14
14
|
@rhythmic_value = HeadMusic::Content::RhythmicValue.get(rhythmic_value)
|
15
15
|
@voice = voice || HeadMusic::Content::Voice.new
|
16
16
|
@position = position || HeadMusic::Content::Position.new(@voice.composition, "1:1")
|
@@ -56,7 +56,7 @@ class HeadMusic::Content::Placement
|
|
56
56
|
@voice = voice
|
57
57
|
ensure_position(position)
|
58
58
|
@rhythmic_value = HeadMusic::Content::RhythmicValue.get(rhythmic_value)
|
59
|
-
@pitch = HeadMusic::Pitch.get(pitch)
|
59
|
+
@pitch = HeadMusic::Rudiment::Pitch.get(pitch)
|
60
60
|
end
|
61
61
|
|
62
62
|
def ensure_position(position)
|
@@ -53,7 +53,7 @@ class HeadMusic::Content::Position
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def +(other)
|
56
|
-
other = HeadMusic::Content::RhythmicValue.new(other) if [HeadMusic::RhythmicUnit, Symbol, String].include?(other.class)
|
56
|
+
other = HeadMusic::Content::RhythmicValue.new(other) if [HeadMusic::Rudiment::RhythmicUnit, Symbol, String].include?(other.class)
|
57
57
|
self.class.new(composition, bar_number, count, tick + other.ticks)
|
58
58
|
end
|
59
59
|
|
@@ -12,7 +12,7 @@ class HeadMusic::Content::RhythmicValue
|
|
12
12
|
case identifier
|
13
13
|
when HeadMusic::Content::RhythmicValue
|
14
14
|
identifier
|
15
|
-
when HeadMusic::RhythmicUnit
|
15
|
+
when HeadMusic::Rudiment::RhythmicUnit
|
16
16
|
new(identifier)
|
17
17
|
when Symbol, String
|
18
18
|
identifier = identifier.to_s.downcase.strip.gsub(/\W+/, "_")
|
@@ -43,7 +43,7 @@ class HeadMusic::Content::RhythmicValue
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def initialize(unit, dots: nil, tied_value: nil)
|
46
|
-
@unit = HeadMusic::RhythmicUnit.get(unit)
|
46
|
+
@unit = HeadMusic::Rudiment::RhythmicUnit.get(unit)
|
47
47
|
@dots = [0, 1, 2, 3].include?(dots) ? dots : 0
|
48
48
|
@tied_value = tied_value
|
49
49
|
end
|
@@ -65,7 +65,7 @@ class HeadMusic::Content::RhythmicValue
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def ticks
|
68
|
-
HeadMusic::Rhythm::PPQN * 4 * total_value
|
68
|
+
HeadMusic::Rudiment::Rhythm::PPQN * 4 * total_value
|
69
69
|
end
|
70
70
|
|
71
71
|
def per_whole
|
@@ -1,13 +1,16 @@
|
|
1
|
+
# A module for musical content
|
2
|
+
module HeadMusic::Content; end
|
3
|
+
|
1
4
|
# A staff is a set of lines and spaces that provides context for a pitch
|
2
|
-
class HeadMusic::Staff
|
5
|
+
class HeadMusic::Content::Staff
|
3
6
|
DEFAULT_LINE_COUNT = 5
|
4
7
|
|
5
8
|
attr_reader :default_clef, :line_count, :instrument
|
6
9
|
|
7
10
|
def initialize(default_clef_key, instrument: nil, line_count: nil)
|
8
|
-
@default_clef = HeadMusic::Clef.get(default_clef_key)
|
11
|
+
@default_clef = HeadMusic::Rudiment::Clef.get(default_clef_key)
|
9
12
|
@line_count = line_count || DEFAULT_LINE_COUNT
|
10
|
-
@instrument = HeadMusic::Instrument.get(instrument) if instrument
|
13
|
+
@instrument = HeadMusic::Instruments::Instrument.get(instrument) if instrument
|
11
14
|
end
|
12
15
|
|
13
16
|
def clef
|
@@ -56,12 +56,12 @@ class HeadMusic::Content::Voice
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def range
|
59
|
-
HeadMusic::DiatonicInterval.new(lowest_pitch, highest_pitch)
|
59
|
+
HeadMusic::Analysis::DiatonicInterval.new(lowest_pitch, highest_pitch)
|
60
60
|
end
|
61
61
|
|
62
62
|
def melodic_intervals
|
63
63
|
@melodic_intervals ||=
|
64
|
-
notes.each_cons(2).map { |note_pair| HeadMusic::MelodicInterval.new(*note_pair) }
|
64
|
+
notes.each_cons(2).map { |note_pair| HeadMusic::Analysis::MelodicInterval.new(*note_pair) }
|
65
65
|
end
|
66
66
|
|
67
67
|
def leaps
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# Namespace for instrument definitions, categorization, and configuration
|
2
|
+
module HeadMusic::Instruments; end
|
3
|
+
|
1
4
|
# A musical instrument.
|
2
5
|
# An instrument object can be assigned to a staff object.
|
3
6
|
# Attributes:
|
@@ -14,17 +17,17 @@
|
|
14
17
|
# Associations:
|
15
18
|
# family: the family of the instrument (e.g. "saxophone")
|
16
19
|
# orchestra_section: the section of the orchestra (e.g. "strings")
|
17
|
-
class HeadMusic::Instrument
|
20
|
+
class HeadMusic::Instruments::Instrument
|
18
21
|
include HeadMusic::Named
|
19
22
|
|
20
|
-
INSTRUMENTS = YAML.load_file(File.expand_path("
|
23
|
+
INSTRUMENTS = YAML.load_file(File.expand_path("instruments.yml", __dir__)).freeze
|
21
24
|
|
22
25
|
def self.get(name)
|
23
26
|
get_by_name(name)
|
24
27
|
end
|
25
28
|
|
26
29
|
def self.all
|
27
|
-
HeadMusic::InstrumentFamily.all
|
30
|
+
HeadMusic::Instruments::InstrumentFamily.all
|
28
31
|
@all ||=
|
29
32
|
INSTRUMENTS.map { |key, _data| get(key) }.sort_by { |instrument| instrument.name.downcase }
|
30
33
|
end
|
@@ -48,7 +51,7 @@ class HeadMusic::Instrument
|
|
48
51
|
def family
|
49
52
|
return unless family_key
|
50
53
|
|
51
|
-
HeadMusic::InstrumentFamily.get(family_key)
|
54
|
+
HeadMusic::Instruments::InstrumentFamily.get(family_key)
|
52
55
|
end
|
53
56
|
|
54
57
|
# Returns true if the instrument sounds at a different pitch than written.
|
@@ -70,7 +73,7 @@ class HeadMusic::Instrument
|
|
70
73
|
end
|
71
74
|
|
72
75
|
def pitched?
|
73
|
-
return false if default_clefs.compact.uniq == [HeadMusic::Clef.get("neutral_clef")]
|
76
|
+
return false if default_clefs.compact.uniq == [HeadMusic::Rudiment::Clef.get("neutral_clef")]
|
74
77
|
|
75
78
|
default_clefs.any?
|
76
79
|
end
|
@@ -139,7 +142,7 @@ class HeadMusic::Instrument
|
|
139
142
|
|
140
143
|
def initialize_family(record)
|
141
144
|
@family_key = record["family_key"]
|
142
|
-
@family = HeadMusic::InstrumentFamily.get(family_key)
|
145
|
+
@family = HeadMusic::Instruments::InstrumentFamily.get(family_key)
|
143
146
|
end
|
144
147
|
|
145
148
|
def inherit_family_attributes(record)
|
@@ -160,7 +163,7 @@ class HeadMusic::Instrument
|
|
160
163
|
@classification_keys = [@classification_keys, record["classification_keys"]].flatten.compact.uniq
|
161
164
|
@variants =
|
162
165
|
(record["variants"] || {}).map do |key, attributes|
|
163
|
-
HeadMusic::
|
166
|
+
HeadMusic::Instruments::Variant.new(key, attributes)
|
164
167
|
end
|
165
168
|
end
|
166
169
|
|
@@ -47,7 +47,12 @@ cymbal:
|
|
47
47
|
classification_keys:
|
48
48
|
- percussion
|
49
49
|
- idiophone
|
50
|
+
- unpitched
|
50
51
|
orchestra_section_key: percussion
|
52
|
+
didgeridoo:
|
53
|
+
classification_keys:
|
54
|
+
- aerophone
|
55
|
+
- wind
|
51
56
|
double_bass:
|
52
57
|
classification_keys:
|
53
58
|
- bowed
|
@@ -69,11 +74,13 @@ glockenspiel:
|
|
69
74
|
- struck
|
70
75
|
- metal
|
71
76
|
- mallet
|
77
|
+
- pitched
|
72
78
|
orchestra_section_key: percussion
|
73
79
|
gong:
|
74
80
|
classification_keys:
|
75
81
|
- percussion
|
76
82
|
- idiophone
|
83
|
+
- unpitched
|
77
84
|
orchestra_section_key: percussion
|
78
85
|
guitar:
|
79
86
|
classification_keys:
|
@@ -81,6 +88,13 @@ guitar:
|
|
81
88
|
- plucked
|
82
89
|
- string
|
83
90
|
orchestra_section_key: string
|
91
|
+
harmonica:
|
92
|
+
classification_keys:
|
93
|
+
- reed
|
94
|
+
- free-reed
|
95
|
+
- aerophone
|
96
|
+
- wind
|
97
|
+
orchestra_section_key: woodwind
|
84
98
|
harp:
|
85
99
|
classification_keys:
|
86
100
|
- chordophone
|
@@ -104,6 +118,7 @@ kettledrum:
|
|
104
118
|
classification_keys:
|
105
119
|
- percussion
|
106
120
|
- membranophone
|
121
|
+
- pitched
|
107
122
|
orchestra_section_key: percussion
|
108
123
|
lute:
|
109
124
|
classification_keys:
|
@@ -125,6 +140,7 @@ marimba:
|
|
125
140
|
- struck
|
126
141
|
- wood
|
127
142
|
- mallet
|
143
|
+
- pitched
|
128
144
|
orchestra_section_key: percussion
|
129
145
|
oboe:
|
130
146
|
classification_keys:
|
@@ -166,16 +182,40 @@ saxophone:
|
|
166
182
|
- wind
|
167
183
|
- woodwind
|
168
184
|
orchestra_section_key: woodwind
|
185
|
+
sitar:
|
186
|
+
classification_keys:
|
187
|
+
- chordophone
|
188
|
+
- plucked
|
189
|
+
- string
|
190
|
+
orchestra_section_key: string
|
169
191
|
snare_drum:
|
170
192
|
classification_keys:
|
171
193
|
- percussion
|
172
194
|
- membranophone
|
195
|
+
- unpitched
|
196
|
+
orchestra_section_key: percussion
|
197
|
+
steelpan:
|
198
|
+
classification_keys:
|
199
|
+
- percussion
|
200
|
+
- idiophone
|
201
|
+
- struck
|
202
|
+
- metal
|
203
|
+
- pitched
|
173
204
|
orchestra_section_key: percussion
|
174
205
|
synthesizer:
|
175
206
|
classification_keys:
|
176
207
|
- electronic
|
177
208
|
- keyboard
|
178
209
|
orchestra_section_key: keyboard
|
210
|
+
tabla:
|
211
|
+
classification_keys:
|
212
|
+
- percussion
|
213
|
+
- membranophone
|
214
|
+
- pitched
|
215
|
+
orchestra_section_key: percussion
|
216
|
+
theremin:
|
217
|
+
classification_keys:
|
218
|
+
- electronic
|
179
219
|
trombone:
|
180
220
|
classification_keys:
|
181
221
|
- aerophone
|
@@ -194,6 +234,12 @@ tuba:
|
|
194
234
|
- brass
|
195
235
|
- wind
|
196
236
|
orchestra_section_key: brass
|
237
|
+
ukulele:
|
238
|
+
classification_keys:
|
239
|
+
- chordophone
|
240
|
+
- plucked
|
241
|
+
- string
|
242
|
+
orchestra_section_key: string
|
197
243
|
vibraphone:
|
198
244
|
classification_keys:
|
199
245
|
- percussion
|
@@ -202,6 +248,7 @@ vibraphone:
|
|
202
248
|
- keyboard
|
203
249
|
- mallet
|
204
250
|
- metal
|
251
|
+
- pitched
|
205
252
|
orchestra_section_key: percussion
|
206
253
|
violin:
|
207
254
|
classification_keys:
|
@@ -218,6 +265,7 @@ woodblock:
|
|
218
265
|
- percussion
|
219
266
|
- struck
|
220
267
|
- idiophone
|
268
|
+
- unpitched
|
221
269
|
orchestra_section_key: percussion
|
222
270
|
xylophone:
|
223
271
|
classification_keys:
|
@@ -227,4 +275,5 @@ xylophone:
|
|
227
275
|
- keyboard
|
228
276
|
- mallet
|
229
277
|
- wood
|
278
|
+
- pitched
|
230
279
|
orchestra_section_key: percussion
|
@@ -1,12 +1,15 @@
|
|
1
|
+
# Namespace for instrument definitions, categorization, and configuration
|
2
|
+
module HeadMusic::Instruments; end
|
3
|
+
|
1
4
|
# An *InstrumentFamily* is a species of instrument
|
2
5
|
# that may exist in a variety of keys or other variations.
|
3
6
|
# For example, _saxophone_ is an instrument family, while
|
4
7
|
# _alto saxophone_ and _baritone saxophone_ are specific instruments.
|
5
|
-
class HeadMusic::InstrumentFamily
|
8
|
+
class HeadMusic::Instruments::InstrumentFamily
|
6
9
|
include HeadMusic::Named
|
7
10
|
|
8
11
|
INSTRUMENT_FAMILIES =
|
9
|
-
YAML.load_file(File.expand_path("
|
12
|
+
YAML.load_file(File.expand_path("instrument_families.yml", __dir__)).freeze
|
10
13
|
|
11
14
|
attr_reader :name_key, :classification_keys, :orchestra_section_key
|
12
15
|
attr_accessor :name
|