Re: [abcusers] parts and multi-voice playback

2003-07-12 Thread Phil Taylor
We've been over this before, but back when BarFly was the only
application to support both parts and multi-voice playback.  So
maybe other implementations have moved on enough to merit a re-run.

In order to understand why BarFly won't do what you want I'll
have to explain how it works.

The program has two separate parsers for playing and display,
and they work quite differently from one another.

The play parser runs through the abc ignoring anything that
isn't required for playing (e.g. beams).  It generates a
list of midi codes and times, which can subsequently be
assembled into a Quicktime tune or a midi file or whatever.
It can't be started or stopped in mid-parse, but it can be
instructed not to generate output from some parts of the
tune, so you can do Play from Insertion Point or Play
Selection.  When playing multi-voice tunes it only parses
one voice at a time, seeking each V: field with the appropriate
voice number and skipping over the other voices.  It gets
called multiple times to assemble the complete tune for voice 1,
then voice 2 etc. until it has the whole thing.  When playing
a single voice tune with parts it also gets called multiple
times, once for each part in the order specified in the header.
In this case it parses the whole tune, but suppresses output
generated by abc outside of the requested part, and the output
is added at the end of the previous list to generate the
whole tune.  If it has to deal with both multivoice and parts
it deals first with voice 1, part A, then voice 1 part B etc.
until it has voice 1 complete, then goes on to voice 2 part A.

The reason why your example won't work:

X:1
T:Drink to me only.
T:2 Flutes.
M:6/8
L:1/8
Q:3/8=60
P:ABA
K:A
P:A
[V:1]   ccc d2d|(ed)c (Bc)d|(eA)d c2B   | HA6:|
[V:2]   AAA B2B|(cB)A (GA)B|(Ac)B A2[EG]|[HC6HA6]:|
%
P:B
[V:1] e|ece a2e|(ec)e  e2e | f2e  d2c   | (c3 B2):|
[V:2] c|cAc c2c|(cA)c  c2c | d2c  B2A   | (A3 G2):|

is that when parsing voice 1 part A, when it gets to the
end of the first line and encounters [V:2] it skips ahead to
find the next [V:1] field.  In doing so, it misses the P:B
field, since it is not contained within voice 1.  In fact,
the P:B field is contained only within voice 2, at the end
of the first line.

The display parser takes exactly two passes through the tune.
On the first pass it just determines where the line ends are,
and how many symbols are to be drawn on each line.  On the
second pass it draws each symbol to the screen.  If it's
single-voice abc there is no internal data structure to
represent the music.  If it's multi-voice then the output
is accumulated into a set of linked lists until it has a
complete block of staves, then the horizontal positions of
the symbols are adjusted to align them according to their
times, and the vertical positions of some symbols are adjusted
to avoid conflicts.  Each block is then drawn, and the data
structure is destroyed ready for the next block.  So the
display parser reads the complete tune from top to bottom
as a human would, and your part labels in the above example
work fine because both of them immediately precede the staff
where they are to be drawn.

The main reason why I did things the way I did was speed.
Nobody minds if they tell a computer to play and it takes
a second or two before the sound starts, but if you are
typing the abc and there's a second or two of dead time
after each keystroke you're not going to bother.  The
program was written to be used on a 25MHz Mac IIci, and
it's still usable on that machine.  The play parser was
written first, and at that time it didn't have to deal with
multivoice abc - that was a later modification.

Both parsers have their disadvantages.  As you've pointed
out, the positioning of part fields required to make them
play properly is too strict, and doesn't make sense unless
you know how the parser works.  Likewise, the display
parser can only deal with abc where the lines of abc are
entered in the order in which they are to be displayed.

However, fixing these problems will require a complete
re-write, and we're talking about half a million lines
of code here (Pascal is a verbose language).

Maybe when I get to version 2.0 I'll do it.  I'll write
a single parser which assembles the whole tune into a
data structure, with separate output routines to generate
midi or pictures of the staff notation.  It will be a lot
slower, but by that time even you will be using a machine
fast enough.

Phil Taylor


To subscribe/unsubscribe, point your browser to: http://www.tullochgorm.com/lists.html


[abcusers] parts and multi-voice playback

2003-07-11 Thread Jack Campin
We've been over this before, but back when BarFly was the only
application to support both parts and multi-voice playback.  So
maybe other implementations have moved on enough to merit a re-run.

The following is my way of representing a piece in book 6 of
Aird's collection.  Aird used a da capo, but ABC doesn't have
that (printing the words does not a control construct make),
so I used the standard P: construct to represent it.  BarFly
displays this nearly how I want it: each part gets a label in
a sensible place, though the playing order is not printed.

X:1
T:Drink to me only.
T:2 Flutes.
M:6/8
L:1/8
Q:3/8=60
P:ABA
K:A
P:A
[V:1]   ccc d2d|(ed)c (Bc)d|(eA)d c2B   | HA6:|
[V:2]   AAA B2B|(cB)A (GA)B|(Ac)B A2[EG]|[HC6HA6]:|
%
P:B
[V:1] e|ece a2e|(ec)e  e2e | f2e  d2c   | (c3 B2):|
[V:2] c|cAc c2c|(cA)c  c2c | d2c  B2A   | (A3 G2):|

The intuition behind the P: construct, to me, is that you are
splicing separate chunks of music together to form a larger
piece.  So this is not really a playback issue at all.  The
semantics of P: is given by a source-to-source operation (which
a staff notation program could also implement), and the above
must be equivalent to this:

X:2
T:Drink to me only.
T:2 Flutes.
M:6/8
L:1/8
Q:3/8=60
K:A
[V:1]   ccc d2d|(ed)c (Bc)d|(eA)d c2B   | HA6:|
[V:2]   AAA B2B|(cB)A (GA)B|(Ac)B A2[EG]|[HC6HA6]:|
%
[V:1] e|ece a2e|(ec)e  e2e | f2e  d2c   | (c3 B2):|
[V:2] c|cAc c2c|(cA)c  c2c | d2c  B2A   | (A3 G2):|
%
[V:1]   ccc d2d|(ed)c (Bc)d|(eA)d c2B   | HA6:|
[V:2]   AAA B2B|(cB)A (GA)B|(Ac)B A2[EG]|[HC6HA6]:|

Now, BarFly isn't having the syntax of ex.1 at playback time, you get
silence.  Its syntax requires that I write more verbosely, like this:

X:3
T:Drink to me only.
T:2 Flutes.
M:6/8
L:1/8
Q:3/8=60
P:ABA
K:A
[V:1] [P:A]  ccc d2d|(ed)c (Bc)d|(eA)d c2B   | HA6:|
[V:2] [P:A]  AAA B2B|(cB)A (GA)B|(Ac)B A2[EG]|[HC6HA6]:|
%
[V:1] [P:B] e|ece a2e|(ec)e  e2e | f2e  d2c   | (c3 B2):|
[V:2] [P:B] c|cAc c2c|(cA)c  c2c | d2c  B2A   | (A3 G2):|

which plays as written (the glitch in the anacrusis is Aird's
responsibility, his da capo isn't meant literally), but doesn't
display right: each voice gets a separate part label.  The
implication appears to be that part boundaries don't have to
coincide across voices: you only get one P: line in the header
so the sequence has to be the same, but if you are *not* going
to syntactically enforce coincidence of part boundaries across
voices, they ought to be allowed to drift, yes?  So let's try
it, even though I can think of no conceivable reason why you'd
want to write something like this:

X:4
T:test
P:ABAB
V:1
V:2
M:none
L:1/4
K:C
[V:1] [P:A] GG [P:B] ||
[V:2] [P:A]  [P:B] GG||

What BarFly displays gives no indication of where the part boundaries
in each voice are, and it doesn't play any sound.  So it doesn't look
like this extra flexibility has been implemented.

Nor do I want it to be.  Please can we have the simpler option as
in my first example, where parts are played as complete chunks of
music, no matter how many voices they've got, and without me having
to do Simon says the viola starts playing the coda here too with
redundant in-line fields?



-
Jack Campin: 11 Third Street, Newtongrange, Midlothian EH22 4PU; 0131 6604760
http://www.purr.demon.co.uk/jack * food intolerance data  recipes,
Mac logic fonts, Scots traditional music files, and my CD-ROM Embro, Embro.
-- off-list mail to j-c rather than abc at this site, please --


To subscribe/unsubscribe, point your browser to: http://www.tullochgorm.com/lists.html