head_music 5.0.0 → 6.0.1

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.
@@ -1,4 +1,4 @@
1
- class HeadMusic::Instrument::PitchConfiguration
1
+ class HeadMusic::Instrument::PitchVariant
2
2
  attr_reader :key, :attributes
3
3
 
4
4
  def initialize(key, attributes = {})
@@ -13,12 +13,12 @@ class HeadMusic::Instrument::PitchConfiguration
13
13
  HeadMusic::Spelling.get(attributes["fundamental_pitch_spelling"])
14
14
  end
15
15
 
16
- def staff_configurations
17
- @staff_configurations ||=
18
- (attributes["staff_configurations"] || {}).map do |key, list|
19
- HeadMusic::Instrument::StaffConfiguration.new(
16
+ def staff_schemes
17
+ @staff_schemes ||=
18
+ (attributes["staff_schemes"] || {}).map do |key, list|
19
+ HeadMusic::Instrument::StaffScheme.new(
20
20
  key: key,
21
- pitch_configuration: self,
21
+ pitch_variant: self,
22
22
  list: list
23
23
  )
24
24
  end
@@ -28,8 +28,8 @@ class HeadMusic::Instrument::PitchConfiguration
28
28
  key.to_s == "default"
29
29
  end
30
30
 
31
- def default_staff_configuration
32
- @default_staff_configuration ||=
33
- staff_configurations.find(&:default?) || staff_configurations.first
31
+ def default_staff_scheme
32
+ @default_staff_scheme ||=
33
+ staff_schemes.find(&:default?) || staff_schemes.first
34
34
  end
35
35
  end
@@ -1,10 +1,10 @@
1
1
  class HeadMusic::Instrument::Staff
2
2
  DEFAULT_CLEF = "treble_clef"
3
3
 
4
- attr_reader :staff_configuration, :attributes
4
+ attr_reader :staff_scheme, :attributes
5
5
 
6
- def initialize(staff_configuration, attributes)
7
- @staff_configuration = staff_configuration
6
+ def initialize(staff_scheme, attributes)
7
+ @staff_scheme = staff_scheme
8
8
  @attributes = attributes || {}
9
9
  end
10
10
 
@@ -21,7 +21,7 @@ class HeadMusic::Instrument::Staff
21
21
  end
22
22
 
23
23
  def name_key
24
- attributes["name_key"]
24
+ attributes["name_key"] || ""
25
25
  end
26
26
 
27
27
  def name
@@ -1,8 +1,8 @@
1
- class HeadMusic::Instrument::StaffConfiguration
2
- attr_reader :pitch_configuration, :key, :list
1
+ class HeadMusic::Instrument::StaffScheme
2
+ attr_reader :pitch_variant, :key, :list
3
3
 
4
- def initialize(pitch_configuration:, key:, list:)
5
- @pitch_configuration = pitch_configuration
4
+ def initialize(pitch_variant:, key:, list:)
5
+ @pitch_variant = pitch_variant
6
6
  @key = key || "default"
7
7
  @list = list
8
8
  end
@@ -9,7 +9,7 @@
9
9
  # default_clefs: the default clef or system of clefs for the instrument
10
10
  # - [treble] for instruments that use the treble clef
11
11
  # - [treble, bass] for instruments that use the grand staff
12
- # pitch_configurations:
12
+ # pitch_variants:
13
13
  # a hash of default and alternative fundamental pitches.
14
14
  # Associations:
15
15
  # family: the family of the instrument (e.g. "saxophone")
@@ -32,7 +32,7 @@ class HeadMusic::Instrument
32
32
  attr_reader(
33
33
  :name_key, :alias_name_keys,
34
34
  :family_key, :orchestra_section_key,
35
- :pitch_configurations, :classification_keys
35
+ :pitch_variants, :classification_keys
36
36
  )
37
37
 
38
38
  def ==(other)
@@ -75,16 +75,16 @@ class HeadMusic::Instrument
75
75
  default_clefs.any?
76
76
  end
77
77
 
78
- def default_pitch_configuration
79
- pitch_configurations.find(&:default?) || pitch_configurations.first
78
+ def default_pitch_variant
79
+ pitch_variants.find(&:default?) || pitch_variants.first
80
80
  end
81
81
 
82
- def default_staff_configuration
83
- default_pitch_configuration&.default_staff_configuration
82
+ def default_staff_scheme
83
+ default_pitch_variant&.default_staff_scheme
84
84
  end
85
85
 
86
86
  def default_staves
87
- default_staff_configuration&.staves || []
87
+ default_staff_scheme&.staves || []
88
88
  end
89
89
 
90
90
  def default_clefs
@@ -158,9 +158,9 @@ class HeadMusic::Instrument
158
158
  def initialize_attributes(record)
159
159
  @orchestra_section_key ||= record["orchestra_section_key"]
160
160
  @classification_keys = [@classification_keys, record["classification_keys"]].flatten.compact.uniq
161
- @pitch_configurations =
162
- (record["pitch_configurations"] || {}).map do |key, attributes|
163
- HeadMusic::Instrument::PitchConfiguration.new(key, attributes)
161
+ @pitch_variants =
162
+ (record["pitch_variants"] || {}).map do |key, attributes|
163
+ HeadMusic::Instrument::PitchVariant.new(key, attributes)
164
164
  end
165
165
  end
166
166
 
@@ -0,0 +1,30 @@
1
+ # Key signatures are enharmonic when all pitch classes in one are respellings of the pitch classes in the other.
2
+ class HeadMusic::KeySignature::EnharmonicEquivalence
3
+ attr_reader :key_signature
4
+
5
+ def self.get(key_signature)
6
+ key_signature = HeadMusic::KeySignature.get(key_signature)
7
+ @enharmonic_equivalences ||= {}
8
+ @enharmonic_equivalences[key_signature.to_s] ||= new(key_signature)
9
+ end
10
+
11
+ def initialize(key_signature)
12
+ @key_signature = HeadMusic::KeySignature.get(key_signature)
13
+ end
14
+
15
+ def enharmonic_equivalent?(other)
16
+ other = HeadMusic::KeySignature.get(other)
17
+
18
+ p key_signature.pitch_classes.map(&:to_i).sort
19
+ p other.pitch_classes.map(&:to_i).sort
20
+ p key_signature.alterations.map(&:to_s).sort
21
+ p other.alterations.map(&:to_s).sort
22
+ key_signature.pitch_classes.map(&:to_i).sort == other.pitch_classes.map(&:to_i).sort &&
23
+ key_signature.alterations.map(&:to_s).sort != other.alterations.map(&:to_s).sort
24
+ end
25
+
26
+ # alias_method :enharmonic?, :enharmonic_equivalent?
27
+ # alias_method :equivalent?, :enharmonic_equivalent?
28
+
29
+ private_class_method :new
30
+ end
@@ -21,7 +21,7 @@ class HeadMusic::KeySignature
21
21
 
22
22
  delegate :pitch_class, to: :tonic_spelling, prefix: :tonic
23
23
  delegate :to_s, to: :name
24
- delegate :pitches, to: :scale
24
+ delegate :pitches, :pitch_classes, to: :scale
25
25
 
26
26
  def initialize(tonic_spelling, scale_type = nil)
27
27
  @tonic_spelling = HeadMusic::Spelling.get(tonic_spelling)
@@ -67,19 +67,23 @@ class HeadMusic::KeySignature
67
67
  flats.length + double_flats.length * 2
68
68
  end
69
69
 
70
- def signs
71
- flats.any? ? flats : sharps
70
+ def num_alterations
71
+ num_sharps + num_flats
72
72
  end
73
73
 
74
- alias_method :sharps_and_flats, :signs
75
- alias_method :accidentals, :signs
74
+ def alterations
75
+ flats.any? ? (double_flats + flats) : (double_sharps + sharps)
76
+ end
77
+
78
+ alias_method :sharps_and_flats, :alterations
79
+ alias_method :accidentals, :alterations
76
80
 
77
81
  def name
78
82
  [tonic_spelling, scale_type].join(" ")
79
83
  end
80
84
 
81
85
  def ==(other)
82
- signs == self.class.get(other).signs
86
+ alterations == self.class.get(other).alterations
83
87
  end
84
88
 
85
89
  def to_s
@@ -93,38 +97,12 @@ class HeadMusic::KeySignature
93
97
  end
94
98
 
95
99
  def enharmonic_equivalent?(other)
96
- other = KeySignature.get(other)
97
- enharmonic_equivalence.equivalent?(other)
100
+ enharmonic_equivalence.enharmonic_equivalent?(other)
98
101
  end
99
102
 
100
103
  private
101
104
 
102
105
  def enharmonic_equivalence
103
- @enharmonic_equivalence ||= EnharmonicEquivalence.get(self)
104
- end
105
-
106
- # Key signatures are enharmonic when all pitch classes in one are respellings of the pitch classes in the other.
107
- class EnharmonicEquivalence
108
- def self.get(key_signature)
109
- key_signature = HeadMusic::KeySignature.get(key_signature)
110
- @enharmonic_equivalences ||= {}
111
- @enharmonic_equivalences[key_signature.to_s] ||= new(key_signature)
112
- end
113
-
114
- attr_reader :key_signature
115
-
116
- def initialize(key_signature)
117
- @key_signature = HeadMusic::KeySignature.get(key_signature)
118
- end
119
-
120
- def enharmonic_equivalent?(other)
121
- other = HeadMusic::KeySignature.get(other)
122
- (key_signature.signs | other.signs).map(&:to_s).uniq.length == 12
123
- end
124
-
125
- alias_method :enharmonic?, :enharmonic_equivalent?
126
- alias_method :equivalent?, :enharmonic_equivalent?
127
-
128
- private_class_method :new
106
+ @enharmonic_equivalence ||= HeadMusic::KeySignature::EnharmonicEquivalence.get(self)
129
107
  end
130
108
  end
@@ -48,7 +48,9 @@ class HeadMusic::Motion
48
48
  end
49
49
 
50
50
  def to_s
51
- "#{contrapuntal_motion} motion from #{first_harmonic_interval} to #{second_harmonic_interval}"
51
+ return "repetition of a #{second_harmonic_interval}" unless contrapuntal_motion != :repetition
52
+
53
+ "#{contrapuntal_motion} motion from a #{first_harmonic_interval} to a #{second_harmonic_interval}"
52
54
  end
53
55
 
54
56
  private
@@ -10,13 +10,10 @@ class HeadMusic::PitchClassSet
10
10
  @pitch_classes = identifiers.map { |identifier| HeadMusic::PitchClass.get(identifier) }.uniq.sort
11
11
  end
12
12
 
13
- def inspect
14
- pitch_classes.map(&:to_s).join(" ")
15
- end
16
-
17
13
  def to_s
18
- pitch_classes.map(&:to_s).join(" ")
14
+ pitch_classes.map(&:to_i).inspect
19
15
  end
16
+ alias_method :inspect, :to_s
20
17
 
21
18
  def ==(other)
22
19
  pitch_classes == other.pitch_classes
@@ -28,6 +28,10 @@ class HeadMusic::Scale
28
28
  @pitches[direction][octaves] ||= determine_scale_pitches(direction, octaves)
29
29
  end
30
30
 
31
+ def pitch_classes
32
+ pitches.map(&:pitch_class).uniq
33
+ end
34
+
31
35
  def spellings(direction: :ascending, octaves: 1)
32
36
  pitches(direction: direction, octaves: octaves).map(&:spelling).map(&:to_s)
33
37
  end
@@ -1,3 +1,3 @@
1
1
  module HeadMusic
2
- VERSION = "5.0.0"
2
+ VERSION = "6.0.1"
3
3
  end
data/lib/head_music.rb CHANGED
@@ -41,11 +41,12 @@ require "head_music/diatonic_interval"
41
41
  require "head_music/harmonic_interval"
42
42
  require "head_music/instrument_family"
43
43
  require "head_music/instrument"
44
- require "head_music/instrument/pitch_configuration"
45
- require "head_music/instrument/staff_configuration"
44
+ require "head_music/instrument/pitch_variant"
45
+ require "head_music/instrument/staff_scheme"
46
46
  require "head_music/instrument/staff"
47
47
  require "head_music/interval_cycle"
48
48
  require "head_music/key_signature"
49
+ require "head_music/key_signature/enharmonic_equivalence"
49
50
  require "head_music/letter_name"
50
51
  require "head_music/melodic_interval"
51
52
  require "head_music/meter"
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: 5.0.0
4
+ version: 6.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Head
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-27 00:00:00.000000000 Z
11
+ date: 2023-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -138,12 +138,13 @@ files:
138
138
  - lib/head_music/diatonic_interval.rb
139
139
  - lib/head_music/harmonic_interval.rb
140
140
  - lib/head_music/instrument.rb
141
- - lib/head_music/instrument/pitch_configuration.rb
141
+ - lib/head_music/instrument/pitch_variant.rb
142
142
  - lib/head_music/instrument/staff.rb
143
- - lib/head_music/instrument/staff_configuration.rb
143
+ - lib/head_music/instrument/staff_scheme.rb
144
144
  - lib/head_music/instrument_family.rb
145
145
  - lib/head_music/interval_cycle.rb
146
146
  - lib/head_music/key_signature.rb
147
+ - lib/head_music/key_signature/enharmonic_equivalence.rb
147
148
  - lib/head_music/letter_name.rb
148
149
  - lib/head_music/locales/de.yml
149
150
  - lib/head_music/locales/en.yml