On 26 Jul 2004, at 04:23, Paul Rosen wrote:

I've finally gotten a few free moments of time, and started thinking about
the "universal parser" that we talked about a few months back. I started to
write down the requirements for the output, which I've included below. I've
included everything I could think of for formatting and playing music.


The idea here is to create a universal data structure suitable for all ABC
applications. Then someone writing a better parser and someone writing a
better formatter could work independently.


If you are interested in this, please comment on the following and tell me
if I've left anything out or made incorrect assumptions. When I get a little
more time, I'll create a C structure that can handle this and post that.


-----

ABC parser output data structure.

Goal

3. This is the data structure between the ABC parser and the application.
There are two main applications: a sheet music formatter, and music player.
I think other applications (like a transposer) would not have any unique
demands on the structure.

As long as the structure contains all the information present in the
original abc it should be possible to perform any function which could have
been done starting from scratch.


4. The goal is to have a flexible enough structure that additional
requirements would be handled without requiring fundamental changes to the
structure. With luck, some additional requirements may be handled without
any changes to the structure at all.

Anticipating future requirements is the difficult part.

5. The purpose of this structure is to completely separate the parser, the
formatter, and the player. Each one of these three functions can be
developed independently, and different developers can have their pieces snap
in.


General requirements

7. This structure is for a single tune. To do multiple tunes, you can simply
have an array of these.
8. Everything possible should be interpreted as much as possible. In other
words, a chord of "Gm" would be stored as a G minor chord, not the text
"Gm". This allows the player to not need to do any parsing.
9. however, the original wording should be available if needed. In other
words, "GM" and "G" are both a G major chord. Some formatting programs may
wish to use one or the other exclusively, or may choose to parrot whatever
was specified.

Not too sure about this. A guitar chord like "Gm" can imply much more than
just a Gm chord at that point - the chord continues until the next chord
symbol, and can have a complex rhythmic structure. Producing this from
the simple text "Gm" is a matter of interpretation, and probably belongs
in a player program, rather than in the first-stage parser.


10. Extra formatting information may be in the structure. The most obvious
is the new staff indicator (the exclamation point) and the
don't-connect-eighths indicator (the space). Room should be made for many
others that may be put in the language later. For instance, what if the user
wanted a measure to be spaced out more than the formatter naturally would?
Or wanted to force the notes to be pointed up? Or wanted more room between
two particular staffs? Or a new page? Or wanted to decide whether the last
staff was justified or aligned to the left? In any case, no formatting is
required, and in that case, the formatter makes all its own decisions.
11. The structure should have a simple, fixed format so that it can be saved
to disk easily, or passed between programs written in different languages.
The saved version would be something of a "compiled" version, that is, our
equivalent of an OBJ file. This means that there can't be any pointers in
the structure.

If we are going to write this out to disk, would it not be better to adopt
an existing public format (e.g. NIFF or MusicXML), rather than create a new
one? In any case, pointers are not a problem, as you can simply convert
them to file offsets.


12. A C++ class will encapsulate the structure, so that users of C++ can
easily gain access to the data in a natural way.


General structure

14. There are two parts:
15. The header contains one-time only information. that includes the title,
etc. It also contains global information, like whether to force all notes to
be pointed up.
16. The body is an array of items. These items define a particular vertical
space on the notation, and a particular time for the player. Note that the
amount of space and amount of time is variable for each item. A simple
example follows. Three possible items are a whole note, a half note, and a
bar. each of the three takes a different amount of time to play (the bar
takes no time to play). The bar takes a different amount of space to display
than the notes.

Some elements in the array will contain much more information than others,
which makes for problems finding your way around. Would you pad the smaller
elements to make them all the same size, use a separate index with pointers
to the start of each element or what?


In BarFly I use a doubly-linked list, each element consisting of a fixed and
a variable part. The fixed part contains stuff which is common to all
elements (e.g. the back and forward pointers). Some elements contain pointers
to subsidiary lists (e.g. beam elements and chord elements contain pointers
to the start and end of a list of notes).


17. Items need to refer to neighboring (and farther off) items. For
instance, an item may indicate that a slur has begun, and another item would
indicate that it has ended.

You will also have to deal with multiple slurs at the same point, so you either
need to indicate both start and end positions at both ends, or attach a unique
i.d. number to each slur.



Elements in the item

19. (All of the following are for a single stave. An element may also have
multiple staves.)
20. Multiple notes, each with a separate rhythm, and a voice number.
21. Chord symbol
22. Singing words (possibly multiple verses)
23. slurs and ties (connected to a particular note if multiple notes are
present)
24. The greater and less than signs that show the differences in volume.
25. New key signature, new tempo, new time signature.
26. The following accents (multiple ones could be in each item, and
sometimes multiple ones can be on each note in an item): slide up and down,
muffled (note head is an X), diamond head note, loudness markings, fingering
numbers, trill indicator, ritard, fermat, arpeggio, legato, staccato &
pizzicato, bowing symbols, pedal on, pedal off, accent, attack,
27. This item is part of a set of grace notes (the rhythm for them should be
stolen from the previous note.)
28. First ending, second ending, etc.
29. Bar line type: repeat, double, thick on left, etc.
30. Text in the staff instead of notes. That is: "8 bar intro", "piano
solo", etc.
31. Non-chord note above the staff. for instance, to indicate a different
instrument should start playing, or to label an interesting spot.


Elements in the header

33. All of the items in the header section of the ABC spec.
34. Additional verses. (probably printed at the bottom)
35. Global indicators, like number of staves and their clef.
36. Instrument name to the left of the staff.
37. Amount of swing (8th notes played dotted by how much)

Looks a bit daunting when you write it all out doesn't it?
I think the real trick is to build extensibility into it from the beginning,
so that you can start with something simple and build up to more complex
capabilities in a predictable way. I would leave out consideration of
a file structure for some time, since that will tie you down badly if
you want to make changes later.


Phil Taylor

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

Reply via email to