Class: HeadMusic::Content::SoundResolver

Inherits:
Object
  • Object
show all
Defined in:
lib/head_music/content/sound_resolver.rb

Overview

Resolves the raw sound argument(s) passed to Placement.new into a frozen, de-duplicated array of sound objects. Each value may be a Pitch, an UnpitchedSound, an Instrument (resolved to its percussive hit), or a name resolvable to one of those; an unresolvable name raises with guidance.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.resolve(sound_or_sounds) ⇒ Object



9
10
11
# File 'lib/head_music/content/sound_resolver.rb', line 9

def self.resolve(sound_or_sounds)
  new.resolve(sound_or_sounds)
end

Instance Method Details

#resolve(sound_or_sounds) ⇒ Object



13
14
15
16
17
18
# File 'lib/head_music/content/sound_resolver.rb', line 13

def resolve(sound_or_sounds)
  return [].freeze if sound_or_sounds.nil?

  values = sound_or_sounds.is_a?(Array) ? sound_or_sounds : [sound_or_sounds]
  values.map { |value| resolve_sound(value) }.uniq.freeze
end

#resolve_sound(value) ⇒ Object (private)



22
23
24
25
26
27
28
29
30
# File 'lib/head_music/content/sound_resolver.rb', line 22

def resolve_sound(value)
  return value if value.is_a?(HeadMusic::Rudiment::UnpitchedSound)
  return HeadMusic::Rudiment::UnpitchedSound.get(value) if value.is_a?(HeadMusic::Instruments::Instrument)

  pitch = HeadMusic::Rudiment::Pitch.get(value)
  return pitch if pitch

  unpitched_sound(value) || raise(ArgumentError, unknown_sound_message(value))
end

#unknown_sound_message(value) ⇒ Object (private)



46
47
48
49
50
51
52
53
# File 'lib/head_music/content/sound_resolver.rb', line 46

def unknown_sound_message(value)
  if HeadMusic::Instruments::Instrument.get(value)&.pitched?
    "#{value.inspect} is a pitched instrument; place a pitch such as \"D4\", " \
      "or pass HeadMusic::Rudiment::UnpitchedSound.get(#{value.inspect}) for a percussive hit"
  else
    "unknown sound: #{value.inspect}"
  end
end

#unpitched_sound(value) ⇒ Object (private)

A bare name resolves to a percussive hit only on an unpitched instrument; naming a pitched instrument is ambiguous, so it raises instead. UnpitchedSound.get(nil) is the generic sound, so nil is excluded here to preserve nil-as-rest at the argument level and nil-raises inside arrays.



36
37
38
39
40
41
42
43
44
# File 'lib/head_music/content/sound_resolver.rb', line 36

def unpitched_sound(value)
  return nil if value.nil?

  sound = HeadMusic::Rudiment::UnpitchedSound.get(value)
  return nil unless sound&.instrument
  return nil if sound.instrument.pitched?

  sound
end