mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 11:14:00 +00:00
Lilypond import works, without repeats & lyrics
This commit is contained in:
parent
698d9964a8
commit
0433ef8fb3
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */,
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue
Block a user