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, composer: nil, origin: nil, comments: nil) ⇒ Composition

Returns a new instance of Composition.



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

def initialize(name: nil, key_signature: nil, meter: nil, composer: nil, origin: nil, comments: nil)
  ensure_attributes(name, key_signature, meter)
  @composer = composer
  @origin = origin
  @voices = []
  @comments = Array(comments).map { |text| HeadMusic::Content::Comment.new(self, text) }
end

Instance Attribute Details

#commentsObject (readonly)

Returns the value of attribute comments.



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

def comments
  @comments
end

#composerObject (readonly)

Returns the value of attribute composer.



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

def composer
  @composer
end

#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

#originObject (readonly)

Returns the value of attribute origin.



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

def origin
  @origin
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_comment(text, position = nil) ⇒ Object



21
22
23
24
# File 'lib/head_music/content/composition.rb', line 21

def add_comment(text, position = nil)
  @comments << HeadMusic::Content::Comment.new(self, text, position)
  @comments.last
end

#add_voice(role: nil) ⇒ Object



16
17
18
19
# File 'lib/head_music/content/composition.rb', line 16

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

#bars(last = latest_bar_number) ⇒ Object



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

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



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

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

#change_key_signature(bar_number, key_signature) ⇒ Object



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

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

#change_meter(bar_number, meter) ⇒ Object



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

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

#counterpoint_voiceObject



64
65
66
# File 'lib/head_music/content/composition.rb', line 64

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

#earliest_bar_numberObject



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

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

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



82
83
84
85
86
87
# File 'lib/head_music/content/composition.rb', line 82

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



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

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)



94
95
96
# File 'lib/head_music/content/composition.rb', line 94

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)



89
90
91
92
# File 'lib/head_music/content/composition.rb', line 89

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



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

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

#meter_at(bar_number) ⇒ Object



26
27
28
29
# File 'lib/head_music/content/composition.rb', line 26

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

#to_abc(**options) ⇒ Object



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

def to_abc(**options)
  HeadMusic::Notation::ABC.render(self, **options)
end

#to_musicxmlObject



76
77
78
# File 'lib/head_music/content/composition.rb', line 76

def to_musicxml
  HeadMusic::Notation::MusicXML.render(self)
end

#to_sObject



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

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