Class: HeadMusic::Content::Composition

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

Overview

A composition is musical content.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name: nil, key_signature: nil, meter: nil) ⇒ Composition

Returns a new instance of Composition.



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

def initialize(name: nil, key_signature: nil, meter: nil)
  ensure_attributes(name, key_signature, meter)
  @voices = []
end

Instance Attribute Details

#key_signatureObject (readonly)

Returns the value of attribute key_signature.



6
7
8
# File 'lib/head_music/content/composition.rb', line 6

def key_signature
  @key_signature
end

#meterObject (readonly)

Returns the value of attribute meter.



6
7
8
# File 'lib/head_music/content/composition.rb', line 6

def meter
  @meter
end

#nameObject (readonly)

Returns the value of attribute name.



6
7
8
# File 'lib/head_music/content/composition.rb', line 6

def name
  @name
end

#voicesObject (readonly)

Returns the value of attribute voices.



6
7
8
# File 'lib/head_music/content/composition.rb', line 6

def voices
  @voices
end

Instance Method Details

#add_voice(role: nil) ⇒ Object



13
14
15
16
# File 'lib/head_music/content/composition.rb', line 13

def add_voice(role: nil)
  @voices << HeadMusic::Content::Voice.new(composition: self, role: role)
  @voices.last
end

#bars(last = latest_bar_number) ⇒ Object



28
29
30
31
32
33
34
# File 'lib/head_music/content/composition.rb', line 28

def bars(last = latest_bar_number)
  @bars ||= []
  (earliest_bar_number..last).each do |bar_number|
    @bars[bar_number] ||= HeadMusic::Content::Bar.new(self)
  end
  @bars[earliest_bar_number..last]
end

#cantus_firmus_voiceObject



52
53
54
# File 'lib/head_music/content/composition.rb', line 52

def cantus_firmus_voice
  voices.detect(&:cantus_firmus?)
end

#change_key_signature(bar_number, key_signature) ⇒ Object



36
37
38
# File 'lib/head_music/content/composition.rb', line 36

def change_key_signature(bar_number, key_signature)
  bars(bar_number).last.key_signature = key_signature
end

#change_meter(bar_number, meter) ⇒ Object



40
41
42
# File 'lib/head_music/content/composition.rb', line 40

def change_meter(bar_number, meter)
  bars(bar_number).last.meter = meter
end

#counterpoint_voiceObject



56
57
58
# File 'lib/head_music/content/composition.rb', line 56

def counterpoint_voice
  voices.reject(&:cantus_firmus?).first
end

#earliest_bar_numberObject



44
45
46
# File 'lib/head_music/content/composition.rb', line 44

def earliest_bar_number
  [voices.map(&:earliest_bar_number), 1].flatten.min
end

#ensure_attributes(name, key_signature, meter) ⇒ Object (private)



66
67
68
69
70
71
# File 'lib/head_music/content/composition.rb', line 66

def ensure_attributes(name, key_signature, meter)
  @name = name || "Composition"
  @key_signature = HeadMusic::Rudiment::KeySignature.get(key_signature) if key_signature
  @key_signature ||= HeadMusic::Rudiment::KeySignature.default
  @meter = meter ? HeadMusic::Rudiment::Meter.get(meter) : HeadMusic::Rudiment::Meter.default
end

#key_signature_at(bar_number) ⇒ Object



23
24
25
26
# File 'lib/head_music/content/composition.rb', line 23

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

#last_key_signature_change(bar_number) ⇒ Object (private)



78
79
80
# File 'lib/head_music/content/composition.rb', line 78

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) ⇒ Object (private)



73
74
75
76
# File 'lib/head_music/content/composition.rb', line 73

def last_meter_change(bar_number)
  bar_number = [bar_number, earliest_bar_number].max
  bars(bar_number)[earliest_bar_number..bar_number].reverse.detect(&:meter)
end

#latest_bar_numberObject



48
49
50
# File 'lib/head_music/content/composition.rb', line 48

def latest_bar_number
  [voices.map(&:latest_bar_number), 1].flatten.max
end

#meter_at(bar_number) ⇒ Object



18
19
20
21
# File 'lib/head_music/content/composition.rb', line 18

def meter_at(bar_number)
  meter_change = last_meter_change(bar_number)
  meter_change ? meter_change.meter : meter
end

#to_sObject



60
61
62
# File 'lib/head_music/content/composition.rb', line 60

def to_s
  "#{name} — #{voices.count} #{(voices.count == 1) ? "voice" : "voices"}"
end