lib/head_music/instrument.rb in head_music-4.0.1 vs lib/head_music/instrument.rb in head_music-5.0.0

- old
+ new

@@ -1,34 +1,28 @@ -# frozen_string_literal: true - # A musical instrument. # An instrument object can be assigned to a staff object. # Attributes: # name_key: the name of the instrument # alias_name_keys: an array of alternative names for the instrument # orchestra_section_key: the section of the orchestra (e.g. "strings") # family_key: the key for the family of the instrument (e.g. "saxophone") # classification_keys: an array of classification_keys -# transposition: the number of semitones between the written and the sounding pitch (optional, default: 0) # default_clefs: the default clef or system of clefs for the instrument # - [treble] for instruments that use the treble clef # - [treble, bass] for instruments that use the grand staff -# notation: -# a hash of default and alternative notation systems, -# each with a staff's key with an array of hashes -# including clef and transposition (where applicable) +# pitch_configurations: +# a hash of default and alternative fundamental pitches. # Associations: # family: the family of the instrument (e.g. "saxophone") # orchestra_section: the section of the orchestra (e.g. "strings") class HeadMusic::Instrument include HeadMusic::Named INSTRUMENTS = YAML.load_file(File.expand_path("data/instruments.yml", __dir__)).freeze def self.get(name) - result = get_by_name(name) || get_by_name(key_for_name(name)) || get_by_alias(name) - result || new(name) + get_by_name(name) end def self.all HeadMusic::InstrumentFamily.all @all ||= @@ -36,13 +30,11 @@ end attr_reader( :name_key, :alias_name_keys, :family_key, :orchestra_section_key, - :notation, :classification_keys, - :fundamental_pitch_spelling, :transposition, - :default_staves, :default_clefs + :pitch_configurations, :classification_keys ) def ==(other) to_s == other.to_s end @@ -59,16 +51,16 @@ HeadMusic::InstrumentFamily.get(family_key) end # Returns true if the instrument sounds at a different pitch than written. def transposing? - transposition != 0 + default_sounding_transposition != 0 end # Returns true if the instrument sounds at a different register than written. def transposing_at_the_octave? - transposing? && transposition % 12 == 0 + transposing? && default_sounding_transposition % 12 == 0 end def single_staff? default_staves.length == 1 end @@ -76,15 +68,35 @@ def multiple_staves? default_staves.length > 1 end def pitched? - return false if default_clefs.compact.uniq == ["percussion"] + return false if default_clefs.compact.uniq == [HeadMusic::Clef.get("neutral_clef")] default_clefs.any? end + def default_pitch_configuration + pitch_configurations.find(&:default?) || pitch_configurations.first + end + + def default_staff_configuration + default_pitch_configuration&.default_staff_configuration + end + + def default_staves + default_staff_configuration&.staves || [] + end + + def default_clefs + default_staves&.map(&:clef) || [] + end + + def default_sounding_transposition + default_staves&.first&.sounding_transposition || 0 + end + private_class_method :new private def initialize(name) @@ -144,13 +156,13 @@ end def initialize_attributes(record) @orchestra_section_key ||= record["orchestra_section_key"] @classification_keys = [@classification_keys, record["classification_keys"]].flatten.compact.uniq - @fundamental_pitch_spelling = record["fundamental_pitch_spelling"] - @default_staves = (record.dig("notation", "default", "staves") || []) - @default_clefs = @default_staves.map { |staff| staff["clef"] } - @transposition = @default_staves&.first&.[]("transposition") || 0 + @pitch_configurations = + (record["pitch_configurations"] || {}).map do |key, attributes| + HeadMusic::Instrument::PitchConfiguration.new(key, attributes) + end end def inferred_name name_key.to_s.tr("_", " ") end