Implement endings, coda

This commit is contained in:
Matthias Neeracher 2007-08-27 00:10:37 +00:00
parent 0dbbf74640
commit 46c44d3bbd
2 changed files with 105 additions and 68 deletions

View File

@ -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

View File

@ -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];
} }