class HeadMusic::Composition

A composition is musical content.

Attributes

key_signature[R]
meter[R]
name[R]
voices[R]

Public Class Methods

new(name: nil, key_signature: nil, meter: nil) click to toggle source
# File lib/head_music/content/composition.rb, line 7
def initialize(name: nil, key_signature: nil, meter: nil)
  ensure_attributes(name, key_signature, meter)
  @voices = []
end

Public Instance Methods

add_voice(role: nil) click to toggle source
# File lib/head_music/content/composition.rb, line 12
def add_voice(role: nil)
  @voices << HeadMusic::Voice.new(composition: self, role: role)
  @voices.last
end
bars(last = latest_bar_number) click to toggle source
# File lib/head_music/content/composition.rb, line 27
def bars(last = latest_bar_number)
  @bars ||= []
  (earliest_bar_number..last).each do |bar_number|
    @bars[bar_number] ||= HeadMusic::Bar.new(self)
  end
  @bars[earliest_bar_number..last]
end
cantus_firmus_voice() click to toggle source
# File lib/head_music/content/composition.rb, line 51
def cantus_firmus_voice
  voices.detect(&:cantus_firmus?)
end
change_key_signature(bar_number, key_signature) click to toggle source
# File lib/head_music/content/composition.rb, line 35
def change_key_signature(bar_number, key_signature)
  bars(bar_number).last.key_signature = key_signature
end
change_meter(bar_number, meter) click to toggle source
# File lib/head_music/content/composition.rb, line 39
def change_meter(bar_number, meter)
  bars(bar_number).last.meter = meter
end
counterpoint_voice() click to toggle source
# File lib/head_music/content/composition.rb, line 55
def counterpoint_voice
  voices.reject(&:cantus_firmus?).first
end
earliest_bar_number() click to toggle source
# File lib/head_music/content/composition.rb, line 43
def earliest_bar_number
  [voices.map(&:earliest_bar_number), 1].flatten.min
end
key_signature_at(bar_number) click to toggle source
# File lib/head_music/content/composition.rb, line 22
def key_signature_at(bar_number)
  key_signature_change = last_key_signature_change(bar_number)
  key_signature_change ? key_signature_change.key_signature : key_signature
end
latest_bar_number() click to toggle source
# File lib/head_music/content/composition.rb, line 47
def latest_bar_number
  [voices.map(&:earliest_bar_number), 1].flatten.max
end
meter_at(bar_number) click to toggle source
# File lib/head_music/content/composition.rb, line 17
def meter_at(bar_number)
  meter_change = last_meter_change(bar_number)
  meter_change ? meter_change.meter : meter
end
to_s() click to toggle source
# File lib/head_music/content/composition.rb, line 59
def to_s
  "#{name} — #{voices.count} voice(s)"
end

Private Instance Methods

ensure_attributes(name, key_signature, meter) click to toggle source
# File lib/head_music/content/composition.rb, line 65
def ensure_attributes(name, key_signature, meter)
  @name = name || 'Composition'
  @key_signature = HeadMusic::KeySignature.get(key_signature) if key_signature
  @key_signature ||= HeadMusic::KeySignature.default
  @meter = meter ? HeadMusic::Meter.get(meter) : HeadMusic::Meter.default
end
last_key_signature_change(bar_number) click to toggle source
# File lib/head_music/content/composition.rb, line 76
def last_key_signature_change(bar_number)
  bars(bar_number)[earliest_bar_number..bar_number].reverse.detect(&:key_signature)
end
last_meter_change(bar_number) click to toggle source
# File lib/head_music/content/composition.rb, line 72
def last_meter_change(bar_number)
  bars(bar_number)[earliest_bar_number..bar_number].reverse.detect(&:meter)
end