Lilypond import works, without repeats & lyrics

This commit is contained in:
Matthias Neeracher 2007-09-10 08:25:22 +00:00
parent 698d9964a8
commit 0433ef8fb3
5 changed files with 144 additions and 21 deletions

View File

@ -16,7 +16,7 @@ OUTPUT = {'measures' => []}
tokens = []
$stdin.each do |line|
line.chomp!.sub!(/%.*/, "")
line.scan(/\G\s*(\{|\}|\(|\)|\||=|~|<<|>>|#'|#\(|##t|##f|\\\w+|\".*?\"|[-+\w\d.',:]+|.)/) do |token|
line.scan(%r$\G\s*(\{|\}|\(|\)|\||=|~|<<|>>|#'|#\(|##t|##f|\\\w+|\".*?\"|\w[-+\w\d.',:*/]+|.)$) do |token|
tokens.push(token[0])
end
end
@ -51,7 +51,7 @@ PITCH = {
}
def lyPitch(pitch, base=-1)
if !pitch || pitch =~ /[rs]/
if !pitch || pitch =~ /^[rs]/
return VL::NoPitch
end
p = PITCH[pitch[0]] || 0
@ -63,7 +63,7 @@ def lyPitch(pitch, base=-1)
end
$RELPITCH = p
else
p += 60
p += 48
end
pitch.scan(/'/) {|c| p += 12}
pitch.scan(/,/) {|c| p -= 12}
@ -78,12 +78,18 @@ def lyPitch(pitch, base=-1)
end
def lyDur(dur)
dur =~ /^(\d+)(?:\*(\d+).(\d+))?/
dur =~ /^(\d+)(\.*)(?:\*(\d+).(\d+))?/
num = 1
den = $1.to_i
if $2
num *= $2.to_i
den *= $3.to_i
if $2.length > 0
(0...$2.length).each do |x|
den = 2*den
num = 2*num+1
end
end
if $3
num *= $3.to_i
den *= $4.to_i
end
return [num,den]
end
@ -147,20 +153,20 @@ MINORKEY = [
];
def lySteps(steps)
steps =~ /^(|m|maj|dim7?|aug|sus[42]?)/
steps =~ /^(maj|dim7?|aug|sus[42]?|m|)/
s = STEPS[$1]
steps = $'
if !($1 =~ /\d/) && steps =~ /^(7|9|11|13)/
if !(s & VL::Maj7th)
if !($1 =~ /\d$/) && steps =~ /^(7|9|11|13)/
if (s & VL::Maj7th) == 0
s |= VL::Min7th
end
case $1
when '9'
s |= VL::Maj9th
when '11'
s |= VL::Maj9th+VL::Maj11th
s |= VL::Maj9th+VL::Eleventh
when '13'
s |= VL::Maj9th+VL::Maj11th+VL::Maj13th
s |= VL::Maj9th+VL::Eleventh+VL::Maj13th
end
steps = $'
end
@ -213,7 +219,7 @@ while tokens.length > 0
[a-g](?:[ei]?s)? # g, ges, fis, es, as
)
(\d+ # 1, 2, 4, 8, 16 ...
(?:\*\d+/\d+)? # *3/4
\.*(?:\*\d+/\d+)? # ., *3/4
)?
(?:\:([-+^:.a-z\d]+))? # :maj9.7-^2
(?:/\+( # /+
@ -242,11 +248,11 @@ while tokens.length > 0
[a-g](?:[ei]?s)? # g, ges, fis, es, as
[',]* # g'''
)
(\d+ # 1, 2, 4, 8, 16 ...
(\d+\.* # 1, 2, 4, 8, 16 ...
(?:\*\d+/\d+)? # *3/4
)?
$}x
pitch = lyPitch($1, 60)
pitch = lyPitch($1)
dur = $2 || lastDur
lastDur = dur
d = lyDur(dur)
@ -295,8 +301,8 @@ while tokens.length > 0
level = nestLevel
when '\time'
if tokens[0] =~ %r{(\d+)/(\d+)}
timeNum = $1
timeDenom = $2
timeNum = $1.to_i
timeDenom = $2.to_i
tokens[0..0] = nil
end
if block != 'voice'
@ -315,6 +321,63 @@ while tokens.length > 0
end
end
measureLen = VL::Fract.new(timeNum, timeDenom)
#
# Make measures
#
measCount= -1
measures = []
while notes.size > 0 || chords.size > 0
measCount += 1
meas = {}
meas['measure'] = measCount
meas['properties'] = 0
if chords.size > 0
mchords = []
len = VL::Fract.new(0, 1)
while len < measureLen && chords.size > 0
chord = chords.shift
chordLen = VL::Fract.new(chord['durNum'], chord['durDenom'])
if len+chordLen > measureLen
remLen = len+chordLen-measureLen
chordLen -= remLen
remChord = chord.dup
remChord['durNum'] = remLen.num
remChord['durDenom'] = remLen.denom
chords.unshift(remChord)
end
mchords.push(chord)
len += chordLen
end
meas['chords'] = mchords
end
if notes.size > 0
mnotes = []
len = VL::Fract.new(0, 1)
while len < measureLen && notes.size > 0
note = notes.shift
noteLen = VL::Fract.new(note['durNum'], note['durDenom'])
if len+noteLen > measureLen
remLen = len+noteLen-measureLen
noteLen -= remLen
remNote = note.dup
remNote['durNum'] = remLen.num
remNote['durDenom'] = remLen.denom
remNote['tied'] = (remNote['tied'] || 0) | VL::TiedWithPrev
note['tied'] = (note['tied'] || 0) | VL::TiedWithNext
notes.unshift(remNote)
end
mnotes.push(note)
len += noteLen
end
meas['melody'] = mnotes
end
measures.push(meas)
end
OUTPUT['measures'] = measures
OUTPUT['properties'] = [{
'divisions' => divisions,
'key' => key,

View File

@ -79,4 +79,53 @@ class VL
Sus4 = VL::Unison+VL::Fourth+VL::Fifth
Sus2 = VL::Unison+VL::Maj2nd+VL::Fifth
end
class Fract
include Comparable
def initialize(num, denom)
@num = num
@denom = denom
normalize()
end
def num
return @num
end
def denom
return @denom
end
def _gcd(x, y)
while y != 0
x,y = [y, x % y]
end
return x
end
def normalize
g = _gcd(@num, @denom)
@num /= g
@denom /= g
end
def -()
return Fract.new(-@num, @denom)
end
def +(other)
return Fract.new(@num*other.denom+other.num*@denom, @denom*other.denom)
end
def -(other)
return Fract.new(@num*other.denom-other.num*@denom, @denom*other.denom)
end
def <=>(other)
return @num*other.denom <=> other.num*@denom
end
end
end

View File

@ -14,6 +14,7 @@
#import "VLMMADocument.h"
#import "VLMIDIDocument.h"
#import "VLPDFDocument.h"
#import "VLPListDocument.h"
#import "VLPDFWindow.h"
#import "VLLogWindow.h"
#import "VLSheetWindow.h"
@ -352,6 +353,12 @@
if ([typeName isEqual:@"VLNativeType"] || [typeName isEqual:@"VLMusicXMLType"]) {
return [self readFromXMLFileWrapper:wrapper error:outError];
} else if ([typeName isEqual:@"VLLilypondType"]) {
if ([self readFromFileWrapper:wrapper withFilter:typeName error:outError]) {
[self setFileURL:nil];
return YES;
} else
return NO;
} else {
if (outError)
*outError = [NSError errorWithDomain:NSCocoaErrorDomain

View File

@ -432,7 +432,7 @@ advanceAt:
[NSException raise:NSInvalidArgumentException
format:@"Filter %@: %@", filterName, errStr];
}
return output;
}
@ -469,9 +469,9 @@ advanceAt:
mutabilityOption:NSPropertyListImmutable
format:NULL errorDescription:&errString];
if (!outPlist)
return NO;
else
return [self readFromPlist:outPlist error:outError];
[NSException raise:NSInvalidArgumentException
format:@"Plist %@: %@", filterName, errString];
return [self readFromPlist:outPlist error:outError];
}
@end

View File

@ -24,6 +24,7 @@
95049CF30BDC32EB0015EE6E /* installLilypond.scpt in Resources */ = {isa = PBXBuildFile; fileRef = 95049CF20BDC32CD0015EE6E /* installLilypond.scpt */; };
95049D020BDC436A0015EE6E /* installPython.scpt in Resources */ = {isa = PBXBuildFile; fileRef = 95049D010BDC43510015EE6E /* installPython.scpt */; };
950795E10B4A34D9008911A6 /* stop.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 950795E00B4A34D9008911A6 /* stop.tiff */; };
95140E3C0C944F7F00966576 /* VLLilypondType.reader in Copy Filters */ = {isa = PBXBuildFile; fileRef = 95140E3B0C944F7F00966576 /* VLLilypondType.reader */; };
9524DAFB0BE569C50002AC03 /* Help in Resources */ = {isa = PBXBuildFile; fileRef = 9524DAF70BE569C50002AC03 /* Help */; };
9524DB390BE5CA070002AC03 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9524DB380BE5CA070002AC03 /* Carbon.framework */; };
952CBB9C095FD1CA00434E43 /* VLSoundOut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 952CBB9A095FD1CA00434E43 /* VLSoundOut.cpp */; };
@ -136,6 +137,7 @@
dstPath = Filters;
dstSubfolderSpec = 7;
files = (
95140E3C0C944F7F00966576 /* VLLilypondType.reader in Copy Filters */,
95795CE60C88B25D00E4A21F /* vl.rb in Copy Filters */,
95795CE70C88B25D00E4A21F /* VLMusicXMLType.reader in Copy Filters */,
95EF921A0C786CB90093E5F4 /* plistReader.rb in Copy Filters */,
@ -174,6 +176,7 @@
95049CF20BDC32CD0015EE6E /* installLilypond.scpt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.scpt; name = installLilypond.scpt; path = Resources/installLilypond.scpt; sourceTree = "<group>"; };
95049D010BDC43510015EE6E /* installPython.scpt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.scpt; name = installPython.scpt; path = Resources/installPython.scpt; sourceTree = "<group>"; };
950795E00B4A34D9008911A6 /* stop.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = stop.tiff; path = Resources/stop.tiff; sourceTree = "<group>"; };
95140E3B0C944F7F00966576 /* VLLilypondType.reader */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = VLLilypondType.reader; sourceTree = "<group>"; };
9524DAF70BE569C50002AC03 /* Help */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Help; path = Resources/Help; sourceTree = "<group>"; };
9524DB380BE5CA070002AC03 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
952CBB98095FD19D00434E43 /* TVLSoundOut */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TVLSoundOut; sourceTree = BUILT_PRODUCTS_DIR; };
@ -539,6 +542,7 @@
95795CE40C88B25D00E4A21F /* vl.rb */,
95795CE50C88B25D00E4A21F /* VLMusicXMLType.reader */,
95EF92270C78E9390093E5F4 /* VLMusicXMLType.writer */,
95140E3B0C944F7F00966576 /* VLLilypondType.reader */,
95EF92120C786B2C0093E5F4 /* plistReader.rb */,
95EF92130C786B2C0093E5F4 /* plistWriter.rb */,
);