💾 Archived View for runjimmyrunrunyoufuckerrun.com › src › foreign › abcmidi › doc › programming › y… captured on 2021-12-17 at 13:26:06.

View Raw

More Information

-=-=-=-=-=-=-

Some Notes on the yaps Code
-------------------------------------------------------------
       written by Seymour Shlien	November 21 2004

This file gives an algorithmic description of the
yaps program which converts an abc file to a PostScript file.

The source consists of almost 10000 lines of C in the following
files. 

parseabc.c is the front end which scans the abc file and invokes
        the appropriate event handler for each element it encounters
        (eg. bar lines, notes, chords etc.) It happens to be the
        front end for other programs such as abc2midi, and
        abc2abc. More details are given in abc2midi.txt.

yapstree.c contains all the event handlers called by the parser.
	It produces a complex data structure called tune which
        references many other structures. When the parser completes
        processing the tune, event_blankline or event_eof calls
        printtune (in drawtree.c) which processes the tune structure
        producing a PostScript file. Unlike abc2midi, most of the
        layout including the detailed beaming is done in the first
        pass during the parsing stage. The information in this
        structure is then processed by drawtune.c in two more
        passes. An overview of these structures is provided here.
        More details on the tune structure is provided in this
        file.

drawtune.c contains the function printtune which turns the tune
	structure into an actual PostScript file. This is done
	in two passes. Before writing the PostScript file it
	is necessary to determine the boundingbox of the output
	image since this information is recorded in the header
	of the output file. This is determined in the first pass
	where functions monospace() or spacevoices() (in position.c)
	are called. During this pass the pixel positions
	of each object are recorded in the associated structures.
	In the second pass, the actual PostScript file is written.
	The function calls printlib() (in pslib.c) outputs
	all the PostScript boiler plate macro definitions required
	by yaps. The information in the tune structure is used
        to output the music notation in a PostScript file. 


position.c contains functions for determining the amount of space
	that is required for the different music objects drawn
	in the PostScript file.

parser2.c contains additional parsing functions missing in parseabc.
	They handle more recent features added to the abcmidi package.

pslib.c Definition of new PostScript commands (eg. notes, clefs,
	stems, tails, ...) which are copied to the PostScript
	file.

debug.c Functions which support the -d option in yaps. It prints
	some of the contents of the internal tune structure.


Data Structures
---------------

The data structures are defined in the include file structs.h.

The top level structure, tune is instantiated by init_tune which
is called by event_init or event_refno. It stores all the
information in the abc field commands (X: ,M:, L:, C:, O: and etc.).
It contains a pointer to the voice structure and a list of voice
pointers where most of the body information is recorded.

The voice structure is instantiated by the function newvoice
which is called by setvoice(n) whenever the voice context
switches in the abc file. Setvoice performs the voice switching
(which occurs in voice interleaved files) and either creates
a new voice or finds the matching voice structure already existing.
The voice structure contains the feature structure which
is somewhat similar in function to the one defined in store.c
(for abc2midi).

The feature structure encodes all the detailed information in
the body, using the same typedef enum featuretype defined
in abc.h. Unlike store.c there is no num and denom arrays. Instead
the feature struct contains a void* pointer called item which
can point to anything and where additional information can be
stored. If the feature type is a NOTE then a "note" struct
is created which records a lot of detailed information related
to the placement and visual representation of the note. They
include:
tail_type	which specifies whether the note appears in
		isolation or is part of a beamed group
base_exp	whole, half, quarter,  ... notes
dots		how many dots follow
stemlength, stemup, fliphead, pitch, octave, accidentals, accents,...
(see struct.h)
Most of the information except actual positioning is determined
by functions such as count_dots and beamitem in yapstree.c.
You can view this information by running yaps.exe with the -d
run time parameter.

The handling of the note positioning is quite complex as
outlined below. It is therefore not easy to implement the
splitvoice feature into yaps. Here is a description.

The positioning of notes is done by the function
spacemultiline() which calls advance() unless one is printing
the voices separately.  The positioning is done on all the voices
at the same time to ensure that they are lined up properly.
Spacemultiline accesses all the active voices using the functions
firstitem() and nextitem() which are used for handling any lists
of objects. Each voice maintains its own pointer to the current
feature being scanned (v->place). Each voice also maintains its
own pointer to the relative time of the note being scanned
in the variable v->time. (v->time contains both a numerator
and denominator.) The advance() function updates v->place,
v->time and interprets the voice features determining the
amount of space that is needed to plot the next object (itemspace)
and the number of plotable objects (items). The position to
plot the next object (x) is maintained by spacemultiline and
passed to advance. Advance() updates v->place->x with the position
to plot the object based on its width. Spacemultiline()
maintains a mastertime variable for maintaining synchrony
between all voices.

At least two passes are made through the voice features.
In the first pass provisional positions are computed for the
notes. The amount of space left over in the music lines is
computed and is used to determine the internote gaps.
In the second pass, the notes are repositioned to use up
the entire space in the staff line.

Spacemultiline is called for each staff line whose end is
signaled by a linefeed feature in the voice.