Class: HeadMusic::Content::Voice
- Inherits:
-
Object
- Object
- HeadMusic::Content::Voice
show all
- Defined in:
- lib/head_music/content/voice.rb,
lib/head_music/content/voice/continuity.rb,
lib/head_music/content/voice/melodic_line.rb,
lib/head_music/content/voice/melodic_note_pair.rb
Overview
A Voice is a stream of music with some indepedence that is conceptually one part or for one performer.
The melodic lines in counterpoint are each a voice.
Defined Under Namespace
Classes: Continuity, MelodicLine, MelodicNotePair
Instance Attribute Summary collapse
Instance Method Summary
collapse
Constructor Details
#initialize(composition: nil, role: nil) ⇒ Voice
Returns a new instance of Voice.
16
17
18
19
20
|
# File 'lib/head_music/content/voice.rb', line 16
def initialize(composition: nil, role: nil)
@composition = composition || HeadMusic::Content::Composition.new
@role = role
@placements = []
end
|
Instance Attribute Details
#composition ⇒ Object
Returns the value of attribute composition.
7
8
9
|
# File 'lib/head_music/content/voice.rb', line 7
def composition
@composition
end
|
#placements ⇒ Object
Returns the value of attribute placements.
7
8
9
|
# File 'lib/head_music/content/voice.rb', line 7
def placements
@placements
end
|
#role ⇒ Object
Returns the value of attribute role.
7
8
9
|
# File 'lib/head_music/content/voice.rb', line 7
def role
@role
end
|
Instance Method Details
#bar_number_of(placement) ⇒ Object
93
94
95
|
# File 'lib/head_music/content/voice.rb', line 93
def bar_number_of(placement)
placement ? placement.position.bar_number : 1
end
|
#cantus_firmus? ⇒ Boolean
52
53
54
|
# File 'lib/head_music/content/voice.rb', line 52
def cantus_firmus?
role.to_s =~ /cantus.?firmus/i
end
|
#earliest_bar_number ⇒ Object
56
57
58
|
# File 'lib/head_music/content/voice.rb', line 56
def earliest_bar_number
bar_number_of(placements.first)
end
|
#first_gap ⇒ Object
Returns nil if placements are contiguous, or [expected_position, found_placement]
for the first gap.
74
75
76
|
# File 'lib/head_music/content/voice.rb', line 74
def first_gap
Continuity.new(composition, placements).first_gap
end
|
#insert_into_placements(placement) ⇒ Object
Positions are unique within a voice (place merges same-position
placements), so insertion order is simply position order.
103
104
105
106
|
# File 'lib/head_music/content/voice.rb', line 103
def insert_into_placements(placement)
index = placements.index { |existing| existing > placement } || placements.length
placements.insert(index, placement)
end
|
#last_placement ⇒ Object
64
65
66
|
# File 'lib/head_music/content/voice.rb', line 64
def last_placement
placements.last
end
|
#latest_bar_number ⇒ Object
60
61
62
|
# File 'lib/head_music/content/voice.rb', line 60
def latest_bar_number
bar_number_of(placements.last)
end
|
#melodic_line ⇒ Object
48
49
50
|
# File 'lib/head_music/content/voice.rb', line 48
def melodic_line
@melodic_line ||= MelodicLine.new(notes)
end
|
#next_position ⇒ Object
68
69
70
|
# File 'lib/head_music/content/voice.rb', line 68
def next_position
last_placement ? last_placement.next_position : HeadMusic::Content::Position.new(composition, 1, 1, 0)
end
|
#notes ⇒ Object
Placements are kept in position order, so the notes and rests drawn from
them are already ordered.
35
36
37
|
# File 'lib/head_music/content/voice.rb', line 35
def notes
placements.select(&:pitched?)
end
|
#notes_not_in_key ⇒ Object
43
44
45
46
|
# File 'lib/head_music/content/voice.rb', line 43
def notes_not_in_key
key_spellings = key_signature.spellings
notes.reject { |note| key_spellings.include?(note.pitch.spelling) }
end
|
#pitches_string ⇒ Object
108
109
110
|
# File 'lib/head_music/content/voice.rb', line 108
def pitches_string
pitches.first(10).join(" ")
end
|
#place(position, rhythmic_value, sound_or_sounds = nil) ⇒ Object
22
23
24
25
26
27
28
29
30
31
|
# File 'lib/head_music/content/voice.rb', line 22
def place(position, rhythmic_value, sound_or_sounds = nil)
@melodic_line = nil
placement = HeadMusic::Content::Placement.new(self, position, rhythmic_value, sound_or_sounds)
existing = placement_at(placement.position)
return existing.merge(placement) if existing
insert_into_placements(placement)
placement
end
|
#placement_at(position) ⇒ Object
97
98
99
|
# File 'lib/head_music/content/voice.rb', line 97
def placement_at(position)
placements.find { |placement| placement.position == position }
end
|
#rests ⇒ Object
39
40
41
|
# File 'lib/head_music/content/voice.rb', line 39
def rests
placements.select(&:rest?)
end
|
#to_h ⇒ Object
84
85
86
87
88
89
|
# File 'lib/head_music/content/voice.rb', line 84
def to_h
{
"role" => role&.to_s,
"placements" => placements.map(&:to_h)
}
end
|
#to_s ⇒ Object
78
79
80
81
82
|
# File 'lib/head_music/content/voice.rb', line 78
def to_s
return pitches_string if role.to_s.strip == ""
[role, pitches_string].join(": ")
end
|