head_music 5.0.0 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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