4 # Copyright (C) 2003 Rainer Typke
5 #pae2xml is licensed under the terms of the GNU General Public License Version
6 #2 as published by the <a href="http://www.fsf.org/" target="_top">Free Software Foundation</a>.
7 #This gives you legal permission to copy, distribute and/or modify <em>pae2xml</em> under
8 #certain conditions. Read
9 #the <a href="http://www.gnu.org/copyleft/gpl.html" target="_top">online version of the license</a>
10 #for more details. pae2xml is provided AS IS with NO WARRANTY OF ANY KIND,
11 #INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
16 $old_duration = $divisions;
19 ($mday, $mon, $year) = (localtime()) [3..5];
20 $encoding_date = sprintf("%4d-%02d-%02d", $year + 1900, $mon+1, $mday);
27 $p =~ s/\s*\=\=+\s*(.*?)\s*\=\=+\s*/$1/sg;
28 $p =~ s/\s*included.*?-------------*\s*(.*?)\s*/$1/s;
31 if ($q !~ /^.*1\.1\.1.*$/gsx && $r =~ /^.*plain.*$/gsx) {
32 print_error
("$a contains 'plain', but not 1.1.1!\n");
34 if ($p =~ /^\s*([^\n]+)\n(.*?)\n((\d+\.\d+\.\d.*?plain.*?\n)+)(.*?)\n?([^\n]+)\n([^\n]+)\s*$/gs) {
35 my ($comp, $title, $incipits, $sonst, $libsig, $rismsig) = ($1, $2, $3, $5, $6, $7);
43 RISM SIGN.: $rismsig\n\n";
44 parse_incipits
($incipits, $comp, $title, $sonst, $libsig, $rismsig);
46 else { if (index($p,"plain&easy") > -1) {
47 print_error
("Ignoring the following text:\n\n\n$p\n\n\n");
56 my ($incipits, $comp, $title, $sonst, $libsig, $rismsig) = @_;
58 $toprint .= "parsing: $incipits\n";
60 while ($incipits =~ /^(\d+\.\d+\..+?)(\d+\.\d+\..*)$/gs) {
63 parse_pe
($inc1, $comp, $title, $sonst, $libsig, $rismsig);
65 parse_pe
($incipits, $comp, $title, $sonst, $libsig, $rismsig);
69 my ($pe, $comp, $title, $sonst, $libsig, $rismsig) = @_;
71 $pe =~ s/@ü/@0ü/gs; # make missing time signature explicit
72 while ($pe =~ s/([^\-])(\d+)(\'|\,)(A|B|C|D|E|F|G)/$1$3$2$4/gs) {}; # octave first, then duration. Truly global.
74 if ($pe =~ /^\s*(\d+\.\d+\.\d)(\.|:)\s*(.*?)\nplain&easy:\s*(%([\w\-\d]+))?(@([\d\w\/]+))?\s
*&?\s
*(\
$([^ü
]+))?ü
(.*)$/gs
) {
75 my ($inr, $instr, $clef, $timesig, $keysig, $rest) = ($1, $3, $5, $7, $9, $10);
77 my $filename="$rismsig-$inr.xml";
78 $filename =~ s/RISM\s*A\/II\s*:?\s*//gs
;
79 print "Writing $filename...\n";
81 open(OUT
, ">$filename");
83 if ($clef =~ /^(\w)\-(\d)$/) {
84 ($clefsign, $clefline) = ($1, $2);
86 ($clefsign, $clefline) = ("G", 2);
89 $timesig = timesignature
($timesig);
91 my %fif=("", 0, "xF", 1, "xFC", 2, "xFCG",3, "xFCGD",4, "xFCGDA",5, "xFCGDAE",6, "xFCGDAEB",7, "bB",-1, "bBE",-2, "bBEA",-3, "bBEAD",-4, "bBEADG",-5, "bBEADGC",-6, "bBEADGCF",-7);
92 $keysig =~ s/(\s+)|&//gs; # it is unclear what the & means, so we'll ignore it for now.
93 $keysig =~ s/\[|\]//gs; # IGNORING brackets around a key sig.
94 $fifths = $fif{$keysig};
95 if ($fifths eq "") { $fifths = "0";
96 print_error
("Strange key signature '$keysig'.\n");}
98 foreach $_ ($rismsig,$title,$inr,$instr,$comp,$encoding_date,$libsig,$sonst)
103 print OUT
'<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
104 <!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 0.6 Partwise//EN" "file:/c:/Program Files/MusicXML/partwise.dtd">
107 <work-number>'.$rismsig.'</work-number>
108 <work-title>'.$title.'</work-title>
110 <movement-number>'.$inr.'</movement-number>
111 <movement-title>'.$instr.'</movement-title>
113 <creator type="composer">'.$comp.'</creator>
115 <software>pae2xml by R. Typke</software>
116 <encoding-date>'.$encoding_date.'</encoding-date>
118 <source>'.$libsig.'</source>
122 <part-name>'.$sonst.'</part-name>
128 <divisions>'.$divisions.'</divisions>
130 <fifths>'.$fifths.'</fifths>
134 <sign>'.$clefsign.'</sign>
135 <line>'.$clefline.'</line>
148 parse_notes
($rest, $keysig);
150 else { print_error
("could not parse $pe\n"); }
152 </score-partwise>\n";
158 my ($notes, $keysig) = @_;
159 my $qq = 0; # in group of cue notes
161 my $meas = 2; # measure number
162 my $mopen = 1; # measure tag still open
164 if ($notes =~ /^\s*(.*?)\s*$/) {
168 $notes =~ s/!([^!]*)!/$1$1/gs; # write out repetitions
169 $notes =~ s/\{([^\}]*)\}/$1/gs; # ignore beamings
171 $notes =~ s/(\d+)\(([^;]+\))/\($1$2/gs; # pull note lengths into fermatas or triplets
172 $notes =~ s/(xx|x|bb|b|n)\(/\($1/gs; # pull accidentals into tuplets or fermatas:
173 $notes =~ s/(\d+)(xx|x|bb|b|n)(A|B|C|D|E|F|G)/$2$1$3/gs; # accidentals first, then duration
175 # $notes =~ s/x\(/\(x/gs; # pull accidentals into tuplets or fermatas
176 # $notes =~ s/bb\(/\(bb/gs; # pull accidentals into tuplets or fermatas
177 # $notes =~ s/b\(/\(b/gs; # pull accidentals into tuplets or fermatas
178 # $notes =~ s/n\(/\(n/gs; # pull accidentals into tuplets or fermatas
179 # $notes =~ s/(\'+|\,+)\(/\($1/g; # pull octave marks into tuplets or fermatas
181 $notes =~ s/(\.|\d|\,|\')qq/qq$1/gs; # pull beginning mark of group of grace notes in front of corresponding notes
182 $notes =~ s/(xx|x|bb|b|n)qq/qq$1/gs; # qq first, then parts of notes
184 $notes =~ s/\=(\d)/$1/gs; # replace multibar rests #n with just n
186 while ($notes ne "") {
187 if ($notes =~ /^(\'+|\,+)(.*)$/) {
188 ($oct, $notes) = ($1, $2);
190 } elsif ($notes =~ /^qq(.*)$/) {
193 } elsif ($notes =~ /^r(.*)$/) {
196 } elsif ($notes =~ /^(\d+|\=)(\/.*)$/) {
199 if ($measrest eq '=') {
202 $toprint .= "$measrest measures of rest.\n";
203 for $n (1..$measrest) {
206 <duration>'.($beats*$divisions*4/$beattype).'</duration
>
207 '.# <type>quarter</type>
211 if ($n < $measrest) {
212 print OUT " </measure>\n";
214 print OUT ' <measure number
="'.$meas.'">
220 } elsif ($notes =~ /^((\,|\')*(x|xx|b|bb|n)?\d*\.*(g|q)?(\-|A|B|C|D|E|F|G)t?\+?)(.*)$/) { # a note
221 ($note, $notes) = ($1,$6);
222 parse_note($note, $keysig, "", "", $qq);
223 } elsif ($notes =~ /^(\((\,|\')*(x|xx|b|bb|n)?\d*\.*(g|q)?(\-|A|B|C|D|E|F|G)t?\+?\))(.*)$/) { # one note with a fermata
224 ($note, $notes) = ($1,$6);
225 parse_note($note, $keysig, "", "", $qq);
226 } elsif ($notes =~ /^(\(((\,|\')*(x|xx|b|bb|n)?\d*\.*(g|q)?(\-|A|B|C|D|E|F|G)t?\+?){3}\))(.*)$/) { # a triplet
227 ($triplet, $notes) = ($1,$7);
228 # print "TRIPLET: ".$triplet." -> ";
229 $triplet =~ /^\(((\,|\')*(x|xx|b|bb|n)?\d*\.*(g|q)?(\-|A|B|C|D|E|F|G)t?\+?)(.*)\)$/gs;
230 ($note, $triplet) = ($1,$6);
231 #print "$note $triplet\n";
232 parse_note($note, $keysig, '<tuplet type
="start"/>', ' <time-modification
>
233 <actual
-notes
>3</actual
-notes
>
234 <normal
-notes
>2</normal
-notes
>
235 </time-modification
>', $qq);
236 $triplet =~ /^((\,|\')*(x|xx|b|bb|n)?\d*\.*(g|q)?(\-|A|B|C|D|E|F|G)t?\+?)(.*)$/gs;
237 ($note, $triplet) = ($1,$6);
238 #print "$note $triplet\n";
239 parse_note($note, $keysig, '', ' <time-modification
>
240 <actual
-notes
>3</actual
-notes
>
241 <normal
-notes
>2</normal
-notes
>
242 </time-modification
>', $qq);
243 parse_note($triplet, $keysig, '<tuplet type
="stop"/>', ' <time-modification
>
244 <actual
-notes
>3</actual
-notes
>
245 <normal
-notes
>2</normal
-notes
>
246 </time-modification
>', $qq);
247 } elsif ($notes =~ /^((\d+)\(((\,|\')*(x|xx|b|bb|n)?\d*\.*(g|q)?(\-|A|B|C|D|E|F|G)t?\+?)+\;(\d+)\))(.*)$/) { # an n-tuplet
248 ($tuplet, $notes) = ($1,$9);
249 # print "N-TUPLET: ".$tuplet." -> ";
250 $tuplet =~ /^(\d+)\(((\,|\')*(x|xx|b|bb|n)?\d*\.*(g|q)?(\-|A|B|C|D|E|F|G)t?\+?)(.*);(\d)\)$/gs;
251 ($combdur, $note, $tuplet, $numval) = ($1,$2,$7,$8);
252 #print "i=$combdur, n=$numval; $note / $tuplet\n";
253 my $ind_dur = duration($combdur)/$numval;
255 my $act_notes = $numval;
256 parse_note($note, $keysig, '<tuplet type
="start"/>', ' <time-modification
>
257 <actual
-notes
>'.$act_notes.'</actual
-notes
>
258 <normal
-notes
>1</normal
-notes
>
259 </time-modification
>', $qq);
260 while ($tuplet =~ /^((\,|\')*(x|xx|b|bb|n)?\d*\.*(g|q)?(\-|A|B|C|D|E|F|G)t?\+?)(.+)$/gs) {
261 ($note, $tuplet) = ($1,$6);
262 #print "$note / $tuplet\n";
263 parse_note($note, $keysig, '', ' <time-modification
>
264 <actual
-notes
>'.$act_notes.'</actual
-notes
>
265 <normal
-notes
>1</normal
-notes
>
266 </time-modification
>', $qq);
268 parse_note($tuplet, $keysig, '<tuplet type
="stop"/>', ' <time-modification
>
269 <actual
-notes
>'.$act_notes.'</actual
-notes
>
270 <normal
-notes
>1</normal
-notes
>
271 </time-modification
>', $qq);
272 } elsif ($notes =~ /^(%\w-\d)(.*)$/) {
273 ($clef,$notes) = ($1,$2);
274 $clef =~ /^%(\w)\-(\d)$/;
275 ($clefsign, $clefline) = ($1, $2);
276 print OUT ' <attributes
>
278 <sign
>'.$clefsign.'</sign
>
279 <line
>'.$clefline.'</line
>
283 } elsif ($notes =~ /^@(\d\/\d|c\/?)\s*(.*)$/) {
285 ($timesig,$notes) = ($1,$2);
286 #print "-> $timesig / $notes\n"; exit;
287 $timesig = timesignature($timesig);
288 print OUT " <attributes>\n$timesig
290 } elsif ($notes =~ /^\/(.*)$/) {
292 if ($notes =~ /^\/(.*)$/) {
294 print OUT ' <barline location
="right">
295 <bar
-style
>light
-light
</bar
-style
>
300 print OUT " </measure>\n";
302 print OUT ' <measure number
="'.$meas.'">
308 $toprint .= "bar line\n";
309 } #elsif ($notes =~ /^(\d*\.*\-)(.*)$/) {
310 #($rst, $notes) = ($1, $2);
311 #$toprint .= "rest: $rst\n";
312 #$rst =~ /^(\d*)(\.*)\-$/;
313 #($rst, $dots) =($1,$2);
316 # <duration>'.duration($rst, $dots).'</duration>
317 #'.# <type>quarter</type>
321 elsif ($notes =~ /^\((\=)\)(.*)$/) { # a bar of rest with a fermata
322 ($rst, $notes) = ($1, $2);
323 $toprint .= "rest: $rst\n";
326 <duration>'.($beats*$divisions*4/$beattype).'</duration
>
327 '.# <type>quarter</type>
329 <fermata type
="upright"/>
334 elsif ($notes =~ s/(\d+\.*)\(((\,|\')*(x|xx|b|bb|n)?\d*\.*(g|q)?(\-|A|B|C|D|E|F|G)t?\+?)\)/\($1$2\)/gs) { # pull duration into fermata parentheses
335 # print "after replacement: $notes\n"; exit;
338 print_error("got stuck with $notes\n");
343 print OUT " </measure>\n";
349 my($note, $keysig, $notation, $addition, $in_qq_group) = @_;
352 my ($actualnotes, $normalnotes) = (1,1);
354 if ($addition =~ /^\s*<time-modification>\s*<actual-notes>\s*(\d+)\s*<\/actual-notes>\s*<normal-notes>\s*(\d+)\s*<\/normal-notes>\s*<\/time-modification>\s*$/) {
355 ($actualnotes, $normalnotes) = ($1, $2);
358 if ($note =~ /^\((.*)\)$/) {
363 $note =~ /^((\,|\')*)(x|xx|b|bb|n)?(\d*)(\.*)(g|q)?(\-|A|B|C|D|E|F|G)(t?)(\+?)$/;
364 my ($oct, $acc, $dur, $dot, $gracecue, $pitch, $trill, $tie) = ($1, $3, $4, $5, $6, $7, $8, $9);
368 if ($gracecue eq "g") {
369 print OUT ' <grace steal
-time-following
="33"/>
372 if ($gracecue eq "q" || $in_qq_group) {
377 print OUT " <rest />\n";
380 <step
>'.$pitch.'</step
>
382 alter($pitch, $acc, $keysig).'
383 <octave
>'.octave($oct).'</octave
>
387 if ($gracecue ne "g") {
388 print OUT ' <duration
>'.(duration($dur, $dot)*$normalnotes/$actualnotes).'</duration
>
391 # <type>quarter</type>
396 print OUT '<tie type
="start"/>
401 print OUT '<tie type
="stop"/>
409 my $notationbracket = $fermata || ($trill eq "t") || ($notation ne "");
410 if ($notationbracket) {
411 print OUT " <notations>\n";
413 if ($fermata) { print OUT '
414 <fermata type
="upright"/>'."\n"; }
415 if ($trill eq "t") { print OUT ' <ornaments
>
420 if ($notation ne "") {
421 print OUT " $notation\n";
423 if ($notationbracket) {
424 print OUT " </notations>\n";
430 $toprint .= "note: oct. $oct/acc. $acc/dur. $dur/dots $dot/grace,cue $gracecue/pitch $pitch\n";
434 my ($pitch, $acc, $keysig) = @_;
438 if (index ($keysig,$pitch) > -1) {
439 $keysig =~ /^(.).*$/gs;
445 my %acc_alt = ("n", 0, "b", -1, "bb", -2, "x", 1, "xx", 2);
446 if ($acc_alt{$acc} ne "") {
447 $alt = $acc_alt{$acc};
451 return "<alter>$alt</alter>\n";
457 my ($duration, $dots) = @_;
459 if ($duration.$dots ne "") {
460 my %du=("1",4*$divisions,"2",2*$divisions,"4",$divisions,
461 "8",$divisions/2,"6",$divisions/4,"3",$divisions/8,
462 "5",$divisions/16,"7",$divisions/32,
463 "9",$divisions*8,"0",$divisions*16); # breve/long
464 $old_duration = $du{$duration};
465 if ($old_duration eq "") {
466 print_error("strange duration '$duration'\n");
468 my $add = $old_duration;
469 while ($dots ne "") {
471 $old_duration += $add;
472 $dots =~ /^.(.*)$/gs;
476 return $old_duration;
483 $octave =~ /^(.)(.*)$/gs;
485 $old_octave = 4 - length $octave;
487 $old_octave = 3 + length $octave;
496 if ($timesig eq "c3") {
497 $timesig = "3/2"; # it would be better to display it as "C". Example: 451.023.814
499 if ($timesig =~ /^c(\d+)\/(\d+)$/gs) {
500 $timesig = "$1/$2"; # it would be better to show the "C"
503 if ($timesig eq "0" || $timesig eq "") { # unclear how to handle absence of time signature.
504 $timesig ='<time symbol
="common">
506 <beat
-type
>4</beat
-type
>
508 '; # using 4/4 for now.
509 ($beats, $beattype) = (4,4);
510 } elsif ($timesig =~ /^c(\/?)$/gi) {
512 $timesig = '<time symbol
="cut">
514 <beat
-type
>2</beat
-type
>
517 ($beats, $beattype) = (2,2);
519 $timesig = '<time symbol
="common">
521 <beat
-type
>4</beat
-type
>
524 ($beats, $beattype) = (4,4);
526 } elsif ($timesig =~ /^(\d+)\/(\d+)$/gs) {
527 ($beats, $beattype) = ($1, $2);
529 <beats
>'.$beats.'</beats
>
530 <beat
-type
>'.$beattype.'</beat
-type
>
534 print_error("Time signature '$timesig' looks strange.\n");
535 # $timesig = ""; we assume 4/4 just to get something legible:
536 ($beats, $beattype) = (4,4);
538 <beats
>'.$beats.'</beats
>
539 <beat
-type
>'.$beattype.'</beat
-type
>
549 print "\nAn error occurred; context:\n\n$toprint\n
560 while (<FH>) { $res .= $_; } # read all lines