Re: [abcusers] abcmac - BarFly-style abc macro preprocessor in Perl
On Wed, Aug 15, 2001 at 11:59:45PM +0100, Jack Campin wrote: | > I wasn't able to test the script, unfortunately. MacPerl has got itself | > into a fankle [...] Us Mac users don't have a lot of fun with perl. | > Every time I try to use it I end up concluding that it would be quicker | > to write a program in C or Pascal to do the job. | | I think I've got three versions of MacPerl sitting around on my machines | and none of them ever worked. Python anybody? That does work on the Mac. I'm a big Python fan myself. Unfortunately I don't have much spare time to learn music, notation and code right now. If you just want a quick-n-dirty preprocessor prototype I could probably make one if I know exactly how the inputs and outputs are to be formatted. -D To subscribe/unsubscribe, point your browser to: http://www.tullochgorm.com/lists.html
Re: [abcusers] abcmac - BarFly-style abc macro preprocessor in Perl
[EMAIL PROTECTED] (Phil Taylor) writes: > >I'm confused now. Suppose I had definitions for `Mn' and `Mn2'. What > >would happen (a) for `Mc' (b) for `Mc2' (c) for `Mc4' in the body of > >a tune? The interesting point is whether the `n' includes a length or > >not. > > (a) and (b) will expand, (c) will not, since there is no macro definition > for that length. 'n' does not itself include the length, but the length > (if any) is part of the target string. So in (a) and (b) the replacement of `n' is `c', and any length specifications are taken from the right-hand side of the macro definition (the `target string', if I understand you correctly). This is what my current implementation does (phew). > Actually, thinking about this some more, it would be possible to sort > the macro definitions into order before expanding them, provided that > you used a sort algorithm which is guaranteed not to change the order > of elements which are the same size. Since the list of macros to be > expanded is never going to be very big you could just use a simple bubble > sort. It's no problem simply to do the replacements in reverse order of occurrence. Actually it simplifies my code considerably. The sorting business came in because my very first version processed the replacements in order of occurrence (rather than reverse order), which obviously didn't work with Jack's example, which was all that I had to go on at the time. I didn't know about the reverse-order constraint until later, and I'm perfectly happy with it if you are. As I said, the version on my web page does the reverse-order thing already. > Us Mac users don't have a lot of fun with perl. Every > time I try to use it I end up concluding that it would be quicker > to write a program in C or Pascal to do the job. Yes, but you Mac users have BarFly to begin with. I could have coded the macro preprocessor in C (no Pascal, please ...) but it would have taken me a lot longer than the two hours or so that I have spent on it so far. Anselm -- Anselm Lingnau .. [EMAIL PROTECTED] The problem is the browser bosses spend way too long listening to the young sprouts in suits in the marketing departments who can barely add 2+2 instead of listening to real users. -- Peter Flynn, on math support in Web browsers To subscribe/unsubscribe, point your browser to: http://www.tullochgorm.com/lists.html
Re: [abcusers] abcmac - BarFly-style abc macro preprocessor in Perl
Anselm Lingnau wrote: >Phil Taylor wrote: > >> BarFly's macro processor does take lengths. You have to write >> a separate macro for each length of note. The reason for this >> is that an ornament which sounds right on a half note is often >> wrong on an eighth. > >I'm confused now. Suppose I had definitions for `Mn' and `Mn2'. What >would happen (a) for `Mc' (b) for `Mc2' (c) for `Mc4' in the body of >a tune? The interesting point is whether the `n' includes a length or >not. (a) and (b) will expand, (c) will not, since there is no macro definition for that length. 'n' does not itself include the length, but the length (if any) is part of the target string. >> What the current Barfly version >> does when it encounters a macro on a note with an accidental is to place >> the accidental on the first ocurrence of the principal note in the >> expansion. [...] >> >> BarFly doesn't do this; rather it expands the macros in reverse order >> to the order in which the definitions are listed. Actually, thinking about this some more, it would be possible to sort the macro definitions into order before expanding them, provided that you used a sort algorithm which is guaranteed not to change the order of elements which are the same size. Since the list of macros to be expanded is never going to be very big you could just use a simple bubble sort. >I've put a version of abcmac which is fixed in these two respects on my >web page at `http://anselm.our-isp.org/abcmac/abcmac'. > >> Maybe we can get abc2midi to process the Goldberg Variations? > >We could try ... > If there's the possibility of other programs handling the macros, I'll fix the V: fields to be inline once I release the next version of BarFly (the current version won't work with that syntax). The postscript programs will still only be able to display it with the ornaments written out in full, which is highly illegible. I wasn't able to test the script, unfortunately. I had installed a new hard drive in my machine and simply copied all my stuff over to it. MacPerl has got itself into a fankle and can't find its libraries any more (perl5lib not found in @IN), despite the fact that perl5lib is certainly there, and the correct pathname is in the preferences. I downloaded and installed a new version which comes as a single standalone application, with all the libraries compiled in, and that didn't work either, objecting to 'strict', right at the beginning of the script. Us Mac users don't have a lot of fun with perl. Every time I try to use it I end up concluding that it would be quicker to write a program in C or Pascal to do the job. Phil Taylor To subscribe/unsubscribe, point your browser to: http://www.tullochgorm.com/lists.html
Re: [abcusers] abcmac - BarFly-style abc macro preprocessor in Perl
Phil Taylor wrote: > BarFly's macro processor does take lengths. You have to write > a separate macro for each length of note. The reason for this > is that an ornament which sounds right on a half note is often > wrong on an eighth. I'm confused now. Suppose I had definitions for `Mn' and `Mn2'. What would happen (a) for `Mc' (b) for `Mc2' (c) for `Mc4' in the body of a tune? The interesting point is whether the `n' includes a length or not. > What the current Barfly version > does when it encounters a macro on a note with an accidental is to place > the accidental on the first ocurrence of the principal note in the > expansion. [...] > > BarFly doesn't do this; rather it expands the macros in reverse order > to the order in which the definitions are listed. I've put a version of abcmac which is fixed in these two respects on my web page at `http://anselm.our-isp.org/abcmac/abcmac'. > Maybe we can get abc2midi to process the Goldberg Variations? We could try ... Anselm -- Anselm Lingnau .. [EMAIL PROTECTED] As an adolescent I aspired to lasting fame, I craved factual certainty, and I thirsted for a meaningful vision of human life -- so I became a scientist. This is like becoming an archbishop so you can meet girls.-- M. Cartmill To subscribe/unsubscribe, point your browser to: http://www.tullochgorm.com/lists.html
Re: [abcusers] abcmac - BarFly-style abc macro preprocessor in Perl
Hi Anselm, ># abcmac -- Barfly-style macro preprocessor for ABC files. Neat! Here are a few comments. ># Currently the argument is a note name (no length). BarFly's macro processor does take lengths. You have to write a separate macro for each length of note. The reason for this is that an ornament which sounds right on a half note is often wrong on an eighth. ># Transpose note `$base' according to the relative position of `$note' ># compared to `n' -- e.g., $base = 'A', $note = 'o' gives 'B'. Don't bother ># dealing with accidentals, since BarFly doesn't either. My web page is a bit out of date there. What the current Barfly version does when it encounters a macro on a note with an accidental is to place the accidental on the first ocurrence of the principal note in the expansion. This seems to be the right thing to do in the majority of cases. Older versions of the program didn't expand macros for notes with an accidental, and you had to write a separate static macro for them. > # Construct a sequence of expansion commands for the macros. > # Make sure to expand longer-named macros first, to avoid > # replacing `On' before `On/' BarFly doesn't do this; rather it expands the macros in reverse order to the order in which the definitions are listed. It is the user's responsibility to enter lists of macros with the shorter ones first. The reason for this is that it is very useful to have macros override one another, e.g. you might want an ornament on one particular pitch of note to play differently from the others, or one tune in a file to have a different set of ornaments from those defined globally. In order to make this work you have to deal with macros in a fixed order. I don't have MacPerl on the machine I'm on at the moment, so I can't try it out, but I will do so later. Maybe we can get abc2midi to process the Goldberg Variations? Phil Taylor To subscribe/unsubscribe, point your browser to: http://www.tullochgorm.com/lists.html
Re: [abcusers] abcmac - BarFly-style abc macro preprocessor in Perl
Anselm Lingnau wrote: > > All right, everybody, please forget the simple-minded piece of junk I > posted recently, which suffered from the delusion of being a BarFly > macro preprocessor. As far as I am concerned here comes the Real Thing [...] > > Please let me know if you find this useful, would like to see bug fixes, > changes and/or improvements, and so on. The script is probably good. As a BarFly user I don't really need it, but quite a lot of the ABCs I've posted on the web (including many of the O'Neill 1001's) contains BarFly ornament macros, and it's nice if visitors with other software can have them played back correctly too :-) But here is a thought about the ornament macro system itself: Currently the system can only add notes. How about rests? We don't need the letter z to signify a note in a macro anyway (since s' does exactly the same job), so why not? Here's an example: X:1 T:Macro example m: Rn = n/G,//z// M:C L:1/4 K:G RG RA RB Rc|Rd Re Rf Rg|] X:2 T:Macro example (expanded the way BarFly does it today) M:C L:1/4 K:G G/G,//e'// A/G,//f'// B/G,//g'// c/G,//a'//|\ d/G,//b'// e/G,//c''// f/G,//d''// g/G,//e''//|] X:3 T:Macro example (expanded with rests) M:C L:1/4 K:G G/G,//z// A/G,//z// B/G,//z// c/G,//z//|\ d/G,//z// e/G,//z// f/G,//z// g/G,//z//|] (BTW, this example also includes a fixed note (G,) within a macro. I was going to suggest that as an addition too, but discovered to my suprise that BarFly already has that feature although it doesn't seem to be documented anywhere.) Frank Nordberg To subscribe/unsubscribe, point your browser to: http://www.tullochgorm.com/lists.html
[abcusers] abcmac - BarFly-style abc macro preprocessor in Perl
All right, everybody, please forget the simple-minded piece of junk I posted recently, which suffered from the delusion of being a BarFly macro preprocessor. As far as I am concerned here comes the Real Thing, based on Phil Taylor's description of BarFly macros (I hope it does everything right). This works at least for Phil's examples (and Jack's tune, too). Suggestions on how to improve the `transpose this note 5 steps up' code are welcome :^) Please let me know if you find this useful, would like to see bug fixes, changes and/or improvements, and so on. I'll give the program a more permanent home on my web site if there is sufficient interest. Cheers, Anselm -- Anselm Lingnau .. [EMAIL PROTECTED] There is only one basic human right, the right to do as you damn well please. And with it comes the only basic human duty, the duty to take the consequences. -- P. J. O'Rourke #!/usr/bin/perl # abcmac -- Barfly-style macro preprocessor for ABC files. # # Copyright © 2001 Anselm Lingnau <[EMAIL PROTECTED]>. Use this as you # like as long as you don't alter or remove this comment or pretend that # you wrote it yourself. # # See http://www.barfly.dial.pipex.com/bfextensions.html for a description # of BarFly macros. use strict; # This defines what a macro takes as an argument. # Currently the argument is a note name (no length). my $arg = q{[\^=_]?[A-Ga-g](,*|\'*)}; my $subst; my (@m, @global_m); my $xnotes = 'hijklmnopqrstuvwxyz'; my $n_pos = index($xnotes, 'n'); my @tnotes = qw/C,,, D,,, E,,, F,,, G,,, A,,, B,,, C,, D,, E,, F,, G,, A,, B,, C, D, E, F, G, A, BCDEFGAB cdefgabc' d' e' f' g' a' b' c'' d'' e'' f'' g'' a'' b'' c''' d''' e''' f''' g''' a''' b'''/; my ($i, $tnotes_max) = (0, scalar(@tnotes)); my %pos; foreach (@tnotes) { $pos{$_} = $i++; }; # Transpose note `$base' according to the relative position of `$note' # compared to `n' -- e.g., $base = 'A', $note = 'o' gives 'B'. Don't bother # dealing with accidentals, since BarFly doesn't either. sub transpose { my ($base, $note) = @_; my ($steps) = index($xnotes, $note) - $n_pos; my ($new_note) = $pos{$base} + $steps; die "transposed note out of range" if $new_note < 0 || $new_note >= $tnotes_max; return $tnotes[$new_note]; } # Main loop. my ($global) = 1; while (<>) { if (/^([A-Za-z]):/) { # header line if ($1 eq 'm') {# macro definition my $def = $_; $def =~ s/\s*%.*$//; if ($global) { # Remember global macros separately push @global_m, $def; } else { push @m, $def; } } elsif ($1 eq 'K') { # last line in header my @subst = (); # Construct a sequence of expansion commands for the macros. # Make sure to expand longer-named macros first, to avoid # replacing `On' before `On/' foreach my $macro (@m) { my ($name, $value) = $macro =~ /m:\s*(\S+)\s*=\s*(.*)\s*$/; my $name_len = length $name; my $transposing; if ($transposing = $name =~ s/n/($arg)/) { $value =~ s/([h-z])/".&transpose(\$1,'$1')."/g; $value = qq{"$value"}; push @subst, [$name_len, qq{s\x01$name\x01$value\x01ge;\n}]; } else { push @subst, [$name_len, qq{s\x01$name\x01$value\x01g;\n}]; } } foreach my $s (sort { $$b[0] <=> $$a[0] } @subst) { $subst .= $$s[1]; } # print "-" x 72, "\n", $subst, "-" x 72, "\n"; } elsif ($1 eq 'X') { # First tune starts here. $global = 0; } print; # This prints »m:« lines as well - should it? } elsif (/^$/) {# End of tune; forget non-global macros @m = @global_m; } elsif (!/^%/) { # non-comment line -- expand macros chomp; my $out = ''; while (length $_) { if (s/^(".*?")//) { # leave stuff in quotes alone $out .= $1; } else {# look for macro calls to preprocess my $v; s/^([^\"]*)//; for ($v = $1) { eval $subst; warn $@ if $@; $out .= $_; } } } print $out, "\n"; } else { print; } }