head_music 7.0.4 → 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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/Gemfile +1 -1
  4. data/lib/head_music/{diatonic_interval → analysis/diatonic_interval}/category.rb +1 -1
  5. data/lib/head_music/{diatonic_interval → analysis/diatonic_interval}/naming.rb +6 -6
  6. data/lib/head_music/{diatonic_interval → analysis/diatonic_interval}/parser.rb +4 -4
  7. data/lib/head_music/{diatonic_interval → analysis/diatonic_interval}/semitones.rb +4 -4
  8. data/lib/head_music/{diatonic_interval → analysis/diatonic_interval}/size.rb +1 -1
  9. data/lib/head_music/{diatonic_interval.rb → analysis/diatonic_interval.rb} +19 -16
  10. data/lib/head_music/{harmonic_interval.rb → analysis/harmonic_interval.rb} +5 -2
  11. data/lib/head_music/{melodic_interval.rb → analysis/melodic_interval.rb} +6 -3
  12. data/lib/head_music/{motion.rb → analysis/motion.rb} +6 -3
  13. data/lib/head_music/content/bar.rb +2 -2
  14. data/lib/head_music/content/composition.rb +3 -3
  15. data/lib/head_music/content/note.rb +1 -1
  16. data/lib/head_music/content/placement.rb +1 -1
  17. data/lib/head_music/content/position.rb +1 -1
  18. data/lib/head_music/content/rhythmic_value.rb +3 -3
  19. data/lib/head_music/{staff.rb → content/staff.rb} +6 -3
  20. data/lib/head_music/content/voice.rb +2 -2
  21. data/lib/head_music/{instrument.rb → instruments/instrument.rb} +10 -7
  22. data/lib/head_music/{data → instruments}/instrument_families.yml +49 -0
  23. data/lib/head_music/{instrument_family.rb → instruments/instrument_family.rb} +5 -2
  24. data/lib/head_music/{data → instruments}/instruments.yml +116 -0
  25. data/lib/head_music/{instrument → instruments}/staff.rb +5 -2
  26. data/lib/head_music/{instrument → instruments}/staff_scheme.rb +7 -2
  27. data/lib/head_music/{instrument → instruments}/variant.rb +6 -3
  28. data/lib/head_music/locales/en.yml +22 -0
  29. data/lib/head_music/locales/es.yml +22 -22
  30. data/lib/head_music/{alteration.rb → rudiment/alteration.rb} +9 -6
  31. data/lib/head_music/{chromatic_interval.rb → rudiment/chromatic_interval.rb} +7 -4
  32. data/lib/head_music/{circle.rb → rudiment/circle.rb} +9 -6
  33. data/lib/head_music/{clef.rb → rudiment/clef.rb} +7 -4
  34. data/lib/head_music/{consonance.rb → rudiment/consonance.rb} +4 -1
  35. data/lib/head_music/{interval_cycle.rb → rudiment/interval_cycle.rb} +12 -9
  36. data/lib/head_music/{key_signature → rudiment/key_signature}/enharmonic_equivalence.rb +4 -4
  37. data/lib/head_music/{key_signature.rb → rudiment/key_signature.rb} +10 -7
  38. data/lib/head_music/{letter_name.rb → rudiment/letter_name.rb} +9 -6
  39. data/lib/head_music/{meter.rb → rudiment/meter.rb} +6 -3
  40. data/lib/head_music/{musical_symbol.rb → rudiment/musical_symbol.rb} +4 -1
  41. data/lib/head_music/{pitch → rudiment/pitch}/enharmonic_equivalence.rb +4 -4
  42. data/lib/head_music/{pitch → rudiment/pitch}/octave_equivalence.rb +2 -2
  43. data/lib/head_music/{pitch.rb → rudiment/pitch.rb} +30 -27
  44. data/lib/head_music/{pitch_class.rb → rudiment/pitch_class.rb} +14 -11
  45. data/lib/head_music/{pitch_class_set.rb → rudiment/pitch_class_set.rb} +5 -2
  46. data/lib/head_music/{pitch_set.rb → rudiment/pitch_set.rb} +14 -11
  47. data/lib/head_music/{quality.rb → rudiment/quality.rb} +4 -1
  48. data/lib/head_music/{reference_pitch.rb → rudiment/reference_pitch.rb} +5 -2
  49. data/lib/head_music/{register.rb → rudiment/register.rb} +6 -3
  50. data/lib/head_music/rudiment/rhythm.rb +6 -0
  51. data/lib/head_music/{rhythmic_unit.rb → rudiment/rhythmic_unit.rb} +5 -2
  52. data/lib/head_music/{scale.rb → rudiment/scale.rb} +12 -9
  53. data/lib/head_music/{scale_degree.rb → rudiment/scale_degree.rb} +8 -5
  54. data/lib/head_music/{scale_type.rb → rudiment/scale_type.rb} +4 -1
  55. data/lib/head_music/{solmization.rb → rudiment/solmization.rb} +4 -1
  56. data/lib/head_music/{sonority.rb → rudiment/sonority.rb} +7 -4
  57. data/lib/head_music/{spelling.rb → rudiment/spelling.rb} +20 -17
  58. data/lib/head_music/{tuning.rb → rudiment/tuning.rb} +6 -3
  59. data/lib/head_music/style/annotation.rb +6 -6
  60. data/lib/head_music/style/guidelines/consonant_climax.rb +4 -4
  61. data/lib/head_music/style/guidelines/diatonic.rb +1 -1
  62. data/lib/head_music/style/guidelines/step_out_of_unison.rb +1 -1
  63. data/lib/head_music/version.rb +1 -1
  64. data/lib/head_music.rb +50 -46
  65. metadata +51 -51
  66. data/lib/head_music/rhythm.rb +0 -3
  67. /data/lib/head_music/{data → rudiment}/clefs.yml +0 -0
  68. /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: 2179abb1bb9bb68a8b73e1847a6b715a37902b8601b1fad1f42729e4a7485c4b
4
- data.tar.gz: 6e9eb38f55e86b7f87a9f6ce0e4b720afadcb5e3d90a95254ef9bb3685cd428b
3
+ metadata.gz: 1693c61699c2fdcf64441f532c205b8be2e3b6b2be47e772c2471d671b7712b3
4
+ data.tar.gz: 1c819eee801f19b38cfbb6bdc51177c2e885aced316ea55034bb6c99a75183c5
5
5
  SHA512:
6
- metadata.gz: 0ba286e7a630413151bd63100a6b0bcb8d9d3adba5e81a3af47c3774724e18c5f78a4330f2811c1068c9a2d8b5a7c4215d27a5793491016ecd61f2660c7755f6
7
- data.tar.gz: d5b916629846e13983fd80794492bb051a0c42139e39b6584c61b21e5a504e7de8e5663f8f931f566c4cd269bef271fd10ac682d1a1bcace6ab37f310101cfce
6
+ metadata.gz: ced29a767bab571ee4c77a14d6c108510465c8424ee66249cd3343efbceb3bec2dec8e94664a2b260a4a0716ae51948c3b796ff088d0b3aab07d40ac762ec111
7
+ data.tar.gz: 6e7bf970c65500799fa0788f468885207f531c7a8de5c6f1f6be27952435994616f7dc1f10bf1ad51a233244a47d43eca553d9d73add30e8ca89afafac300d9b
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.2
1
+ 3.3.0
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- ruby "3.2.2"
3
+ ruby "3.3.0"
4
4
 
5
5
  # Specify your gem's dependencies in head_music.gemspec
6
6
  gemspec
@@ -1,5 +1,5 @@
1
1
  # Accepts the letter name count between two notes and categorizes the interval
2
- class HeadMusic::DiatonicInterval::Category
2
+ class HeadMusic::Analysis::DiatonicInterval::Category
3
3
  attr_reader :number
4
4
 
5
5
  def initialize(number)
@@ -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,5 @@
1
1
  # Encapsulate the distance methods of the interval
2
- class HeadMusic::DiatonicInterval::Size
2
+ class HeadMusic::Analysis::DiatonicInterval::Size
3
3
  attr_reader :low_pitch, :high_pitch
4
4
 
5
5
  def initialize(pitch1, pitch2)
@@ -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("data/instruments.yml", __dir__)).freeze
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::Instrument::Variant.new(key, attributes)
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("data/instrument_families.yml", __dir__)).freeze
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