head_music 1.0.0 → 2.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.
- checksums.yaml +4 -4
- data/TODO.md +106 -1
- data/lib/head_music/chromatic_interval.rb +16 -3
- data/lib/head_music/data/clefs.yml +3 -1
- data/lib/head_music/data/instrument_families.yml +229 -0
- data/lib/head_music/data/instruments.yml +835 -116
- data/lib/head_music/instrument.rb +90 -10
- data/lib/head_music/instrument_family.rb +69 -0
- data/lib/head_music/locales/de.yml +10 -3
- data/lib/head_music/locales/en.yml +27 -8
- data/lib/head_music/locales/es.yml +9 -2
- data/lib/head_music/locales/fr.yml +8 -1
- data/lib/head_music/locales/it.yml +10 -3
- data/lib/head_music/locales/ru.yml +9 -2
- data/lib/head_music/staff.rb +4 -1
- data/lib/head_music/version.rb +1 -1
- data/lib/head_music.rb +1 -1
- metadata +5 -4
- data/lib/head_music/grand_staff.rb +0 -56
@@ -1,23 +1,47 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
3
|
+
# A musical instrument.
|
4
|
+
# An instrument object can be assigned to a staff object.
|
5
|
+
# Attributes:
|
6
|
+
# name_key: the name of the instrument
|
7
|
+
# alias_name_keys: an array of alternative names for the instrument
|
8
|
+
# orchestra_section_key: the section of the orchestra (e.g. "strings")
|
9
|
+
# family_key: the key for the family of the instrument (e.g. "saxophone")
|
10
|
+
# classification_keys: an array of classification_keys
|
11
|
+
# transposition: the number of semitones between the written and the sounding pitch (optional, default: 0)
|
12
|
+
# default_clefs: the default clef or system of clefs for the instrument
|
13
|
+
# - [treble] for instruments that use the treble clef
|
14
|
+
# - [treble, bass] for instruments that use the grand staff
|
15
|
+
# notation:
|
16
|
+
# a hash of default and alternative notation systems,
|
17
|
+
# each with a staffs key with an array of hashes
|
18
|
+
# including clef and transposition (where applicable)
|
19
|
+
# Associations:
|
20
|
+
# family: the family of the instrument (e.g. "saxophone")
|
21
|
+
# orchestra_section: the section of the orchestra (e.g. "strings")
|
4
22
|
class HeadMusic::Instrument
|
5
23
|
include HeadMusic::Named
|
6
24
|
|
7
25
|
INSTRUMENTS = YAML.load_file(File.expand_path("data/instruments.yml", __dir__)).freeze
|
8
26
|
|
9
27
|
def self.get(name)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
new(name)
|
28
|
+
result = get_by_name(name) || get_by_name(key_for_name(name)) || get_by_alias(name)
|
29
|
+
result || new(name)
|
14
30
|
end
|
15
31
|
|
16
32
|
def self.all
|
17
|
-
|
33
|
+
HeadMusic::InstrumentFamily.all
|
34
|
+
@all ||=
|
35
|
+
INSTRUMENTS.map { |key, _data| get(key) }.sort_by(&:name)
|
18
36
|
end
|
19
37
|
|
20
|
-
attr_reader
|
38
|
+
attr_reader(
|
39
|
+
:name_key, :alias_name_keys,
|
40
|
+
:family_key, :orchestra_section_key,
|
41
|
+
:notation, :classification_keys,
|
42
|
+
:fundamental_pitch_spelling, :transposition,
|
43
|
+
:default_staffs, :default_clefs
|
44
|
+
)
|
21
45
|
|
22
46
|
def ==(other)
|
23
47
|
to_s == other.to_s
|
@@ -29,6 +53,36 @@ class HeadMusic::Instrument
|
|
29
53
|
I18n.translate(name_key, scope: [:instruments], locale: locale)
|
30
54
|
end
|
31
55
|
|
56
|
+
def family
|
57
|
+
return unless family_key
|
58
|
+
|
59
|
+
HeadMusic::InstrumentFamily.get(family_key)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns true if the instrument sounds at a different pitch than written.
|
63
|
+
def transposing?
|
64
|
+
transposition != 0
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns true if the instrument sounds at a different register than written.
|
68
|
+
def transposing_at_the_octave?
|
69
|
+
transposing? && transposition % 12 == 0
|
70
|
+
end
|
71
|
+
|
72
|
+
def single_staff?
|
73
|
+
default_staffs.length == 1
|
74
|
+
end
|
75
|
+
|
76
|
+
def multiple_staffs?
|
77
|
+
default_staffs.length > 1
|
78
|
+
end
|
79
|
+
|
80
|
+
def pitched?
|
81
|
+
return false if default_clefs.compact.uniq == ["percussion"]
|
82
|
+
|
83
|
+
default_clefs.any?
|
84
|
+
end
|
85
|
+
|
32
86
|
private_class_method :new
|
33
87
|
|
34
88
|
private
|
@@ -65,11 +119,37 @@ class HeadMusic::Instrument
|
|
65
119
|
end
|
66
120
|
|
67
121
|
def initialize_data_from_record(record)
|
122
|
+
initialize_family(record)
|
123
|
+
inherit_family_attributes(record)
|
124
|
+
initialize_names(record)
|
125
|
+
initialize_attributes(record)
|
126
|
+
end
|
127
|
+
|
128
|
+
def initialize_family(record)
|
129
|
+
@family_key = record["family_key"]
|
130
|
+
@family = HeadMusic::InstrumentFamily.get(family_key)
|
131
|
+
end
|
132
|
+
|
133
|
+
def inherit_family_attributes(record)
|
134
|
+
return unless family
|
135
|
+
|
136
|
+
@orchestra_section_key = family.orchestra_section_key
|
137
|
+
@classification_keys = family.classification_keys || []
|
138
|
+
end
|
139
|
+
|
140
|
+
def initialize_names(record)
|
68
141
|
@name_key = record["name_key"].to_sym
|
69
|
-
@family = record["family"]
|
70
|
-
@standard_staves = record["standard_staves"] || []
|
71
|
-
@classifications = record["classifications"] || []
|
72
142
|
self.name = I18n.translate(name_key, scope: "instruments", locale: "en", default: inferred_name)
|
143
|
+
@alias_name_keys = record["alias_name_keys"] || []
|
144
|
+
end
|
145
|
+
|
146
|
+
def initialize_attributes(record)
|
147
|
+
@orchestra_section_key ||= record["orchestra_section_key"]
|
148
|
+
@classification_keys = [@classification_keys, record["classification_keys"]].flatten.compact.uniq
|
149
|
+
@fundamental_pitch_spelling = record["fundamental_pitch_spelling"]
|
150
|
+
@default_staffs = (record.dig("notation", "default", "staffs") || [])
|
151
|
+
@default_clefs = @default_staffs.map { |staff| staff["clef"] }
|
152
|
+
@transposition = @default_staffs&.first&.[]("transposition") || 0
|
73
153
|
end
|
74
154
|
|
75
155
|
def inferred_name
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# An *InstrumentFamily* is a species of instrument
|
2
|
+
# that may exist in a variety of keys or other variations.
|
3
|
+
# For example, _saxophone_ is an instrument family, while
|
4
|
+
# _alto saxophone_ and _baritone saxophone_ are specific instruments.
|
5
|
+
class HeadMusic::InstrumentFamily
|
6
|
+
include HeadMusic::Named
|
7
|
+
|
8
|
+
INSTRUMENT_FAMILIES =
|
9
|
+
YAML.load_file(File.expand_path("data/instrument_families.yml", __dir__)).freeze
|
10
|
+
|
11
|
+
attr_reader :name_key, :classification_keys, :orchestra_section_key, :default_staffs
|
12
|
+
attr_accessor :name
|
13
|
+
|
14
|
+
def self.get(name)
|
15
|
+
result = get_by_name(name) || get_by_name(key_for_name(name))
|
16
|
+
result || new(name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.all
|
20
|
+
@all ||=
|
21
|
+
INSTRUMENT_FAMILIES.map { |key, _data| get(key) }.sort_by(&:name)
|
22
|
+
end
|
23
|
+
|
24
|
+
private_class_method :new
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def initialize(name)
|
29
|
+
record = record_for_name(name)
|
30
|
+
if record
|
31
|
+
initialize_data_from_record(record)
|
32
|
+
else
|
33
|
+
self.name = name.to_s
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def record_for_name(name)
|
38
|
+
record_for_key(HeadMusic::Utilities::HashKey.for(name)) ||
|
39
|
+
record_for_key(key_for_name(name))
|
40
|
+
end
|
41
|
+
|
42
|
+
def key_for_name(name)
|
43
|
+
INSTRUMENT_FAMILIES.each do |key, _data|
|
44
|
+
I18n.config.available_locales.each do |locale|
|
45
|
+
translation = I18n.t("instruments.#{key}", locale: locale)
|
46
|
+
return key if translation.downcase == name.downcase
|
47
|
+
end
|
48
|
+
end
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def record_for_key(key)
|
53
|
+
INSTRUMENT_FAMILIES.each do |name_key, data|
|
54
|
+
return data.merge!("name_key" => name_key) if name_key.to_s == key.to_s
|
55
|
+
end
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize_data_from_record(record)
|
60
|
+
@name_key = record["name_key"].to_sym
|
61
|
+
@orchestra_section_key = record["orchestra_section_key"]
|
62
|
+
@classification_keys = record["classification_keys"] || []
|
63
|
+
self.name = I18n.translate(name_key, scope: "instruments", locale: "en", default: inferred_name)
|
64
|
+
end
|
65
|
+
|
66
|
+
def inferred_name
|
67
|
+
name_key.to_s.tr("_", " ")
|
68
|
+
end
|
69
|
+
end
|
@@ -6,7 +6,7 @@ de:
|
|
6
6
|
baritone_f_clef: Baritonschlüssel
|
7
7
|
bass_clef: Bassschlüssel
|
8
8
|
c_clef: C-Schlüssel
|
9
|
-
|
9
|
+
vocal_tenor_clef: oktavierten Violinschlüssel
|
10
10
|
contrabass_clef: contrabass clef
|
11
11
|
countertenor_clef: countertenor clef
|
12
12
|
double_treble_clef: double treble clef
|
@@ -61,10 +61,10 @@ de:
|
|
61
61
|
bagpipe: Dudelsack
|
62
62
|
baritone_horn: Baritonhorn
|
63
63
|
baritone_voice: Bariton
|
64
|
-
bass_voice: Bass
|
65
64
|
bass_clarinet: Bassklarinette
|
66
65
|
bass_drum: Grosse Trommel
|
67
66
|
bass_trombone: Bass Posaune
|
67
|
+
bass_voice: Bass
|
68
68
|
bassoon: Fagott
|
69
69
|
castanets: Kastagnetten
|
70
70
|
celesta: Celesta
|
@@ -78,7 +78,7 @@ de:
|
|
78
78
|
english_horn: Englischhorn
|
79
79
|
euphonium: Euphonium
|
80
80
|
fiddle: Geige
|
81
|
-
|
81
|
+
flugelhorn: Flügelhorn
|
82
82
|
flute: Flöte
|
83
83
|
french_horn: Horn
|
84
84
|
glockenspiel: Glockenspiel
|
@@ -114,6 +114,13 @@ de:
|
|
114
114
|
voice: Stimme
|
115
115
|
xylophone: Xylophon
|
116
116
|
zither: Zither
|
117
|
+
locales:
|
118
|
+
de: Deutsch
|
119
|
+
en: Englisch
|
120
|
+
es: Spanisch
|
121
|
+
fr: Französisch
|
122
|
+
it: Italienisch
|
123
|
+
ru: Russisch
|
117
124
|
reference_pitches:
|
118
125
|
chamber_tone: Kammerton
|
119
126
|
choir_tone: Chorton
|
@@ -1,4 +1,18 @@
|
|
1
1
|
en:
|
2
|
+
chromatic_intervals:
|
3
|
+
perfect_unison: perfect unison
|
4
|
+
minor_second: minor second
|
5
|
+
major_second: major second
|
6
|
+
minor_third: minor third
|
7
|
+
major_third: major third
|
8
|
+
perfect_fourth: perfect fourth
|
9
|
+
tritone: tritone
|
10
|
+
perfect_fifth: perfect fifth
|
11
|
+
minor_sixth: minor sixth
|
12
|
+
major_sixth: major sixth
|
13
|
+
minor_seventh: minor seventh
|
14
|
+
major_seventh: major seventh
|
15
|
+
perfect_octave: perfect octave
|
2
16
|
clefs:
|
3
17
|
alto_clef: alto clef
|
4
18
|
baritone_c_clef: baritone C-clef
|
@@ -6,7 +20,7 @@ en:
|
|
6
20
|
baritone_f_clef: baritone F-clef
|
7
21
|
bass_clef: bass clef
|
8
22
|
c_clef: C-clef
|
9
|
-
|
23
|
+
vocal_tenor_clef: vocal tenor clef
|
10
24
|
contrabass_clef: contrabass clef
|
11
25
|
countertenor_clef: countertenor clef
|
12
26
|
double_treble_clef: double treble clef
|
@@ -92,7 +106,6 @@ en:
|
|
92
106
|
bass_drum: bass drum
|
93
107
|
bass_guitar: bass guitar
|
94
108
|
bass_oboe: bass oboe
|
95
|
-
bass_drum: bass drum
|
96
109
|
bass_trombone: bass trombone
|
97
110
|
bass_tuba: bass tuba
|
98
111
|
bass_voice: bass
|
@@ -102,21 +115,20 @@ en:
|
|
102
115
|
cello: cello
|
103
116
|
chimes: chimes
|
104
117
|
cimbalom: cimbalom
|
105
|
-
cowbell: cowbell
|
106
118
|
clarinet: clarinet
|
107
|
-
clavichord: clavichord
|
108
119
|
clash_cymbals: clash cymbals
|
109
|
-
|
110
|
-
contrabassoon: contrabassoon
|
120
|
+
clavichord: clavichord
|
111
121
|
contra_bass_clarinet: contra bass clarinet
|
122
|
+
contrabassoon: contrabassoon
|
112
123
|
cor_anglais: cor anglais
|
124
|
+
cornet: cornet
|
113
125
|
cowbell: cowbell
|
114
|
-
cymbal: cymbal
|
115
126
|
crotales: crotales
|
127
|
+
cymbal: cymbal
|
116
128
|
double_bass: double bass
|
117
129
|
english_horn: English horn
|
118
130
|
euphonium: euphonium
|
119
|
-
|
131
|
+
flugelhorn: flugelhorn
|
120
132
|
flute: flute
|
121
133
|
french_horn: French horn
|
122
134
|
glockenspiel: glockenspiel
|
@@ -164,6 +176,13 @@ en:
|
|
164
176
|
woodblock: woodblock
|
165
177
|
xylophone: xylophone
|
166
178
|
zither: zither
|
179
|
+
locales:
|
180
|
+
de: German
|
181
|
+
en: English
|
182
|
+
es: Spanish
|
183
|
+
fr: French
|
184
|
+
it: Italian
|
185
|
+
ru: Russian
|
167
186
|
reference_pitches:
|
168
187
|
a440: A440
|
169
188
|
baroque: Baroque pitch
|
@@ -6,7 +6,7 @@ es:
|
|
6
6
|
baritone_f_clef: clave de fa en tercera
|
7
7
|
bass_clef: clave de bajo
|
8
8
|
c_clef: clave de do
|
9
|
-
|
9
|
+
vocal_tenor_clef: vocal tenor clef
|
10
10
|
contrabass_clef: clave de contrabajo
|
11
11
|
countertenor_clef: clave de contratenor
|
12
12
|
double_treble_clef: double clave de sol
|
@@ -72,7 +72,7 @@ es:
|
|
72
72
|
double_bass: contrabajo
|
73
73
|
english_horn: Cuerno inglés
|
74
74
|
euphonium: euphonium
|
75
|
-
|
75
|
+
flugelhorn: fliscorno
|
76
76
|
flute: flauta
|
77
77
|
french_horn: corno
|
78
78
|
glockenspiel: campanólogo
|
@@ -108,6 +108,13 @@ es:
|
|
108
108
|
voice: voz
|
109
109
|
xylophone: xilofón
|
110
110
|
zither: cítara
|
111
|
+
locales:
|
112
|
+
de: Alemán
|
113
|
+
en: Inglés
|
114
|
+
es: Español
|
115
|
+
fr: Francés
|
116
|
+
it: Italiano
|
117
|
+
ru: Ruso
|
111
118
|
rudiments:
|
112
119
|
clef: clave
|
113
120
|
consonance: consonancia
|
@@ -6,7 +6,7 @@ fr:
|
|
6
6
|
baritone_f_clef: clé de fa 3e
|
7
7
|
bass_clef: clé de basse
|
8
8
|
c_clef: clé d'ut
|
9
|
-
|
9
|
+
vocal_tenor_clef: vocal tenor clef
|
10
10
|
contrabass_clef: clé de contrebasse
|
11
11
|
countertenor_clef: clé de contre-ténor
|
12
12
|
double_treble_clef: double clé de sol
|
@@ -120,5 +120,12 @@ fr:
|
|
120
120
|
voice: voix
|
121
121
|
xylophone: xylophone
|
122
122
|
zither: cithare
|
123
|
+
locales:
|
124
|
+
de: allemand
|
125
|
+
en: anglais
|
126
|
+
es: espagnol
|
127
|
+
fr: français
|
128
|
+
it: italien
|
129
|
+
ru: russe
|
123
130
|
rudiments:
|
124
131
|
clef: clé
|
@@ -6,7 +6,7 @@ it:
|
|
6
6
|
baritone_f_clef: chiave di baritono
|
7
7
|
bass_clef: chiave di basso
|
8
8
|
c_clef: chiave di do
|
9
|
-
|
9
|
+
vocal_tenor_clef: chiave di sol in ottava
|
10
10
|
contrabass_clef: chiave di contrabbasso
|
11
11
|
countertenor_clef: chiave di controtenore
|
12
12
|
double_treble_clef: chiave di sol in ottava
|
@@ -76,7 +76,7 @@ it:
|
|
76
76
|
double_bass: contrabasso
|
77
77
|
english_horn: corno inglese
|
78
78
|
euphonium: eufonio
|
79
|
-
|
79
|
+
flugelhorn: flicorno
|
80
80
|
flute: flauto
|
81
81
|
french_horn: corno
|
82
82
|
glockenspiel: glockenspiel
|
@@ -91,9 +91,9 @@ it:
|
|
91
91
|
natural_horn: corno naturale
|
92
92
|
oboe: oboe
|
93
93
|
oboe_d_amore: oboe d'amore
|
94
|
-
piccolo: ottavino
|
95
94
|
organ: organo
|
96
95
|
piano: piano
|
96
|
+
piccolo: ottavino
|
97
97
|
recorder: flauto dolce
|
98
98
|
saxophone: sassofono
|
99
99
|
snare_drum: tamburo rullante
|
@@ -112,6 +112,13 @@ it:
|
|
112
112
|
voice: voce
|
113
113
|
xylophone: xilofono
|
114
114
|
zither: cetra da tavolo
|
115
|
+
locales:
|
116
|
+
de: Tedesco
|
117
|
+
en: Inglese
|
118
|
+
es: Spagnolo
|
119
|
+
fr: Francese
|
120
|
+
it: Italiano
|
121
|
+
ru: Russo
|
115
122
|
rudiments:
|
116
123
|
clef: chiave
|
117
124
|
consonance: consonanza
|
@@ -32,7 +32,7 @@ ru:
|
|
32
32
|
double_bass: kontrabas
|
33
33
|
english_horn: angliiskii rozhok
|
34
34
|
euphonium: evfonium
|
35
|
-
|
35
|
+
flugelhorn: fliugel'gorn
|
36
36
|
flute: fleita
|
37
37
|
french_horn: Gorn
|
38
38
|
glockenspiel: kolokol'chiki
|
@@ -67,4 +67,11 @@ ru:
|
|
67
67
|
violoncello: violonchel'
|
68
68
|
voice: golos
|
69
69
|
xylophone: ksilofon
|
70
|
-
zither: tsitra
|
70
|
+
zither: tsitra
|
71
|
+
locales:
|
72
|
+
de: Немецкий
|
73
|
+
en: Английский
|
74
|
+
es: Испанский
|
75
|
+
fr: Французский
|
76
|
+
it: Итальянский
|
77
|
+
ru: Русский
|
data/lib/head_music/staff.rb
CHANGED
@@ -5,11 +5,14 @@ class HeadMusic::Staff
|
|
5
5
|
DEFAULT_LINE_COUNT = 5
|
6
6
|
|
7
7
|
attr_reader :default_clef, :line_count, :instrument
|
8
|
-
alias_method :clef, :default_clef
|
9
8
|
|
10
9
|
def initialize(default_clef, instrument: nil, line_count: nil)
|
11
10
|
@default_clef = HeadMusic::Clef.get(default_clef)
|
12
11
|
@line_count = line_count || DEFAULT_LINE_COUNT
|
13
12
|
@instrument = HeadMusic::Instrument.get(instrument) if instrument
|
14
13
|
end
|
14
|
+
|
15
|
+
def clef
|
16
|
+
default_clef || instrument&.default_staffs&.first
|
17
|
+
end
|
15
18
|
end
|
data/lib/head_music/version.rb
CHANGED
data/lib/head_music.rb
CHANGED
@@ -39,8 +39,8 @@ require "head_music/circle"
|
|
39
39
|
require "head_music/clef"
|
40
40
|
require "head_music/consonance"
|
41
41
|
require "head_music/diatonic_interval"
|
42
|
-
require "head_music/grand_staff"
|
43
42
|
require "head_music/harmonic_interval"
|
43
|
+
require "head_music/instrument_family"
|
44
44
|
require "head_music/instrument"
|
45
45
|
require "head_music/interval_cycle"
|
46
46
|
require "head_music/key_signature"
|
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:
|
4
|
+
version: 2.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-
|
11
|
+
date: 2023-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -132,11 +132,12 @@ files:
|
|
132
132
|
- lib/head_music/content/rhythmic_value.rb
|
133
133
|
- lib/head_music/content/voice.rb
|
134
134
|
- lib/head_music/data/clefs.yml
|
135
|
+
- lib/head_music/data/instrument_families.yml
|
135
136
|
- lib/head_music/data/instruments.yml
|
136
137
|
- lib/head_music/diatonic_interval.rb
|
137
|
-
- lib/head_music/grand_staff.rb
|
138
138
|
- lib/head_music/harmonic_interval.rb
|
139
139
|
- lib/head_music/instrument.rb
|
140
|
+
- lib/head_music/instrument_family.rb
|
140
141
|
- lib/head_music/interval_cycle.rb
|
141
142
|
- lib/head_music/key_signature.rb
|
142
143
|
- lib/head_music/letter_name.rb
|
@@ -234,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
234
235
|
- !ruby/object:Gem::Version
|
235
236
|
version: '0'
|
236
237
|
requirements: []
|
237
|
-
rubygems_version: 3.
|
238
|
+
rubygems_version: 3.4.12
|
238
239
|
signing_key:
|
239
240
|
specification_version: 4
|
240
241
|
summary: The rudiments of western music theory.
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# A grand staff is a group of staves for a single instrument, such as a piano.
|
4
|
-
class HeadMusic::GrandStaff
|
5
|
-
GRAND_STAVES = {
|
6
|
-
piano: {
|
7
|
-
instrument: :piano,
|
8
|
-
staves: [
|
9
|
-
{clef: :treble_clef, for: :right_hand},
|
10
|
-
{clef: :bass_clef, for: :left_hand}
|
11
|
-
]
|
12
|
-
},
|
13
|
-
organ: {
|
14
|
-
instrument: :organ,
|
15
|
-
staves: [
|
16
|
-
{clef: :treble_clef, for: :right_hand},
|
17
|
-
{clef: :bass_clef, for: :left_hand},
|
18
|
-
{clef: :bass_clef, for: :pedals}
|
19
|
-
]
|
20
|
-
}
|
21
|
-
}.freeze
|
22
|
-
|
23
|
-
def self.get(name)
|
24
|
-
@grand_staves ||= {}
|
25
|
-
hash_key = HeadMusic::Utilities::HashKey.for(name)
|
26
|
-
return nil unless GRAND_STAVES.key?(hash_key)
|
27
|
-
|
28
|
-
@grand_staves[hash_key] ||= new(hash_key)
|
29
|
-
end
|
30
|
-
|
31
|
-
attr_reader :identifier, :data
|
32
|
-
|
33
|
-
def initialize(name)
|
34
|
-
@identifier = HeadMusic::Utilities::HashKey.for(name)
|
35
|
-
@data = GRAND_STAVES[identifier]
|
36
|
-
end
|
37
|
-
|
38
|
-
def instrument
|
39
|
-
@instrument ||= HeadMusic::Instrument.get(data[:instrument])
|
40
|
-
end
|
41
|
-
|
42
|
-
def staves
|
43
|
-
@staves ||=
|
44
|
-
data[:staves].map do |staff|
|
45
|
-
HeadMusic::Staff.new(staff[:clef], instrument: instrument)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def brace_staves_index_first
|
50
|
-
0
|
51
|
-
end
|
52
|
-
|
53
|
-
def brace_staves_index_last
|
54
|
-
1
|
55
|
-
end
|
56
|
-
end
|