head_music 4.0.1 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -2
  3. data/Rakefile +0 -2
  4. data/bin/console +0 -2
  5. data/head_music.gemspec +0 -2
  6. data/lib/head_music/{sign.rb → alteration.rb} +13 -15
  7. data/lib/head_music/chromatic_interval.rb +0 -2
  8. data/lib/head_music/circle.rb +0 -2
  9. data/lib/head_music/clef.rb +0 -2
  10. data/lib/head_music/consonance.rb +0 -2
  11. data/lib/head_music/content/bar.rb +0 -2
  12. data/lib/head_music/content/composition.rb +0 -2
  13. data/lib/head_music/content/note.rb +0 -2
  14. data/lib/head_music/content/placement.rb +0 -2
  15. data/lib/head_music/content/position.rb +0 -2
  16. data/lib/head_music/content/rhythmic_value.rb +0 -2
  17. data/lib/head_music/content/voice.rb +0 -2
  18. data/lib/head_music/data/instrument_families.yml +1 -1
  19. data/lib/head_music/data/instruments.yml +570 -522
  20. data/lib/head_music/diatonic_interval.rb +0 -2
  21. data/lib/head_music/harmonic_interval.rb +0 -2
  22. data/lib/head_music/instrument/pitch_configuration.rb +35 -0
  23. data/lib/head_music/instrument/staff.rb +30 -0
  24. data/lib/head_music/instrument/staff_configuration.rb +19 -0
  25. data/lib/head_music/instrument.rb +31 -19
  26. data/lib/head_music/interval_cycle.rb +0 -2
  27. data/lib/head_music/key_signature.rb +0 -2
  28. data/lib/head_music/letter_name.rb +0 -2
  29. data/lib/head_music/locales/en.yml +2 -1
  30. data/lib/head_music/melodic_interval.rb +0 -2
  31. data/lib/head_music/meter.rb +0 -2
  32. data/lib/head_music/motion.rb +0 -2
  33. data/lib/head_music/musical_symbol.rb +0 -2
  34. data/lib/head_music/named.rb +0 -2
  35. data/lib/head_music/pitch/enharmonic_equivalence.rb +0 -2
  36. data/lib/head_music/pitch/octave_equivalence.rb +0 -2
  37. data/lib/head_music/pitch.rb +7 -9
  38. data/lib/head_music/pitch_class.rb +0 -2
  39. data/lib/head_music/pitch_class_set.rb +0 -2
  40. data/lib/head_music/pitch_set.rb +0 -2
  41. data/lib/head_music/quality.rb +0 -2
  42. data/lib/head_music/reference_pitch.rb +0 -2
  43. data/lib/head_music/register.rb +0 -2
  44. data/lib/head_music/rhythm.rb +0 -2
  45. data/lib/head_music/rhythmic_unit.rb +0 -2
  46. data/lib/head_music/scale.rb +0 -2
  47. data/lib/head_music/scale_degree.rb +8 -10
  48. data/lib/head_music/scale_type.rb +0 -2
  49. data/lib/head_music/solmization.rb +0 -2
  50. data/lib/head_music/sonority.rb +0 -2
  51. data/lib/head_music/spelling.rb +18 -20
  52. data/lib/head_music/staff.rb +0 -2
  53. data/lib/head_music/style/analysis.rb +0 -2
  54. data/lib/head_music/style/annotation.rb +0 -2
  55. data/lib/head_music/style/guidelines/always_move.rb +0 -2
  56. data/lib/head_music/style/guidelines/approach_perfection_contrarily.rb +0 -2
  57. data/lib/head_music/style/guidelines/at_least_eight_notes.rb +0 -2
  58. data/lib/head_music/style/guidelines/avoid_crossing_voices.rb +0 -2
  59. data/lib/head_music/style/guidelines/avoid_overlapping_voices.rb +0 -2
  60. data/lib/head_music/style/guidelines/consonant_climax.rb +0 -2
  61. data/lib/head_music/style/guidelines/consonant_downbeats.rb +0 -2
  62. data/lib/head_music/style/guidelines/diatonic.rb +1 -3
  63. data/lib/head_music/style/guidelines/direction_changes.rb +0 -2
  64. data/lib/head_music/style/guidelines/end_on_perfect_consonance.rb +0 -2
  65. data/lib/head_music/style/guidelines/end_on_tonic.rb +0 -2
  66. data/lib/head_music/style/guidelines/frequent_direction_changes.rb +0 -2
  67. data/lib/head_music/style/guidelines/limit_octave_leaps.rb +0 -2
  68. data/lib/head_music/style/guidelines/moderate_direction_changes.rb +0 -2
  69. data/lib/head_music/style/guidelines/mostly_conjunct.rb +0 -2
  70. data/lib/head_music/style/guidelines/no_rests.rb +0 -2
  71. data/lib/head_music/style/guidelines/no_unisons_in_middle.rb +0 -2
  72. data/lib/head_music/style/guidelines/notes_same_length.rb +0 -2
  73. data/lib/head_music/style/guidelines/one_to_one.rb +0 -2
  74. data/lib/head_music/style/guidelines/prefer_contrary_motion.rb +0 -2
  75. data/lib/head_music/style/guidelines/prefer_imperfect.rb +0 -2
  76. data/lib/head_music/style/guidelines/prepare_octave_leaps.rb +0 -2
  77. data/lib/head_music/style/guidelines/recover_large_leaps.rb +0 -2
  78. data/lib/head_music/style/guidelines/singable_intervals.rb +0 -2
  79. data/lib/head_music/style/guidelines/singable_range.rb +0 -2
  80. data/lib/head_music/style/guidelines/single_large_leaps.rb +0 -2
  81. data/lib/head_music/style/guidelines/start_on_perfect_consonance.rb +0 -2
  82. data/lib/head_music/style/guidelines/start_on_tonic.rb +0 -2
  83. data/lib/head_music/style/guidelines/step_down_to_final_note.rb +0 -2
  84. data/lib/head_music/style/guidelines/step_out_of_unison.rb +0 -2
  85. data/lib/head_music/style/guidelines/step_to_final_note.rb +0 -2
  86. data/lib/head_music/style/guidelines/step_up_to_final_note.rb +0 -2
  87. data/lib/head_music/style/guidelines/up_to_fourteen_notes.rb +0 -2
  88. data/lib/head_music/style/guides/first_species_harmony.rb +0 -2
  89. data/lib/head_music/style/guides/first_species_melody.rb +0 -2
  90. data/lib/head_music/style/guides/fux_cantus_firmus.rb +0 -2
  91. data/lib/head_music/style/guides/modern_cantus_firmus.rb +0 -2
  92. data/lib/head_music/style/mark.rb +0 -2
  93. data/lib/head_music/tuning.rb +0 -2
  94. data/lib/head_music/utilities/hash_key.rb +0 -2
  95. data/lib/head_music/version.rb +1 -3
  96. data/lib/head_music.rb +4 -3
  97. metadata +6 -3
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A diatonic interval is the distance between two spelled pitches.
4
2
  class HeadMusic::DiatonicInterval
5
3
  include Comparable
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A harmonic interval is the diatonic interval between two notes sounding together.
4
2
  class HeadMusic::HarmonicInterval
5
3
  attr_reader :voice1, :voice2, :position
@@ -0,0 +1,35 @@
1
+ class HeadMusic::Instrument::PitchConfiguration
2
+ attr_reader :key, :attributes
3
+
4
+ def initialize(key, attributes = {})
5
+ @key = key.to_s.to_sym
6
+ @attributes = attributes
7
+ end
8
+
9
+ def fundamental_pitch_spelling
10
+ return unless attributes["fundamental_pitch_spelling"].to_s != ""
11
+
12
+ @fundamental_pitch_spelling ||=
13
+ HeadMusic::Spelling.get(attributes["fundamental_pitch_spelling"])
14
+ end
15
+
16
+ def staff_configurations
17
+ @staff_configurations ||=
18
+ (attributes["staff_configurations"] || {}).map do |key, list|
19
+ HeadMusic::Instrument::StaffConfiguration.new(
20
+ key: key,
21
+ pitch_configuration: self,
22
+ list: list
23
+ )
24
+ end
25
+ end
26
+
27
+ def default?
28
+ key.to_s == "default"
29
+ end
30
+
31
+ def default_staff_configuration
32
+ @default_staff_configuration ||=
33
+ staff_configurations.find(&:default?) || staff_configurations.first
34
+ end
35
+ end
@@ -0,0 +1,30 @@
1
+ class HeadMusic::Instrument::Staff
2
+ DEFAULT_CLEF = "treble_clef"
3
+
4
+ attr_reader :staff_configuration, :attributes
5
+
6
+ def initialize(staff_configuration, attributes)
7
+ @staff_configuration = staff_configuration
8
+ @attributes = attributes || {}
9
+ end
10
+
11
+ def clef
12
+ HeadMusic::Clef.get(smart_clef_key)
13
+ end
14
+
15
+ def smart_clef_key
16
+ "#{attributes["clef"]}_clef".gsub(/_clef_clef$/, "_clef")
17
+ end
18
+
19
+ def sounding_transposition
20
+ attributes["sounding_transposition"] || 0
21
+ end
22
+
23
+ def name_key
24
+ attributes["name_key"]
25
+ end
26
+
27
+ def name
28
+ name_key.to_s.tr("_", " ")
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ class HeadMusic::Instrument::StaffConfiguration
2
+ attr_reader :pitch_configuration, :key, :list
3
+
4
+ def initialize(pitch_configuration:, key:, list:)
5
+ @pitch_configuration = pitch_configuration
6
+ @key = key || "default"
7
+ @list = list
8
+ end
9
+
10
+ def default?
11
+ key.to_s == "default"
12
+ end
13
+
14
+ def staves
15
+ @staves ||= list.map do |attributes|
16
+ HeadMusic::Instrument::Staff.new(self, attributes)
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A musical instrument.
4
2
  # An instrument object can be assigned to a staff object.
5
3
  # Attributes:
@@ -8,14 +6,11 @@
8
6
  # orchestra_section_key: the section of the orchestra (e.g. "strings")
9
7
  # family_key: the key for the family of the instrument (e.g. "saxophone")
10
8
  # classification_keys: an array of classification_keys
11
- # transposition: the number of semitones between the written and the sounding pitch (optional, default: 0)
12
9
  # default_clefs: the default clef or system of clefs for the instrument
13
10
  # - [treble] for instruments that use the treble clef
14
11
  # - [treble, bass] for instruments that use the grand staff
15
- # notation:
16
- # a hash of default and alternative notation systems,
17
- # each with a staff's key with an array of hashes
18
- # including clef and transposition (where applicable)
12
+ # pitch_configurations:
13
+ # a hash of default and alternative fundamental pitches.
19
14
  # Associations:
20
15
  # family: the family of the instrument (e.g. "saxophone")
21
16
  # orchestra_section: the section of the orchestra (e.g. "strings")
@@ -25,8 +20,7 @@ class HeadMusic::Instrument
25
20
  INSTRUMENTS = YAML.load_file(File.expand_path("data/instruments.yml", __dir__)).freeze
26
21
 
27
22
  def self.get(name)
28
- result = get_by_name(name) || get_by_name(key_for_name(name)) || get_by_alias(name)
29
- result || new(name)
23
+ get_by_name(name)
30
24
  end
31
25
 
32
26
  def self.all
@@ -38,9 +32,7 @@ class HeadMusic::Instrument
38
32
  attr_reader(
39
33
  :name_key, :alias_name_keys,
40
34
  :family_key, :orchestra_section_key,
41
- :notation, :classification_keys,
42
- :fundamental_pitch_spelling, :transposition,
43
- :default_staves, :default_clefs
35
+ :pitch_configurations, :classification_keys
44
36
  )
45
37
 
46
38
  def ==(other)
@@ -61,12 +53,12 @@ class HeadMusic::Instrument
61
53
 
62
54
  # Returns true if the instrument sounds at a different pitch than written.
63
55
  def transposing?
64
- transposition != 0
56
+ default_sounding_transposition != 0
65
57
  end
66
58
 
67
59
  # Returns true if the instrument sounds at a different register than written.
68
60
  def transposing_at_the_octave?
69
- transposing? && transposition % 12 == 0
61
+ transposing? && default_sounding_transposition % 12 == 0
70
62
  end
71
63
 
72
64
  def single_staff?
@@ -78,11 +70,31 @@ class HeadMusic::Instrument
78
70
  end
79
71
 
80
72
  def pitched?
81
- return false if default_clefs.compact.uniq == ["percussion"]
73
+ return false if default_clefs.compact.uniq == [HeadMusic::Clef.get("neutral_clef")]
82
74
 
83
75
  default_clefs.any?
84
76
  end
85
77
 
78
+ def default_pitch_configuration
79
+ pitch_configurations.find(&:default?) || pitch_configurations.first
80
+ end
81
+
82
+ def default_staff_configuration
83
+ default_pitch_configuration&.default_staff_configuration
84
+ end
85
+
86
+ def default_staves
87
+ default_staff_configuration&.staves || []
88
+ end
89
+
90
+ def default_clefs
91
+ default_staves&.map(&:clef) || []
92
+ end
93
+
94
+ def default_sounding_transposition
95
+ default_staves&.first&.sounding_transposition || 0
96
+ end
97
+
86
98
  private_class_method :new
87
99
 
88
100
  private
@@ -146,10 +158,10 @@ class HeadMusic::Instrument
146
158
  def initialize_attributes(record)
147
159
  @orchestra_section_key ||= record["orchestra_section_key"]
148
160
  @classification_keys = [@classification_keys, record["classification_keys"]].flatten.compact.uniq
149
- @fundamental_pitch_spelling = record["fundamental_pitch_spelling"]
150
- @default_staves = (record.dig("notation", "default", "staves") || [])
151
- @default_clefs = @default_staves.map { |staff| staff["clef"] }
152
- @transposition = @default_staves&.first&.[]("transposition") || 0
161
+ @pitch_configurations =
162
+ (record["pitch_configurations"] || {}).map do |key, attributes|
163
+ HeadMusic::Instrument::PitchConfiguration.new(key, attributes)
164
+ end
153
165
  end
154
166
 
155
167
  def inferred_name
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # An Interval Cycle is a collection of pitch classes created from a sequence of the same interval class.
4
2
  class HeadMusic::IntervalCycle
5
3
  attr_reader :interval, :starting_pitch
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Represents a key signature.
4
2
  # In French, sharps and flats in the key signature are called "altérations".
5
3
  class HeadMusic::KeySignature
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Music has seven lette names that are used to identify pitches and pitch classes.
4
2
  class HeadMusic::LetterName
5
3
  NAMES = %w[C D E F G A B].freeze
@@ -103,6 +103,7 @@ en:
103
103
  instrument_voices:
104
104
  piccolo: piccolo
105
105
  soprano: soprano
106
+ mezzo_soprano: mezzo-soprano
106
107
  alto: alto
107
108
  tenor: tenor
108
109
  baritone: baritone
@@ -252,6 +253,7 @@ en:
252
253
  sydney_symphony_orchestra: Sydney Symphony Orchestra
253
254
  verdi: Verdi tuning
254
255
  rudiments:
256
+ alteration: alteration
255
257
  chromatic_interval: chromatic interval
256
258
  circle: circle
257
259
  clef: clef
@@ -279,7 +281,6 @@ en:
279
281
  scale: scale
280
282
  scale_degree: scale degree
281
283
  scale_type: scale type
282
- sign: sign
283
284
  solmization: solmization
284
285
  sonority: sonority
285
286
  spelling: spelling
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A melodic interval is the distance between one note and the next.
4
2
  class HeadMusic::MelodicInterval
5
3
  attr_reader :first_note, :second_note
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Meter is the rhythmic size of a measure, such as 4/4 or 6/8
4
2
  class HeadMusic::Meter
5
3
  attr_reader :top_number, :bottom_number
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Motion defines the relative pitch direction of the upper and lower voices of subsequence intervals.
4
2
  class HeadMusic::Motion
5
3
  attr_reader :first_harmonic_interval, :second_harmonic_interval
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A symbol is a mark or sign that signifies a particular rudiment of music
4
2
  class HeadMusic::MusicalSymbol
5
3
  attr_reader :ascii, :unicode, :html_entity
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # NameRudiment is a module to be included in classes whose instances may be identified by name.
4
2
  module HeadMusic::Named
5
3
  delegate :to_s, to: :name
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # An enharmonic equivalent pitch is the same frequency spelled differently, such as D# and Eb.
4
2
  class HeadMusic::Pitch::EnharmonicEquivalence
5
3
  def self.get(pitch)
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Octave equivalence is the functional equivalence of pitches with the same spelling separated by one or more octaves.
4
2
  class HeadMusic::Pitch::OctaveEquivalence
5
3
  def self.get(pitch)
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A pitch is a named frequency represented by a spelling and a register.
4
2
  class HeadMusic::Pitch
5
3
  include Comparable
@@ -8,11 +6,11 @@ class HeadMusic::Pitch
8
6
 
9
7
  delegate :letter_name, to: :spelling
10
8
  delegate :series_ascending, :series_descending, to: :letter_name, prefix: true
11
- delegate :sign, :sharp?, :flat?, to: :spelling
9
+ delegate :alteration, :sharp?, :flat?, to: :spelling
12
10
  delegate :pitch_class, to: :spelling
13
11
  delegate :number, to: :pitch_class, prefix: true
14
12
  delegate :pitch_class_number, to: :natural, prefix: true
15
- delegate :semitones, to: :sign, prefix: true, allow_nil: true
13
+ delegate :semitones, to: :alteration, prefix: true, allow_nil: true
16
14
  delegate :steps_to, to: :letter_name, prefix: true
17
15
 
18
16
  delegate :smallest_interval_to, to: :pitch_class
@@ -62,9 +60,9 @@ class HeadMusic::Pitch
62
60
  def self.from_number_and_letter(number, letter_name)
63
61
  letter_name = HeadMusic::LetterName.get(letter_name)
64
62
  natural_letter_pitch = natural_letter_pitch(number, letter_name)
65
- sign_interval = natural_letter_pitch.smallest_interval_to(HeadMusic::PitchClass.get(number))
66
- sign = HeadMusic::Sign.by(:semitones, sign_interval) if sign_interval != 0
67
- spelling = HeadMusic::Spelling.fetch_or_create(letter_name, sign)
63
+ alteration_interval = natural_letter_pitch.smallest_interval_to(HeadMusic::PitchClass.get(number))
64
+ alteration = HeadMusic::Alteration.by(:semitones, alteration_interval) if alteration_interval != 0
65
+ spelling = HeadMusic::Spelling.fetch_or_create(letter_name, alteration)
68
66
  fetch_or_create(spelling, natural_letter_pitch.register)
69
67
  end
70
68
 
@@ -94,7 +92,7 @@ class HeadMusic::Pitch
94
92
  end
95
93
 
96
94
  def midi_note_number
97
- (register + 1) * 12 + letter_name.pitch_class.to_i + sign_semitones.to_i
95
+ (register + 1) * 12 + letter_name.pitch_class.to_i + alteration_semitones.to_i
98
96
  end
99
97
 
100
98
  alias_method :midi, :midi_note_number
@@ -113,7 +111,7 @@ class HeadMusic::Pitch
113
111
  end
114
112
 
115
113
  def natural
116
- HeadMusic::Pitch.get(to_s.gsub(HeadMusic::Sign.matcher, ""))
114
+ HeadMusic::Pitch.get(to_s.gsub(HeadMusic::Alteration.matcher, ""))
117
115
  end
118
116
 
119
117
  def +(other)
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A pitch class is a set of pitches separated by octaves.
4
2
  class HeadMusic::PitchClass
5
3
  include Comparable
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A PitchClassSet represents a pitch-class set or pitch collection.
4
2
  # See also: PitchSet, PitchClass
5
3
  class HeadMusic::PitchClassSet
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A PitchSet is a collection of one or more pitches.
4
2
  # See also: PitchClassSet
5
3
  class HeadMusic::PitchSet
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A quality is a categorization of an interval.
4
2
  class HeadMusic::Quality
5
3
  SHORTHAND = {
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A reference pitch has a pitch and a frequency
4
2
  # With no arguments, it assumes that A4 = 440.0 Hz
5
3
  class HeadMusic::ReferencePitch
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # The register is a numeric octave identifier used in scientific pitch notation.
4
2
  #
5
3
  # A pitch is a spelling plus a register. For example, C4 is middle C and C5 is the C one octave higher.
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  module HeadMusic::Rhythm
4
2
  PPQN = PULSES_PER_QUARTER_NOTE = 960
5
3
  end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A rhythmic unit is a rudiment of duration consisting of doublings and divisions of a whole note.
4
2
  class HeadMusic::RhythmicUnit
5
3
  include HeadMusic::Named
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A scale contains ordered pitches starting at a tonal center.
4
2
  class HeadMusic::Scale
5
3
  SCALE_REGEX = /^[A-G][#b]?\s+\w+$/
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A scale degree is a number indicating the ordinality of the spelling in the key signature.
4
2
  # TODO: Rewrite to accept a tonal_center and a scale type.
5
3
  class HeadMusic::ScaleDegree
@@ -21,20 +19,20 @@ class HeadMusic::ScaleDegree
21
19
  scale.letter_name_series_ascending.index(spelling.letter_name.to_s) + 1
22
20
  end
23
21
 
24
- def sign
25
- sign_semitones = spelling.sign&.semitones || 0
26
- usual_sign_semitones = scale_degree_usual_spelling.sign&.semitones || 0
27
- delta = sign_semitones - usual_sign_semitones
28
- HeadMusic::Sign.by(:semitones, delta) if delta != 0
22
+ def alteration
23
+ alteration_semitones = spelling.alteration&.semitones || 0
24
+ usual_sign_semitones = scale_degree_usual_spelling.alteration&.semitones || 0
25
+ delta = alteration_semitones - usual_sign_semitones
26
+ HeadMusic::Alteration.by(:semitones, delta) if delta != 0
29
27
  end
30
28
 
31
29
  def to_s
32
- "#{sign}#{degree}"
30
+ "#{alteration}#{degree}"
33
31
  end
34
32
 
35
33
  def <=>(other)
36
34
  if other.is_a?(HeadMusic::ScaleDegree)
37
- [degree, sign.semitones] <=> [other.degree, other.sign.semitones]
35
+ [degree, alteration.semitones] <=> [other.degree, other.alteration.semitones]
38
36
  else
39
37
  to_s <=> other.to_s
40
38
  end
@@ -44,7 +42,7 @@ class HeadMusic::ScaleDegree
44
42
  return unless scale_type.diatonic?
45
43
 
46
44
  NAME_FOR_DIATONIC_DEGREE[degree] ||
47
- ((scale_type.intervals.last == 1 || sign == "#") ? "leading tone" : "subtonic")
45
+ ((scale_type.intervals.last == 1 || alteration == "#") ? "leading tone" : "subtonic")
48
46
  end
49
47
 
50
48
  private
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A ScaleType represents a particular scale pattern, such as major, lydian, or minor pentatonic.
4
2
  class HeadMusic::ScaleType
5
3
  H = 1 # whole step
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A scale degree is a number indicating the ordinality of the spelling in the key signature.
4
2
  # TODO: Rewrite to accept a tonal_center and a scale type.
5
3
  class HeadMusic::Solmization
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A Sonority describes a set of pitch class intervalic relationships.
4
2
  # For example, a minor triad, or a major-minor seventh chord.
5
3
  # The Sonority class is a factory for returning one of its subclasses.
@@ -1,18 +1,16 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Represents the spelling of a pitch, such as C# or Db.
4
- # Composite of a LetterName and an optional Sign.
2
+ # Composite of a LetterName and an optional Alteration.
5
3
  # Does not include the octave. See Pitch for that.
6
4
  class HeadMusic::Spelling
7
- MATCHER = /^\s*([A-G])(#{HeadMusic::Sign.matcher}?)(-?\d+)?\s*$/i
5
+ MATCHER = /^\s*([A-G])(#{HeadMusic::Alteration.matcher}?)(-?\d+)?\s*$/i
8
6
 
9
- attr_reader :pitch_class, :letter_name, :sign
7
+ attr_reader :pitch_class, :letter_name, :alteration
10
8
 
11
9
  delegate :number, to: :pitch_class, prefix: true
12
10
  delegate :to_i, to: :pitch_class_number
13
11
  delegate :series_ascending, :series_descending, to: :letter_name, prefix: true
14
12
  delegate :enharmonic?, to: :enharmonic_equivalence
15
- delegate :sharp?, :flat?, :double_sharp?, :double_flat?, to: :sign, allow_nil: true
13
+ delegate :sharp?, :flat?, :double_sharp?, :double_flat?, to: :alteration, allow_nil: true
16
14
 
17
15
  def self.get(identifier)
18
16
  return identifier if identifier.is_a?(HeadMusic::Spelling)
@@ -31,8 +29,8 @@ class HeadMusic::Spelling
31
29
  letter_name = HeadMusic::LetterName.get(letter_name)
32
30
  return nil unless letter_name
33
31
 
34
- sign = HeadMusic::Sign.get(sign_string)
35
- fetch_or_create(letter_name, sign)
32
+ alteration = HeadMusic::Alteration.get(sign_string)
33
+ fetch_or_create(letter_name, alteration)
36
34
  end
37
35
 
38
36
  def self.from_number(number)
@@ -46,26 +44,26 @@ class HeadMusic::Spelling
46
44
  def self.from_number_and_letter(number, letter_name)
47
45
  letter_name = HeadMusic::LetterName.get(letter_name)
48
46
  natural_letter_pitch_class = letter_name.pitch_class
49
- sign_interval = natural_letter_pitch_class.smallest_interval_to(HeadMusic::PitchClass.get(number))
50
- sign = HeadMusic::Sign.by(:semitones, sign_interval) if sign_interval != 0
51
- fetch_or_create(letter_name, sign)
47
+ alteration_interval = natural_letter_pitch_class.smallest_interval_to(HeadMusic::PitchClass.get(number))
48
+ alteration = HeadMusic::Alteration.by(:semitones, alteration_interval) if alteration_interval != 0
49
+ fetch_or_create(letter_name, alteration)
52
50
  end
53
51
 
54
- def self.fetch_or_create(letter_name, sign)
52
+ def self.fetch_or_create(letter_name, alteration)
55
53
  @spellings ||= {}
56
- hash_key = [letter_name, sign].join
57
- @spellings[hash_key] ||= new(letter_name, sign)
54
+ hash_key = [letter_name, alteration].join
55
+ @spellings[hash_key] ||= new(letter_name, alteration)
58
56
  end
59
57
 
60
- def initialize(letter_name, sign = nil)
58
+ def initialize(letter_name, alteration = nil)
61
59
  @letter_name = HeadMusic::LetterName.get(letter_name.to_s)
62
- @sign = HeadMusic::Sign.get(sign)
63
- sign_semitones = @sign ? @sign.semitones : 0
64
- @pitch_class = HeadMusic::PitchClass.get(letter_name.pitch_class + sign_semitones)
60
+ @alteration = HeadMusic::Alteration.get(alteration)
61
+ alteration_semitones = @alteration ? @alteration.semitones : 0
62
+ @pitch_class = HeadMusic::PitchClass.get(letter_name.pitch_class + alteration_semitones)
65
63
  end
66
64
 
67
65
  def name
68
- [letter_name, sign].join
66
+ [letter_name, alteration].join
69
67
  end
70
68
 
71
69
  def to_s
@@ -82,7 +80,7 @@ class HeadMusic::Spelling
82
80
  end
83
81
 
84
82
  def natural?
85
- !sign || sign.natural?
83
+ !alteration || alteration.natural?
86
84
  end
87
85
 
88
86
  private_class_method :new
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A staff is a set of lines and spaces that provides context for a pitch
4
2
  class HeadMusic::Staff
5
3
  DEFAULT_LINE_COUNT = 5
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # A module for style analysis and guidelines.
4
2
  module HeadMusic::Style; end
5
3
 
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # An Annotation encapsulates an issue with or comment on a voice
4
2
  class HeadMusic::Style::Annotation
5
3
  MESSAGE = "Write music."
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Module for style guidelines.
4
2
  module HeadMusic::Style::Guidelines; end
5
3
 
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Module for style guidelines.
4
2
  module HeadMusic::Style::Guidelines; end
5
3
 
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Module for style guidelines.
4
2
  module HeadMusic::Style::Guidelines; end
5
3
 
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Module for style guidelines.
4
2
  module HeadMusic::Style::Guidelines; end
5
3
 
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Module for style guidelines.
4
2
  module HeadMusic::Style::Guidelines; end
5
3
 
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Module for style guidelines.
4
2
  module HeadMusic::Style::Guidelines; end
5
3
 
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Module for style guidelines.
4
2
  module HeadMusic::Style::Guidelines; end
5
3
 
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Module for style guidelines.
4
2
  module HeadMusic::Style::Guidelines; end
5
3
 
@@ -17,7 +15,7 @@ class HeadMusic::Style::Guidelines::Diatonic < HeadMusic::Style::Annotation
17
15
  notes_not_in_key.reject do |note|
18
16
  penultimate_note &&
19
17
  note == penultimate_note &&
20
- HeadMusic::ScaleDegree.new(key_signature, note.pitch.spelling).sign == "#"
18
+ HeadMusic::ScaleDegree.new(key_signature, note.pitch.spelling).alteration == "#"
21
19
  end
22
20
  end
23
21
 
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # Module for style guidelines.
4
2
  module HeadMusic::Style::Guidelines; end
5
3