head_music 0.23.2 → 0.24.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -6
  3. data/Rakefile +1 -1
  4. data/head_music.gemspec +3 -2
  5. data/lib/head_music.rb +15 -1
  6. data/lib/head_music/chromatic_interval.rb +6 -1
  7. data/lib/head_music/circle.rb +30 -19
  8. data/lib/head_music/clef.rb +63 -26
  9. data/lib/head_music/content/placement.rb +1 -0
  10. data/lib/head_music/content/position.rb +1 -0
  11. data/lib/head_music/content/voice.rb +1 -0
  12. data/lib/head_music/data/clefs.yml +126 -0
  13. data/lib/head_music/data/instruments.yml +36 -0
  14. data/lib/head_music/diatonic_interval.rb +3 -0
  15. data/lib/head_music/grand_staff.rb +11 -6
  16. data/lib/head_music/instrument.rb +40 -27
  17. data/lib/head_music/interval_cycle.rb +37 -16
  18. data/lib/head_music/key_signature.rb +22 -6
  19. data/lib/head_music/locales/de.yml +63 -0
  20. data/lib/head_music/locales/en.yml +198 -0
  21. data/lib/head_music/locales/en_GB.yml +3 -0
  22. data/lib/head_music/locales/es.yml +53 -0
  23. data/lib/head_music/locales/fr.yml +57 -0
  24. data/lib/head_music/locales/it.yml +58 -0
  25. data/lib/head_music/musical_symbol.rb +1 -1
  26. data/lib/head_music/named.rb +112 -0
  27. data/lib/head_music/octave.rb +1 -0
  28. data/lib/head_music/pitch.rb +11 -4
  29. data/lib/head_music/pitch_class.rb +2 -2
  30. data/lib/head_music/quality.rb +1 -0
  31. data/lib/head_music/reference_pitch.rb +105 -47
  32. data/lib/head_music/rhythmic_unit.rb +2 -2
  33. data/lib/head_music/scale_degree.rb +1 -0
  34. data/lib/head_music/scale_type.rb +1 -1
  35. data/lib/head_music/sign.rb +46 -14
  36. data/lib/head_music/solmization.rb +52 -0
  37. data/lib/head_music/solmizations.yml +20 -0
  38. data/lib/head_music/spelling.rb +6 -9
  39. data/lib/head_music/tuning.rb +1 -4
  40. data/lib/head_music/utilities/hash_key.rb +1 -1
  41. data/lib/head_music/version.rb +1 -1
  42. metadata +30 -6
  43. data/lib/head_music/named_rudiment.rb +0 -29
@@ -0,0 +1,36 @@
1
+ ---
2
+ - name_key: alto_flute
3
+ - name_key: guitar
4
+ family: string
5
+ classifications:
6
+ - string
7
+ - chordophone
8
+ default_clefs:
9
+ - treble_clef
10
+ - name_key: piano
11
+ family: string
12
+ classifications:
13
+ - string
14
+ - chordophone
15
+ - keyboard
16
+ default_clefs:
17
+ - treble_clef
18
+ - bass_clef
19
+ - name_key: violin
20
+ alias_name_keys:
21
+ - fiddle
22
+ family: string
23
+ classifications:
24
+ - string
25
+ - chordophone
26
+ - bowed
27
+ default_clefs:
28
+ - treble_clef
29
+ - name_key: viola
30
+ family: string
31
+ classifications:
32
+ - string
33
+ - chordophone
34
+ - bowed
35
+ default_clefs:
36
+ - alto_clef
@@ -4,6 +4,7 @@
4
4
  class HeadMusic::DiatonicInterval
5
5
  include Comparable
6
6
 
7
+ # TODO: include Named module
7
8
  NUMBER_NAMES = %w[
8
9
  unison second third fourth fifth sixth seventh octave
9
10
  ninth tenth eleventh twelfth thirteenth fourteenth fifteenth
@@ -280,6 +281,8 @@ class HeadMusic::DiatonicInterval
280
281
  to: :naming
281
282
  )
282
283
 
284
+ alias to_i semitones
285
+
283
286
  # Accepts a name and returns the interval with middle c on the bottom
284
287
  def self.get(identifier)
285
288
  name = Parser.new(identifier)
@@ -6,16 +6,16 @@ class HeadMusic::GrandStaff
6
6
  piano: {
7
7
  instrument: :piano,
8
8
  staves: [
9
- { clef: :treble, instrument: :piano },
10
- { clef: :bass, instrument: :piano },
9
+ { clef: :treble_clef, instrument: :piano },
10
+ { clef: :bass_clef, instrument: :piano },
11
11
  ],
12
12
  },
13
13
  organ: {
14
14
  instrument: :organ,
15
15
  staves: [
16
- { clef: :treble, instrument: :organ },
17
- { clef: :bass, instrument: :organ },
18
- { clef: :bass, instrument: :pedals },
16
+ { clef: :treble_clef, instrument: :organ },
17
+ { clef: :bass_clef, instrument: :organ },
18
+ { clef: :bass_clef, instrument: :pedals },
19
19
  ],
20
20
  },
21
21
  }.freeze
@@ -41,7 +41,12 @@ class HeadMusic::GrandStaff
41
41
 
42
42
  def staves
43
43
  @staves ||=
44
- data[:staves].map { |staff| HeadMusic::Staff.new(staff[:clef], instrument: staff[:instrument] || instrument) }
44
+ data[:staves].map do |staff|
45
+ HeadMusic::Staff.new(
46
+ staff[:clef],
47
+ instrument: staff[:instrument] || instrument
48
+ )
49
+ end
45
50
  end
46
51
 
47
52
  def brace_staves_index_first
@@ -2,46 +2,59 @@
2
2
 
3
3
  # An instrument can be assigned to a staff.
4
4
  class HeadMusic::Instrument
5
- include HeadMusic::NamedRudiment
6
-
7
- INSTRUMENTS = {
8
- violin: {
9
- name: 'violin',
10
- family: :string,
11
- default_clef: :treble,
12
- },
13
- piano: {
14
- name: 'piano',
15
- family: :string,
16
- default_system: %i[treble bass],
17
- },
18
- }.freeze
5
+ include HeadMusic::Named
6
+
7
+ INSTRUMENTS = YAML.load_file(File.expand_path('data/instruments.yml', __dir__)).freeze
19
8
 
20
9
  def self.get(name)
21
- get_by_name(name)
10
+ return get_by_name(name) if get_by_name(name)
11
+ return get_by_name(key_for_name(name)) if key_for_name(name)
12
+
13
+ new(name)
22
14
  end
23
15
 
24
- def initialize(name)
25
- @name = name.to_s
16
+ attr_reader :name_key, :family, :default_clefs
17
+
18
+ def ==(other)
19
+ to_s == other.to_s
26
20
  end
27
21
 
28
- def data
29
- @data ||= INSTRUMENTS[hash_key]
22
+ private_class_method :new
23
+
24
+ private
25
+
26
+ def initialize(name)
27
+ record = record_for_name(name)
28
+ if record
29
+ initialize_data_from_record(record)
30
+ else
31
+ self.name = name
32
+ end
30
33
  end
31
34
 
32
- def family
33
- data[:family]
35
+ def record_for_name(name)
36
+ key = HeadMusic::Utilities::HashKey.for(name)
37
+ record_for_key(key) || record_for_key(key_for_name(name))
34
38
  end
35
39
 
36
- def default_system
37
- data[:default_system]
40
+ def key_for_name(name)
41
+ INSTRUMENTS.each do |instrument|
42
+ I18n.config.available_locales.each do |locale|
43
+ translation = I18n.t("instruments.#{instrument['name_key']}", locale: locale)
44
+ return instrument['name_key'] if translation.downcase == name.downcase
45
+ end
46
+ end
47
+ nil
38
48
  end
39
49
 
40
- def default_clef
41
- data[:default_clef]
50
+ def record_for_key(key)
51
+ INSTRUMENTS.detect { |instrument| instrument['name_key'] == key }
42
52
  end
43
53
 
44
- def ==(other)
45
- to_s == other.to_s
54
+ def initialize_data_from_record(record)
55
+ @family = record['family']
56
+ @default_clefs = record['default_clefs']
57
+ @name_key = record['name_key'].to_sym
58
+ self.name = I18n.translate(name_key, scope: 'instruments', locale: 'en')
46
59
  end
47
60
  end
@@ -2,35 +2,56 @@
2
2
 
3
3
  # An Interval Cycle is a collection of pitch classes created from a sequence of the same interval class.
4
4
  class HeadMusic::IntervalCycle
5
+ attr_reader :interval, :starting_pitch
6
+
5
7
  def self.get(interval = 7)
6
- @circles ||= {}
8
+ @interval_cycles ||= {}
7
9
  interval = interval.to_s.gsub(/^C/i, '').to_i
8
- @circles[interval.to_i] ||= new(interval)
10
+ interval = HeadMusic::ChromaticInterval.get(interval)
11
+ @interval_cycles[interval.to_i] ||= new(interval: interval, starting_pitch: 'C4')
9
12
  end
10
13
 
11
- attr_reader :interval, :pitch_classes
14
+ def initialize(interval:, starting_pitch: 'C4')
15
+ @interval = interval if interval.is_a?(HeadMusic::DiatonicInterval)
16
+ @interval ||= interval if interval.is_a?(HeadMusic::ChromaticInterval)
17
+ @interval ||= HeadMusic::ChromaticInterval.get(interval) if interval.to_s.match?(/\d/)
18
+ @interval ||= HeadMusic::DiatonicInterval.get(interval)
19
+ @starting_pitch = HeadMusic::Pitch.get(starting_pitch)
20
+ end
12
21
 
13
- def initialize(interval)
14
- @interval = interval.to_i
15
- @pitch_classes = pitch_classes_by_interval
22
+ def pitches
23
+ @pitches ||= pitches_up
16
24
  end
17
25
 
18
- def index(pitch_class)
19
- @pitch_classes.index(HeadMusic::Spelling.get(pitch_class).pitch_class)
26
+ def pitch_classes
27
+ @pitch_classes ||= pitches.map(&:pitch_class)
20
28
  end
21
29
 
22
- private_class_method :new
30
+ def pitch_class_set
31
+ @pitch_class_set ||= HeadMusic::PitchClassSet.new(pitches)
32
+ end
23
33
 
24
- private
34
+ def spellings
35
+ @spellings ||= pitches.map(&:spelling)
36
+ end
25
37
 
26
- def pitch_classes_by_interval
27
- [HeadMusic::PitchClass.get(0)].tap do |list|
28
- loop do
29
- next_pitch_class = list.last + interval
30
- break if next_pitch_class == list.first
38
+ protected
31
39
 
32
- list << next_pitch_class
40
+ def pitches_up
41
+ @pitches_up ||= begin
42
+ [starting_pitch].tap do |list|
43
+ loop do
44
+ next_pitch = list.last + interval
45
+ next_pitch -= octave while next_pitch - starting_pitch > 12
46
+ break if next_pitch.pitch_class == list.first.pitch_class
47
+
48
+ list << next_pitch
49
+ end
33
50
  end
34
51
  end
35
52
  end
53
+
54
+ def octave
55
+ @octave ||= HeadMusic::DiatonicInterval.get(:perfect_octave)
56
+ end
36
57
  end
@@ -6,8 +6,8 @@ class HeadMusic::KeySignature
6
6
  attr_reader :scale_type
7
7
  attr_reader :scale
8
8
 
9
- SHARPS = %w[F C G D A E B].freeze
10
- FLATS = %w[B♭ E♭ A♭ D♭ G♭ C♭ F♭].freeze
9
+ ORDERED_LETTER_NAMES_OF_SHARPS = %w[F C G D A E B].freeze
10
+ ORDERED_LETTER_NAMES_OF_FLATS = ORDERED_LETTER_NAMES_OF_SHARPS.reverse.freeze
11
11
 
12
12
  def self.default
13
13
  @default ||= new('C', :major)
@@ -39,19 +39,35 @@ class HeadMusic::KeySignature
39
39
  end
40
40
 
41
41
  def sharps
42
- spellings.select(&:sharp?).sort_by { |sharp| SHARPS.index(sharp.to_s) }
42
+ spellings.select(&:sharp?).sort_by do |spelling|
43
+ ORDERED_LETTER_NAMES_OF_SHARPS.index(spelling.letter_name.to_s)
44
+ end
45
+ end
46
+
47
+ def double_sharps
48
+ spellings.select(&:double_sharp?).sort_by do |spelling|
49
+ ORDERED_LETTER_NAMES_OF_SHARPS.index(spelling.letter_name.to_s)
50
+ end
43
51
  end
44
52
 
45
53
  def flats
46
- spellings.select(&:flat?).sort_by { |flat| FLATS.index(flat.to_s) }
54
+ spellings.select(&:flat?).sort_by do |spelling|
55
+ ORDERED_LETTER_NAMES_OF_FLATS.index(spelling.letter_name.to_s)
56
+ end
57
+ end
58
+
59
+ def double_flats
60
+ spellings.select(&:double_flat?).sort_by do |spelling|
61
+ ORDERED_LETTER_NAMES_OF_FLATS.index(spelling.letter_name.to_s)
62
+ end
47
63
  end
48
64
 
49
65
  def num_sharps
50
- sharps.length
66
+ sharps.length + double_sharps.length * 2
51
67
  end
52
68
 
53
69
  def num_flats
54
- flats.length
70
+ flats.length + double_flats.length * 2
55
71
  end
56
72
 
57
73
  def signs
@@ -0,0 +1,63 @@
1
+ de:
2
+ rudiments:
3
+ clef: Notenschlüssel
4
+ consonance: Konsonanz
5
+ clefs:
6
+ alto_clef: Altschlüssel
7
+ baritone_c_clef: Baritonschlüssel
8
+ baritone_clef: Baritonschlüssel
9
+ baritone_f_clef: Baritonschlüssel
10
+ bass_clef: Bassschlüssel
11
+ c_clef: C-Schlüssel
12
+ choral_tenor_clef: oktavierten Violinschlüssel
13
+ contrabass_clef: contrabass clef
14
+ countertenor_clef: countertenor clef
15
+ double_treble_clef: double treble clef
16
+ drum_clef: Schlagzeugschlüssel
17
+ f_clef: F-Schlüssel
18
+ fifth_line_c_clef: fifth-line C-clef
19
+ fifth_line_f_clef: fifth-line F-clef
20
+ first_line_c_clef: Sopranschlüssel
21
+ first_line_g_clef: first-line G-clef
22
+ fourth_line_c_clef: fourth-line C-clef
23
+ fourth_line_f_clef: fourth-line F-clef
24
+ french_clef: French clef
25
+ french_violin_clef: French violin clef
26
+ g_clef: G-Schlüssel
27
+ indefinite_pitch_clef: indefinite pitch clef
28
+ mezzo_soprano_clef: Mezzosopranschlüssel
29
+ neutral_clef: Schlagzeugschlüssel
30
+ percussion_clef: Schlagzeugschlüssel
31
+ second_line_c_clef: second-line C-clef
32
+ second_line_g_clef: second-line G-clef
33
+ soprano_clef: Sopranschlüssel
34
+ sub_bass_clef: Subbassschlüssel
35
+ tenor_c_clef: Tenorschlüssel
36
+ tenor_clef: Tenorschlüssel
37
+ tenor_g_clef: tenor G-clef
38
+ third_line_c_clef: third-line C-clef
39
+ third_line_f_clef: third-line F-clef
40
+ treble_clef: Violinschlüssel
41
+ viola_clef: Bratschenschlüssel
42
+ violin_clef: Violinschlüssel
43
+ reference_pitches:
44
+ chamber_tone: Kammerton
45
+ choir_tone: Chorton
46
+ instruments:
47
+ accordian: Akkordeon
48
+ alto_flute: Altflöte
49
+ alto_voice: Alt
50
+ arpeggione: Arpeggione
51
+ bagpipe: Dudelsack
52
+ baritone_voice: Bariton
53
+ bass_voice: Bass
54
+ bass_clarinet: clarinette basse
55
+ fiddle: Geige
56
+ guitar: Gitarre
57
+ piano: Piano
58
+ viola: Bratsche
59
+ violin: Violine
60
+ instrument_voices:
61
+ alto: Alt
62
+ baritone: Bariton
63
+ bass: Bass
@@ -0,0 +1,198 @@
1
+ en:
2
+ rudiments:
3
+ chromatic_interval: chromatic interval
4
+ circle: circle
5
+ clef: clef
6
+ consonance: consonance
7
+ diatonic_interval: diatonic interval
8
+ grand_staff: grand staff
9
+ harmonic_interval: harmonic interval
10
+ instrument: instrument
11
+ interval_cycle: interval cycle
12
+ key_signature: key signature
13
+ letter_name: letter name
14
+ melodic_interval: melodic interval
15
+ meter: meter
16
+ motion: motion
17
+ musical_symbol: musical symbol
18
+ octave: octave
19
+ pitch: pitch
20
+ pitch_class: pitch class
21
+ pitch_class_set: pitch class set
22
+ pitch_set: pitch set
23
+ quality: quality
24
+ reference_pitch: reference pitch
25
+ rhythm: rhythm
26
+ rhythmic_unit: rhythmic unit
27
+ scale: scale
28
+ scale_degree: scale degree
29
+ scale_type: scale type
30
+ sign: sign
31
+ solmization: solmization
32
+ sonority: sonority
33
+ spelling: spelling
34
+ staff: staff
35
+ tuning: tuning
36
+ clefs:
37
+ alto_clef: alto clef
38
+ baritone_c_clef: baritone C-clef
39
+ baritone_clef: baritone clef
40
+ baritone_f_clef: baritone F-clef
41
+ bass_clef: bass clef
42
+ c_clef: C-clef
43
+ choral_tenor_clef: choral tenor clef
44
+ contrabass_clef: contrabass clef
45
+ countertenor_clef: countertenor clef
46
+ double_treble_clef: double treble clef
47
+ drum_clef: drum clef
48
+ f_clef: F-clef
49
+ fifth_line_c_clef: fifth-line C-clef
50
+ fifth_line_f_clef: fifth-line F-clef
51
+ first_line_c_clef: first-line C-clef
52
+ first_line_g_clef: first-line G-clef
53
+ fourth_line_c_clef: fourth-line C-clef
54
+ fourth_line_f_clef: fourth-line F-clef
55
+ french_clef: French clef
56
+ french_violin_clef: French violin clef
57
+ g_clef: G-clef
58
+ indefinite_pitch_clef: indefinite pitch clef
59
+ mezzo_soprano_clef: mezzo-soprano clef
60
+ neutral_clef: neutral clef
61
+ percussion_clef: percussion clef
62
+ second_line_c_clef: second-line C-clef
63
+ second_line_g_clef: second-line G-clef
64
+ soprano_clef: soprano clef
65
+ sub_bass_clef: sub-bass clef
66
+ tenor_c_clef: tenor C-clef
67
+ tenor_clef: tenor clef
68
+ tenor_g_clef: tenor G-clef
69
+ third_line_c_clef: third-line C-clef
70
+ third_line_f_clef: third-line F-clef
71
+ treble_clef: treble clef
72
+ viola_clef: viola clef
73
+ violin_clef: treble clef
74
+ reference_pitches:
75
+ a440: A440
76
+ baroque: Baroque pitch
77
+ berlin_philharmonic: Berlin Philharmonic
78
+ boston_symphony_orchestra: Boston Symphony Orchestra
79
+ chamber_tone: chamber tone
80
+ choir: choir tone
81
+ classical: classical pitch
82
+ concert: concert pitch
83
+ continental: continental pitch
84
+ french: French pitch
85
+ haydn: Haydn pitch
86
+ high: high pitch
87
+ international: international pitch
88
+ iso_16: ISO 16
89
+ low: low pitch
90
+ mozart: Mozart pitch
91
+ new_philharmonic: new philharmonic pitch
92
+ new_york_philharmonic: New York Philharmonic
93
+ old_philharmonic: old philharmonic pitch
94
+ philosophical: philosophical pitch
95
+ sauveur: Sauveur pitch
96
+ scheibler: Scheibler pitch
97
+ scientific: scientific pitch
98
+ stuttgart: Stuttgart pitch
99
+ sydney_symphony_orchestra: Sydney Symphony Orchestra
100
+ verdi: Verdi tuning
101
+ instruments:
102
+ accordian: accordian
103
+ alto_flute: alto flute
104
+ alto_voice: alto
105
+ arpeggione: arpeggione
106
+ bagpipe: bagpipe
107
+ baritone_voice: baritone
108
+ bass_clarinet: bass clarinet
109
+ bass_drum: bass drum
110
+ bass_guitar: bass guitar
111
+ bass_oboe: bass oboe
112
+ bass_trombone: bass trombone
113
+ bass_tuba: bass tuba
114
+ bass_voice: bass
115
+ bassoon: bassoon
116
+ castanets: castanets
117
+ chimes: chimes
118
+ clarinet: clarinet
119
+ clash_cymbals: clash cymbals
120
+ cornet: cornet
121
+ contrabassoon: contrabassoon
122
+ contra_bass_clarinet: contra bass clarinet
123
+ cor_anglais: cor anglais
124
+ cowbell: cowbell
125
+ cymbal: cymbal
126
+ crotales: crotales
127
+ double_bass: double bass
128
+ english_horn: English horn
129
+ euphonium: euphonium
130
+ flugel_horn: flugel horn
131
+ flute: flute
132
+ french_horn: French horn
133
+ glockenspiel: glockenspiel
134
+ guitar: guitar
135
+ harp: harp
136
+ harpsichord: harpsichord
137
+ mandolin: mandolin
138
+ maracas: maracas
139
+ marimba: marimba
140
+ metal_block: metal block
141
+ oboe: oboe
142
+ piano: piano
143
+ piccolo: piccolo
144
+ piccolo_trumpet: piccolo trumpet
145
+ side_drum: side drum
146
+ suspended_cymbal: suspended cymbal
147
+ synthesizer: synthesizer
148
+ tam_tam: tam-tam
149
+ tambourine: tambourine
150
+ temple_blocks: temple blocks
151
+ tenor_drum: tenor drum
152
+ tenor_trombone: tenor trombone
153
+ timpani: timpani
154
+ triangle: triangle
155
+ trumpet: trumpet
156
+ tuba: tuba
157
+ tubular_bells: tubular bells
158
+ vibraphone: vibraphone
159
+ viola: viola
160
+ violin: violin
161
+ violincello: cello
162
+ woodblock: woodblock
163
+ xylophone: xylophone
164
+ instrument_abbreviations:
165
+ accordian:
166
+ - acc
167
+ alto_flute:
168
+ - afl
169
+ alto_voice:
170
+ - alt
171
+ bagpipe:
172
+ - bag
173
+ baritone_voice:
174
+ - bar
175
+ bass_voice:
176
+ - bass
177
+ bass_clarinet:
178
+ - bcl
179
+ instrument_classifications:
180
+ aerophone: aerophone
181
+ bowed: bowed
182
+ brass: brass
183
+ double_reed: double-reed
184
+ keyboard: keyboard
185
+ percussion: percussion
186
+ single_reed: single-reed
187
+ string: string
188
+ wind: wind
189
+ woodwind: woodwind
190
+ instrument_voices:
191
+ piccolo: piccolo
192
+ soprano: soprano
193
+ alto: alto
194
+ tenor: tenor
195
+ baritone: baritone
196
+ bass: bass
197
+ contrabass: contrabass
198
+ octobass: octobass