mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 19:23:59 +00:00
Writes chords and notes in original format
This commit is contained in:
parent
e7ee4e301d
commit
0dbbf74640
|
@ -3,11 +3,15 @@
|
||||||
# VLMusicXMLType.write - Translate plist into MusicXML
|
# VLMusicXMLType.write - Translate plist into MusicXML
|
||||||
#
|
#
|
||||||
|
|
||||||
require File.dirname($0)+'plistReader'
|
require File.dirname($0)+'/plistReader'
|
||||||
|
require File.dirname($0)+'/vl'
|
||||||
require 'rexml/document'
|
require 'rexml/document'
|
||||||
|
|
||||||
INPUT = readPlist($stdin)
|
INPUT = readPlist($stdin)
|
||||||
|
|
||||||
|
$USE_FLATS = false
|
||||||
|
$DIVISIONS = 3
|
||||||
|
|
||||||
def _work
|
def _work
|
||||||
work = REXML::Element.new('work')
|
work = REXML::Element.new('work')
|
||||||
title = REXML::Element.new('work-title')
|
title = REXML::Element.new('work-title')
|
||||||
|
@ -26,10 +30,10 @@ def _identification
|
||||||
poet = REXML::Element.new('creator')
|
poet = REXML::Element.new('creator')
|
||||||
poet.add_attribute('type', 'poet')
|
poet.add_attribute('type', 'poet')
|
||||||
poet.add_text(INPUT['lyricist'])
|
poet.add_text(INPUT['lyricist'])
|
||||||
ident.add_element(lyricist)
|
ident.add_element(poet)
|
||||||
encoding = REXML::Element.new('encoding')
|
encoding = REXML::Element.new('encoding')
|
||||||
date = REXML::Element.new('encoding-date')
|
date = REXML::Element.new('encoding-date')
|
||||||
date.add_text(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 = REXML::Element.new('software')
|
||||||
software.add_text(INPUT['software'])
|
software.add_text(INPUT['software'])
|
||||||
|
@ -57,20 +61,175 @@ def _part_list
|
||||||
return part_list
|
return part_list
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def _attributes(prop)
|
||||||
|
$USE_FLATS = prop['key'] < 0
|
||||||
|
$DIVISIONS = prop['divisions']
|
||||||
|
attr = REXML::Element.new('attributes')
|
||||||
|
div = REXML::Element.new('divisions')
|
||||||
|
div.add_text(prop['divisions'].to_s)
|
||||||
|
attr.add_element(div)
|
||||||
|
key = REXML::Element.new('key')
|
||||||
|
fifths = REXML::Element.new('fifths')
|
||||||
|
fifths.add_text(prop['key'].to_s)
|
||||||
|
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)
|
||||||
|
time = REXML::Element.new('time')
|
||||||
|
beats = REXML::Element.new('beats')
|
||||||
|
beats.add_text(prop['timeNum'].to_s)
|
||||||
|
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)
|
||||||
|
clef = REXML::Element.new('clef')
|
||||||
|
sign = REXML::Element.new('sign')
|
||||||
|
sign.add_text('G')
|
||||||
|
clef.add_element(sign)
|
||||||
|
line = REXML::Element.new('line')
|
||||||
|
line.add_text('2')
|
||||||
|
clef.add_element(line)
|
||||||
|
attr.add_element(clef)
|
||||||
|
|
||||||
|
return attr
|
||||||
|
end
|
||||||
|
|
||||||
|
STEPS = 'C DbD EbE F GbG AbA BbB '
|
||||||
|
|
||||||
|
def _note(pitch, dur, tied=0)
|
||||||
|
note = REXML::Element.new('note')
|
||||||
|
if pitch == VL::NoPitch
|
||||||
|
note.add_element(REXML::Element.new('rest'))
|
||||||
|
else
|
||||||
|
oct = pitch/12 - 1
|
||||||
|
stp = 2*(pitch%12)
|
||||||
|
step = STEPS[stp]
|
||||||
|
alt = STEPS[stp+1] == ?b
|
||||||
|
if alt
|
||||||
|
if $USE_FLATS
|
||||||
|
alt = "-1"
|
||||||
|
else
|
||||||
|
step = step == ?A ? ?G : step-1
|
||||||
|
alt = "1"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (tied & VL::InChord) != 0
|
||||||
|
note.add_element 'chord'
|
||||||
|
end
|
||||||
|
pitch= REXML::Element.new('pitch')
|
||||||
|
st = REXML::Element.new('step')
|
||||||
|
st.add_text(step.chr)
|
||||||
|
pitch.add_element(st)
|
||||||
|
if alt
|
||||||
|
a = REXML::Element.new('alter')
|
||||||
|
a.add_text(alt)
|
||||||
|
pitch.add_element(a)
|
||||||
|
end
|
||||||
|
o = REXML::Element.new('octave')
|
||||||
|
o.add_text(oct.to_s)
|
||||||
|
pitch.add_element(o)
|
||||||
|
note.add_element(pitch)
|
||||||
|
end
|
||||||
|
d = REXML::Element.new('duration')
|
||||||
|
d.add_text(dur.to_s)
|
||||||
|
note.add_element(d)
|
||||||
|
if (tied & VL::TiedWithPrev) != 0
|
||||||
|
t = REXML::Element.new('tie')
|
||||||
|
t.add_attribute('type', 'stop')
|
||||||
|
note.add_element(t)
|
||||||
|
end
|
||||||
|
if (tied & VL::TiedWithNext) != 0
|
||||||
|
t = REXML::Element.new('tie')
|
||||||
|
t.add_attribute('type', 'start')
|
||||||
|
note.add_element(t)
|
||||||
|
end
|
||||||
|
voice = REXML::Element.new('voice')
|
||||||
|
voice.add_text("1")
|
||||||
|
note.add_element(voice)
|
||||||
|
|
||||||
|
return note
|
||||||
|
end
|
||||||
|
|
||||||
def _chords
|
def _chords
|
||||||
chords = REXML::Element.new('part')
|
chords = REXML::Element.new('part')
|
||||||
chords.add_attribute('id', 'HARM')
|
chords.add_attribute('id', 'HARM')
|
||||||
|
|
||||||
|
lastProp = -1
|
||||||
|
measNum = 0
|
||||||
INPUT['measures'].each do |meas|
|
INPUT['measures'].each do |meas|
|
||||||
|
measNum += 1
|
||||||
|
m = REXML::Element.new('measure')
|
||||||
|
m.add_attribute('number', measNum.to_s);
|
||||||
|
if meas['properties'] != lastProp
|
||||||
|
lastProp = meas['properties']
|
||||||
|
m.add_element(_attributes(INPUT['properties'][lastProp]))
|
||||||
|
end
|
||||||
|
meas['chords'].each do |chord|
|
||||||
|
dur = (chord['durNum'] * $DIVISIONS * 4) / chord['durDenom']
|
||||||
|
if chord['pitch'] == VL::NoPitch
|
||||||
|
m.add_element _note(VL::NoPitch, dur)
|
||||||
|
else
|
||||||
|
seenNote = 0
|
||||||
|
if chord['root'] != VL::NoPitch
|
||||||
|
m.add_element _note(chord['root'], dur)
|
||||||
|
seenNote = VL::InChord
|
||||||
|
end
|
||||||
|
pitch = chord['pitch']
|
||||||
|
steps = chord['steps']
|
||||||
|
(0..25).each do |step|
|
||||||
|
if (steps & (1<<step)) != 0
|
||||||
|
m.add_element _note(pitch+step, dur, seenNote)
|
||||||
|
seenNote = VL::InChord
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
chords.add_element(m)
|
||||||
end
|
end
|
||||||
|
|
||||||
return chords
|
return chords
|
||||||
end
|
end
|
||||||
|
|
||||||
|
SYLLABLE = %w[single begin end middle]
|
||||||
|
|
||||||
def _melody
|
def _melody
|
||||||
melody = REXML::Element.new('part')
|
melody = REXML::Element.new('part')
|
||||||
melody.add_attribute('id', 'MELO')
|
melody.add_attribute('id', 'MELO')
|
||||||
|
|
||||||
|
lastProp = -1
|
||||||
|
measNum = 0
|
||||||
|
INPUT['measures'].each do |meas|
|
||||||
|
measNum += 1
|
||||||
|
m = REXML::Element.new('measure')
|
||||||
|
m.add_attribute('number', measNum.to_s);
|
||||||
|
if meas['properties'] != lastProp
|
||||||
|
lastProp = meas['properties']
|
||||||
|
m.add_element(_attributes(INPUT['properties'][lastProp]))
|
||||||
|
end
|
||||||
|
meas['melody'].each do |note|
|
||||||
|
dur = (note['durNum'] * $DIVISIONS * 4) / note['durDenom']
|
||||||
|
n = _note(note['pitch'], dur, note['tied'])
|
||||||
|
stanza = 1
|
||||||
|
note['lyrics'].each do |syll|
|
||||||
|
if syll['text']
|
||||||
|
lyr = REXML::Element.new('lyric')
|
||||||
|
lyr.add_attribute('number', stanza.to_s)
|
||||||
|
sy = REXML::Element.new('syllabic')
|
||||||
|
sy.add_text(SYLLABLE[syll['kind']])
|
||||||
|
lyr.add_element(sy)
|
||||||
|
tx = REXML::Element.new('text')
|
||||||
|
tx.add_text(syll['text'])
|
||||||
|
lyr.add_element(tx)
|
||||||
|
n.add_element(lyr)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
m.add_element(n)
|
||||||
|
end
|
||||||
|
melody.add_element(m)
|
||||||
|
end
|
||||||
|
|
||||||
return melody
|
return melody
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ require 'rexml/document'
|
||||||
require 'rexml/streamlistener'
|
require 'rexml/streamlistener'
|
||||||
require 'base64'
|
require 'base64'
|
||||||
require 'date'
|
require 'date'
|
||||||
|
require 'time'
|
||||||
|
|
||||||
class PlistListener
|
class PlistListener
|
||||||
include REXML::StreamListener
|
include REXML::StreamListener
|
||||||
|
|
11
Filters/vl.rb
Normal file
11
Filters/vl.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#
|
||||||
|
# vl - VocalEasel
|
||||||
|
#
|
||||||
|
|
||||||
|
class VL
|
||||||
|
NoPitch = -128
|
||||||
|
|
||||||
|
TiedWithNext = 1
|
||||||
|
TiedWithPrev = 2
|
||||||
|
InChord = 4
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user