mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 19:23:59 +00:00
Implement endings, coda
This commit is contained in:
parent
0dbbf74640
commit
46c44d3bbd
|
@ -12,31 +12,32 @@ INPUT = readPlist($stdin)
|
||||||
$USE_FLATS = false
|
$USE_FLATS = false
|
||||||
$DIVISIONS = 3
|
$DIVISIONS = 3
|
||||||
|
|
||||||
|
def newTextElement(name, text)
|
||||||
|
elt = REXML::Element.new(name)
|
||||||
|
elt.add_text(text.to_s)
|
||||||
|
|
||||||
|
return elt
|
||||||
|
end
|
||||||
|
|
||||||
def _work
|
def _work
|
||||||
work = REXML::Element.new('work')
|
work = REXML::Element.new('work')
|
||||||
title = REXML::Element.new('work-title')
|
work.add_element newTextElement('work-title', INPUT['title'])
|
||||||
title.add_text(INPUT['title'])
|
|
||||||
work.add_element(title)
|
|
||||||
|
|
||||||
return work
|
return work
|
||||||
end
|
end
|
||||||
|
|
||||||
def _identification
|
def _identification
|
||||||
ident = REXML::Element.new('identification')
|
ident = REXML::Element.new('identification')
|
||||||
composer = REXML::Element.new('creator')
|
composer = newTextElement('creator', INPUT['composer'])
|
||||||
composer.add_attribute('type', 'composer')
|
composer.add_attribute('type', 'composer')
|
||||||
composer.add_text(INPUT['composer'])
|
|
||||||
ident.add_element(composer)
|
ident.add_element(composer)
|
||||||
poet = REXML::Element.new('creator')
|
poet = newTextElement('creator', INPUT['lyricist'])
|
||||||
poet.add_attribute('type', 'poet')
|
poet.add_attribute('type', 'poet')
|
||||||
poet.add_text(INPUT['lyricist'])
|
|
||||||
ident.add_element(poet)
|
ident.add_element(poet)
|
||||||
encoding = REXML::Element.new('encoding')
|
encoding = REXML::Element.new('encoding')
|
||||||
date = REXML::Element.new('encoding-date')
|
date = newTextElement('encoding-date', INPUT['saved'].strftime("%Y-%m-%d"))
|
||||||
date.add_text(INPUT['saved'].strftime("%Y-%m-%d"))
|
|
||||||
encoding.add_element(date)
|
encoding.add_element(date)
|
||||||
software = REXML::Element.new('software')
|
software = newTextElement('software', INPUT['software'])
|
||||||
software.add_text(INPUT['software'])
|
|
||||||
encoding.add_element(software)
|
encoding.add_element(software)
|
||||||
ident.add_element(encoding)
|
ident.add_element(encoding)
|
||||||
|
|
||||||
|
@ -47,15 +48,11 @@ def _part_list
|
||||||
part_list = REXML::Element.new('part-list')
|
part_list = REXML::Element.new('part-list')
|
||||||
chords = REXML::Element.new('score-part')
|
chords = REXML::Element.new('score-part')
|
||||||
chords.add_attribute('id', 'HARM')
|
chords.add_attribute('id', 'HARM')
|
||||||
chords_name = REXML::Element.new('part-name')
|
chords.add_element newTextElement('part-name', 'Chords')
|
||||||
chords_name.add_text('Chords')
|
|
||||||
chords.add_element(chords_name)
|
|
||||||
part_list.add_element(chords)
|
part_list.add_element(chords)
|
||||||
melody = REXML::Element.new('score-part')
|
melody = REXML::Element.new('score-part')
|
||||||
melody.add_attribute('id', 'MELO')
|
melody.add_attribute('id', 'MELO')
|
||||||
melody_name = REXML::Element.new('part-name')
|
melody.add_element newTextElement('part-name', 'Melody')
|
||||||
melody_name.add_text('Melody')
|
|
||||||
melody.add_element(melody_name)
|
|
||||||
part_list.add_element(melody)
|
part_list.add_element(melody)
|
||||||
|
|
||||||
return part_list
|
return part_list
|
||||||
|
@ -65,32 +62,18 @@ def _attributes(prop)
|
||||||
$USE_FLATS = prop['key'] < 0
|
$USE_FLATS = prop['key'] < 0
|
||||||
$DIVISIONS = prop['divisions']
|
$DIVISIONS = prop['divisions']
|
||||||
attr = REXML::Element.new('attributes')
|
attr = REXML::Element.new('attributes')
|
||||||
div = REXML::Element.new('divisions')
|
attr.add_element newTextElement('divisions', prop['divisions'])
|
||||||
div.add_text(prop['divisions'].to_s)
|
|
||||||
attr.add_element(div)
|
|
||||||
key = REXML::Element.new('key')
|
key = REXML::Element.new('key')
|
||||||
fifths = REXML::Element.new('fifths')
|
key.add_element newTextElement('fifths', prop['key'])
|
||||||
fifths.add_text(prop['key'].to_s)
|
key.add_element newTextElement('mode', prop['mode'] > 0 ? "major" : "minor")
|
||||||
key.add_element(fifths)
|
|
||||||
mode = REXML::Element.new('mode')
|
|
||||||
mode.add_text(prop['mode'] > 0 ? "major" : "minor")
|
|
||||||
key.add_element(mode)
|
|
||||||
attr.add_element(key)
|
attr.add_element(key)
|
||||||
time = REXML::Element.new('time')
|
time = REXML::Element.new('time')
|
||||||
beats = REXML::Element.new('beats')
|
time.add_element newTextElement('beats', prop['timeNum'])
|
||||||
beats.add_text(prop['timeNum'].to_s)
|
time.add_element newTextElement('beat-type', prop['timeDenom'])
|
||||||
time.add_element(beats)
|
|
||||||
beatType = REXML::Element.new('beat-type')
|
|
||||||
beatType.add_text(prop['timeDenom'].to_s)
|
|
||||||
time.add_element(beatType)
|
|
||||||
attr.add_element(time)
|
attr.add_element(time)
|
||||||
clef = REXML::Element.new('clef')
|
clef = REXML::Element.new('clef')
|
||||||
sign = REXML::Element.new('sign')
|
clef.add_element newTextElement('sign', 'G')
|
||||||
sign.add_text('G')
|
clef.add_element newTextElement('line', 2)
|
||||||
clef.add_element(sign)
|
|
||||||
line = REXML::Element.new('line')
|
|
||||||
line.add_text('2')
|
|
||||||
clef.add_element(line)
|
|
||||||
attr.add_element(clef)
|
attr.add_element(clef)
|
||||||
|
|
||||||
return attr
|
return attr
|
||||||
|
@ -109,45 +92,31 @@ def _note(pitch, dur, tied=0)
|
||||||
alt = STEPS[stp+1] == ?b
|
alt = STEPS[stp+1] == ?b
|
||||||
if alt
|
if alt
|
||||||
if $USE_FLATS
|
if $USE_FLATS
|
||||||
alt = "-1"
|
alt = -1
|
||||||
else
|
else
|
||||||
step = step == ?A ? ?G : step-1
|
step = step == ?A ? ?G : step-1
|
||||||
alt = "1"
|
alt = 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (tied & VL::InChord) != 0
|
if (tied & VL::InChord) != 0
|
||||||
note.add_element 'chord'
|
note.add_element 'chord'
|
||||||
end
|
end
|
||||||
pitch= REXML::Element.new('pitch')
|
pitch= REXML::Element.new('pitch')
|
||||||
st = REXML::Element.new('step')
|
pitch.add_element newTextElement('step', step.chr)
|
||||||
st.add_text(step.chr)
|
|
||||||
pitch.add_element(st)
|
|
||||||
if alt
|
if alt
|
||||||
a = REXML::Element.new('alter')
|
pitch.add_element newTextElement('alter', alt)
|
||||||
a.add_text(alt)
|
|
||||||
pitch.add_element(a)
|
|
||||||
end
|
end
|
||||||
o = REXML::Element.new('octave')
|
pitch.add_element newTextElement('octave', oct)
|
||||||
o.add_text(oct.to_s)
|
|
||||||
pitch.add_element(o)
|
|
||||||
note.add_element(pitch)
|
note.add_element(pitch)
|
||||||
end
|
end
|
||||||
d = REXML::Element.new('duration')
|
note.add_element newTextElement('duration', dur)
|
||||||
d.add_text(dur.to_s)
|
|
||||||
note.add_element(d)
|
|
||||||
if (tied & VL::TiedWithPrev) != 0
|
if (tied & VL::TiedWithPrev) != 0
|
||||||
t = REXML::Element.new('tie')
|
note.add_element 'tie', {'type' => 'stop' }
|
||||||
t.add_attribute('type', 'stop')
|
|
||||||
note.add_element(t)
|
|
||||||
end
|
end
|
||||||
if (tied & VL::TiedWithNext) != 0
|
if (tied & VL::TiedWithNext) != 0
|
||||||
t = REXML::Element.new('tie')
|
note.add_element 'tie', {'type' => 'start' }
|
||||||
t.add_attribute('type', 'start')
|
|
||||||
note.add_element(t)
|
|
||||||
end
|
end
|
||||||
voice = REXML::Element.new('voice')
|
note.add_element newTextElement('voice', 1)
|
||||||
voice.add_text("1")
|
|
||||||
note.add_element(voice)
|
|
||||||
|
|
||||||
return note
|
return note
|
||||||
end
|
end
|
||||||
|
@ -200,6 +169,14 @@ def _melody
|
||||||
|
|
||||||
lastProp = -1
|
lastProp = -1
|
||||||
measNum = 0
|
measNum = 0
|
||||||
|
repeat = [0]
|
||||||
|
INPUT['measures'].each do |meas|
|
||||||
|
r = 0
|
||||||
|
r |= 1 if meas['begin-repeat']
|
||||||
|
r |= 2 if meas['end-repeat']
|
||||||
|
repeat.push r
|
||||||
|
end
|
||||||
|
repeat.push 0
|
||||||
INPUT['measures'].each do |meas|
|
INPUT['measures'].each do |meas|
|
||||||
measNum += 1
|
measNum += 1
|
||||||
m = REXML::Element.new('measure')
|
m = REXML::Element.new('measure')
|
||||||
|
@ -208,6 +185,34 @@ def _melody
|
||||||
lastProp = meas['properties']
|
lastProp = meas['properties']
|
||||||
m.add_element(_attributes(INPUT['properties'][lastProp]))
|
m.add_element(_attributes(INPUT['properties'][lastProp]))
|
||||||
end
|
end
|
||||||
|
if meas['coda']
|
||||||
|
m.add_element 'sound', {'coda' => 'A'}
|
||||||
|
end
|
||||||
|
if meas['begin-repeat']
|
||||||
|
barline = REXML::Element.new('barline')
|
||||||
|
barline.add_attribute('location', 'left')
|
||||||
|
barline.add_element newTextElement('bar-style',
|
||||||
|
(repeat[measNum-1] & 2) != 0 ? 'heavy-heavy' : 'heavy-light')
|
||||||
|
barline.add_element 'repeat', {'direction' => 'forward'}
|
||||||
|
m.add_element(barline)
|
||||||
|
end
|
||||||
|
if ending = meas['begin-ending']
|
||||||
|
barline = REXML::Element.new('barline')
|
||||||
|
barline.add_attribute('location', 'left')
|
||||||
|
volta = ending['volta']
|
||||||
|
num = nil
|
||||||
|
(0..7).each do |i|
|
||||||
|
if (volta & (1<<i)) != 0
|
||||||
|
if num
|
||||||
|
num += ",#{i+1}"
|
||||||
|
else
|
||||||
|
num = (i+1).to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
barline.add_element 'ending', {'type' => 'start', 'number' => num}
|
||||||
|
m.add_element(barline)
|
||||||
|
end
|
||||||
meas['melody'].each do |note|
|
meas['melody'].each do |note|
|
||||||
dur = (note['durNum'] * $DIVISIONS * 4) / note['durDenom']
|
dur = (note['durNum'] * $DIVISIONS * 4) / note['durDenom']
|
||||||
n = _note(note['pitch'], dur, note['tied'])
|
n = _note(note['pitch'], dur, note['tied'])
|
||||||
|
@ -216,17 +221,45 @@ def _melody
|
||||||
if syll['text']
|
if syll['text']
|
||||||
lyr = REXML::Element.new('lyric')
|
lyr = REXML::Element.new('lyric')
|
||||||
lyr.add_attribute('number', stanza.to_s)
|
lyr.add_attribute('number', stanza.to_s)
|
||||||
sy = REXML::Element.new('syllabic')
|
lyr.add_element newTextElement('syllabic', SYLLABLE[syll['kind']])
|
||||||
sy.add_text(SYLLABLE[syll['kind']])
|
lyr.add_element newTextElement('text', syll['text'])
|
||||||
lyr.add_element(sy)
|
|
||||||
tx = REXML::Element.new('text')
|
|
||||||
tx.add_text(syll['text'])
|
|
||||||
lyr.add_element(tx)
|
|
||||||
n.add_element(lyr)
|
n.add_element(lyr)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
m.add_element(n)
|
m.add_element(n)
|
||||||
end
|
end
|
||||||
|
if r = meas['end-repeat']
|
||||||
|
barline = REXML::Element.new('barline')
|
||||||
|
barline.add_attribute('location', 'right')
|
||||||
|
barline.add_element newTextElement('bar-style',
|
||||||
|
(repeat[measNum+1] & 1) != 0 ? 'heavy-heavy' : 'light-heavy')
|
||||||
|
barline.add_element 'repeat', {'direction' => 'backward', 'times' => r['times'].to_s}
|
||||||
|
m.add_element(barline)
|
||||||
|
end
|
||||||
|
if ending = meas['end-ending']
|
||||||
|
barline = REXML::Element.new('barline')
|
||||||
|
barline.add_attribute('location', 'right')
|
||||||
|
barline.add_element newTextElement('bar-style',
|
||||||
|
(repeat[measNum+1] & 1) != 0 ? 'heavy-heavy' : 'light-heavy')
|
||||||
|
barline.add_element 'repeat', {'direction' => 'backward'}
|
||||||
|
volta = ending['volta']
|
||||||
|
num = nil
|
||||||
|
(0..7).each do |i|
|
||||||
|
if (volta & (1<<i)) != 0
|
||||||
|
if num
|
||||||
|
num += ",#{i+1}"
|
||||||
|
else
|
||||||
|
num = (i+1).to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
type = ending['last'] ? "discontinue" : "stop"
|
||||||
|
barline.add_element 'ending', {'type', type, 'number', num}
|
||||||
|
m.add_element(barline)
|
||||||
|
end
|
||||||
|
if meas['tocoda']
|
||||||
|
m.add_element 'sound', {'tocoda' => 'A'}
|
||||||
|
end
|
||||||
melody.add_element(m)
|
melody.add_element(m)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -108,13 +108,17 @@ void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
|
||||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
[NSNumber numberWithInt:times], @"times", nil]
|
[NSNumber numberWithInt:times], @"times", nil]
|
||||||
forKey: @"end-repeat"];
|
forKey: @"end-repeat"];
|
||||||
if (fSong->DoesEndEnding(m, &last, &volta))
|
if (fSong->DoesEndEnding(m+1, &last, &volta))
|
||||||
[md setObject:
|
[md setObject:
|
||||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
[NSNumber numberWithBool:!last], @"last",
|
[NSNumber numberWithBool:!last], @"last",
|
||||||
[NSNumber numberWithInt:volta], @"volta",
|
[NSNumber numberWithInt:volta], @"volta",
|
||||||
nil]
|
nil]
|
||||||
forKey: @"end-ending"];
|
forKey: @"end-ending"];
|
||||||
|
if (fSong->fGoToCoda == m)
|
||||||
|
[md setObject:[NSNumber numberWithBool:YES] forKey:@"tocoda"];
|
||||||
|
if (fSong->fCoda == m)
|
||||||
|
[md setObject:[NSNumber numberWithBool:YES] forKey:@"coda"];
|
||||||
[fMeasures addObject:md];
|
[fMeasures addObject:md];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user