>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