Previous | Up | Home | Next

Chapter 2 - Symbol Relationships

The meaning of a music notation symbol often depends on its relationships with other music symbols. Storing enough information in the NIFF file to relate music symbols to one another introduces complex programming issues. NIFF has been carefully designed in an attempt to allow programs to indicate symbol relationships with logical rigor, flexibility and efficiency. A balance has been sought between the sometimes conflicting efficiency goals of minimizing processing time, programming effort, memory usage and disk space.

Dependent symbols and their anchors.

In NIFF, a music symbol whose placement depends on one or more other symbols is called a "dependent" symbol, and the symbol or other chunk type on which its placement depends is called its "anchor." For each symbol chunk type, a default anchor chunk type is defined. For example, for the Fingering chunk, the Notehead is the default anchor, and for the Articulation chunk, the Stem is the default anchor.

The Anchor Override tag can be used on a dependent symbol chunk to indicate a non-default anchor type. For example, a Slur's default anchor type is a Stem, but an anchor override could be applied to a particular slur endpoint to anchor it to a Notehead or Fingering chunk instead. The Time-Slice is the default anchor for some symbols, and is a valid override anchor as well.

The dependent/anchor relationship between symbols plays a major role in both file syntax and symbol placement.

File Syntax.

Syntax rules.

There are two rules defined for the syntactic order of dependent and anchor symbols:

1) The dependent symbol physically appears in the file as soon as possible after its anchor.

"As soon as possible" means that the only symbols that can be stored between a dependent symbol and its anchor are other symbols dependent on the same anchor, and nested symbols dependent on those.

2) When more than one symbol is dependent on the same anchor, the dependent symbols should be placed in the file in order of graphical proximity to the anchor, from nearest to farthest. For symbols that are the same distance from the anchor, or when distance doesn't matter, any order will do.

A detailed example demonstrating these rules is given below.

Stems and Notes.

The relationship between the Stem chunk and Notehead chunk is a little different from other symbol relationships. In terms of syntax, the Notehead is dependent on the Stem (i.e. Noteheads appear in the file after their associated Stem). However, for symbol placement, both the Notehead and Stem are dependent on the Time-Slice. This is discussed below in "Reference points on Noteheads and Stems."

Noteheads and Stems bypass syntax rule 2. Notehead chunks always follow the Stem chunk in order from highest to lowest pitch.

Complex dependencies - some examples.

The file syntax and use of the Anchor Override tag allow complex dependencies to be represented in NIFF. For example, consider a slur between two fingering numbers related to a single notehead, parentheses surrounding the staccatos over a series of notes, or a small sharp sign above a trill ornament over a note. The anchor of each symbol is the chunk of the appropriate type (either default or explicit) which most closely precedes the dependent symbol in the file.

Here are two examples in NIFF pseudo-code. In Example A1 there is a small sharp sign over a trill ornament anchored to one note of a chord; a fingering number is anchored to another note of the chord. In Example A2 parentheses surround the staccatos over three notes.

Diagram 1

Example A1:

Stem
Notehead, staff step=3, duration=1/4
Fingering, shape=1
Notehead, staff step=7, duration=1/4
Ornament, shape=short trill
Accidental, shape=sharp, Small Size, Anchor Override=Ornament,
	Logical Placement=above [discussed later]

Diagram 2

Example A2:

Time-Slice, type=event,start time=0/4
Stem
Notehead, staff step=5, duration=1/4
Articulation, shape=staccato
Parenthesis, shape = "(", Anchor Override=Articulation,Logical Placement = left,
	ID=1, Number of Nodes=2 [multi-node, discussed below]

Time-slice, type=event, start-time=1/4
Stem
Notehead, staff step=5, duration=1/4
Articulation, shape=staccato

Time-slice, type=event, start-time=2/4
Stem
Note, staff step=5, duration=1/4
Articulation, shape=staccato
Parenthesis, shape = ")", Anchor Override=Articulation,Logical Placement = right, ID=1

Multi-node symbols.

Beams, Slurs, Ties and Hairpins are examples of symbols which are normally dependent on more than one anchor. The interpretation of syntax rule 1 would be ambiguous in the case of a dependent symbol with a one-to-many relationship with its anchors. For example, consider a beam connecting three stems. Should the beam appear after the first, second or third stem? To allow syntax rule 1 to be applied consistently, one-to-many relationships have been decomposed in NIFF into one-to-one relationships by subdividing the "one" dependent symbol into several node chunks of a "multi-node symbol", each one corresponding to one of the "many" anchor chunks. Syntax rule 1 can then be followed: each dependent symbol node chunk physically appears in the file immediately after its corresponding anchor chunk.

For example, the beam is decomposed into nodes, each one corresponding to a stem. Each node supplies information about the beam at that point, i.e. the number of beam parts to the left and to the right of that stem, including partial (fractional) beams.

Every node of a multi-node symbol must contain an ID tag. The same ID is used on all nodes of a multi-node symbol, so the nodes can be recognized as belonging to the same symbol. As a convention, ID numbers should be assigned sequentially within a chunk type starting with zero.

The first node of a multi-node symbol (the one appearing physically first in the file) has some special properties. Any information which applies to the symbol as a whole appears here, such as the Fanned Beam tag on Beams. Tags which are independently associated with each node, such as Bezier Incoming/Outgoing and the Anchor Override tag can appear on any node.

The first node also contains the Number of Nodes tag indicating how many nodes are present in the file for the multi-node symbol with this ID. This allows the reading program if desired to allocate the appropriate amount of storage when it finds the first beam node, and to release the storage when it has found and handled the last beam node. The Number of Nodes tag and ID tag together identify a symbol as multi-node. In the rare case of a one-node symbol of a type which is normally multi-node, such as a beam when it is anchored to only one stem, the one beam chunk need not contain the Number of Nodes or ID tags.

In a cross-staff beam which starts on a stem in the lower staff and ends on a stem in the upper staff of a piano grand staff, the first beam node to appear in the file may be the one corresponding to the rightmost stem in the beam structure (the last one in time-slice order), or perhaps even to a stem in the middle of the beam structure. The reading program may not be able to reconstruct the complete beam until the last beam node has been read.

Here is an example in NIFF pseudo-code, showing a cross-staff beam connecting three eighth notes in ascending order.

Diagram B

Example:

(Staff 1)
Time-slice, type=event, start time=1/8
Stem
Beam, ID=1, Number of Nodes=3,parts to left=1, parts to right=1
Notehead, staff step= 2, duration=1/8

Time-slice, type=event, start time=2/8
Stem
Beam, ID=1, part to left=1, parts to right=0
Notehead, staff step=5, duration=1/8

(Staff 2)
Time-slice, type=event, start-time=0/8
Stem
Beam, ID=1,parts to left=0, parts to right=1
Notehead, staff step= 6, duration=1/8

Multi-staff chords.

When a stem contains notes on more than one staff, the stem is represented by a multi-node symbol. Each staff on which a portion of the stem appears has its own Stem node chunk. The first node contains the tags which affect all the nodes, such as Number of Flags.

Because the ID tag is unique within the chunk type for the entire score, the ID tag is sufficient to identify the related stem nodes in the different staves.

Here is an example:

Diagram C

Example:

(Staff 1)
Time-slice. type=event, start-time=0/8
Rest, duration=1/8

Time-slice. type=event, start-time=1/8
Rest, duration=1/8

Time-slice. type=event, start-time=2/8
Stem, ID=1, Number of nodes=2
Notehead, staff step=2, duration=1/4
Notehead, staff step=-1, duration=1/4

(staff 2)
Time-slice. type=event, start-time=0/8
Stem
Notehead, staff step=6, duration=1/8

Time-slice. type=event, start-time=1/8
Stem
Notehead, staff step=6, duration=1/8

Time-slice. type=event, start-time=2/8
Stem, ID=1
Notehead, staff step=7, duration=1/4

Multi-system multi-node symbols.

When a multi-node symbol crosses a system boundary, two special tags are used: the Multi-node End Of System tag, and the Multi-node Start Of System tag. These are required because the reading program might not have a system break in the same location as the writing program, and thus might not require these extra nodes. It can ignore all nodes with these tags if desired.

An example of the use of these tags is when a tie extends from the last note on one system to the first note in the following system. In this case the tie symbol will contain an extra pair of nodes, one at the end of the first system and one at the start of the next. All four nodes are assigned the same ID.

In the following example, the tie's Multi-node End Of System node is anchored to the Barline chunk at the end of the first system. The tie's Multi-node Start Of System node is anchored to the current time-slice, optionally with a negative horizontal placement.

Diagram D [the end of system barline was accidentally omitted from this diagram]

Example:

(System 1)
Time-slice, type=event, start-time=3/4
Stem
Notehead, staff step=5, duration=1/4
Tie, ID=1, Number of Nodes=4

Time-Slice,type=event, start-time=4/4
Barline
Tie, ID=1, Anchor Override=Barline, Multi-node End Of System

(System 2)
Time-slice, type=measure-start, start-time=16/4
Clef, shape=F clef, staff step=6
Time-slice, type=event, start-time=0/4
Tie, ID=1, Anchor Override=Time-Slice, Multi-node Start Of System
Stem
Notehead, staff step=5, duration=1/4
Tie, ID=1

Symbol Placement.

NIFF allows a variety of choices in describing the placement of symbols. The placement of a symbol is always described in terms of its relationship to its anchor. The choices include default placement, logical placement and absolute placement. A reference point for each symbol, defined by default, or explicitly by use of the Reference Point Override tag, is used in the interpretation of both absolute and logical placement values.

It is suggested that the writing program allow the user as much control as possible in the choice of the symbol placement technique or combination of techniques used in a particular NIFF file.

When non-default placement information is present for a symbol, it should not contradict the placement relationship implied by the file syntax, but should complement it.

Default, logical and absolute placement.

Default placement: This is the case when no indication of symbol placement is present for a symbol other than that implied by the file syntax. The reading program must use its own defaults for intelligent placement of the symbol.

Logical placement: This supplies the logical relationship between a dependent symbol and its anchor. It is implemented by the use of the Logical Placement tag, which indicates direction such as left, right, above, below or centered, and proximity such as touching or offset; and the Staff Step tag, which gives the position of the symbol's hot spot as a particular staff line or space.

Absolute placement: This gives the exact location of the symbol, as an offset in absolute measurement units relative to its anchor. This is useful when an exact reproduction of the original image is desirable. It is implemented by the use of the Absolute Placement tag, which supplies the exact horizontal and vertical offsets of symbols from one another.

Choice of placement technique by the writing program.

Absolute placement allows for the most precise rendering of the original notation. However, there are many situations where logical or default placement is more appropriate:

Combinations of the various techniques can be included in a NIFF file. One possibility might be for a writing program to record page layout information such as the vertical location of each system and staff, and the horizontal position of each measure. Finer detail might be stored only when the user has specified non-default placement of some object, such as when a slur has been reshaped to avoid another symbol. In this case the writing program might store the absolute placement of a particular slur's endpoints in relation to its stem anchors.

The use of the three placement options will likely evolve during the trial implementation of NIFF.

Interpretation of placement values by the reading program.

When encountering only absolute placement values in a NIFF file, a reading program could ignore them completely (strictly using its own defaults), or it could observe them without question. More intelligently, it could use them as a clue to determine logical placement of the symbols, avoiding collisions or incorrect alignment when necessary.

Reference points.

Every symbol has a default reference point used in interpreting the logical and absolute placement values. For a symbol such as an accidental or clef sign which has a natural "hot spot," the chunk definition specifies the hot spot as the default reference point. The default reference point of a Time-slice is the intersection of the time-slice at the staff's top line. If not otherwise specified, the default reference point of a symbol is the center of its bounding box.

When an absolute placement value is supplied for a dependent symbol, the meaning of its value is "the offset of the dependent symbol's reference point from the anchor symbol's reference point." Note that the NIFF reference point is not the same as the default placement. In other words, an absolute offset of (0,0) on a symbol does not mean "place the symbol exactly at its default horizontal and vertical position." Instead, it means "place the reference point of the symbol (often its center) exactly on top of the reference point of its anchor (often the anchor's center)."

The Reference Point Override tag can be used to temporarily change the reference point of either the anchor or the dependent symbol, or both. Descriptions of non-default reference points include codes such as "left of symbol's bounding box", "top of symbol's bounding box", or "vertical center of symbol's bounding box." When present, this tag is always specified on the dependent symbol for a particular dependent/anchor relationship.

Reference points on the anchor and dependent symbols are only to be considered when explicit placement information is supplied. Otherwise, the reading program should use its own defaults to determine the placement of a dependent symbol relative to its anchor.

Reference points on Noteheads and Stems.

As stated earlier, the Notehead and Stem chunks both use the Time-slice as their anchor in terms of symbol placement. This means that the offsets of the Notehead and Stem chunks are both given in relation to the time-slice.

The default reference point of a Notehead is its center. A horizontal offset of zero on a note chunk thus means it is horizontally centered over the time-slice. This would also be the default position, on an individual note or on a chord without seconds. When a chord contains a second, the notes on the "correct" side of the stem are by default to be centered over the time-slice. This allows for the correct alignment of simultaneous up-stem and down-stem chords which both contain seconds.

When both a normal size notehead and a small size notehead are both present on the same stem, it is the normal size notehead that is centered over the time-slice.

Diagram D

The time-slice is centered under the two notes to the left of the up-stem, and the two notes to the right of the down-stem.

A stem's default reference point is its end where the flag or beam would be attached, and its horizontal center. On a stem, a horizontal offset of zero would indicate that the stem is centered over the time-slice - obviously not the stem's default position. If a horizontal offset were supplied on a normal up-stem just touching the right side of an individual note (not required, since this would be the stem's default placement relative to the note), the stem's offset would be one half of the note width minus a half stem width. A larger stem offset would be used if the stem were to appear slightly separated from the note.

Advanced feature: using time-slice start time as a placement clue.

There are some cases when the start times on an event time-slice might be used as a clue to the proper positioning of symbols. This is an advanced feature that is not required in either reading or writing programs for successful implementation of NIFF.

There are situations in music where the proportional placement of symbols is meaningful: for example, a crescendo hairpin ending somewhere between the start and end of a whole note. When the spacing of symbols is later adjusted, the hairpin should expand or shrink proportionally to its surroundings.

When the writing program has used either logical or default placement of symbols rather than absolute, the proportion cannot be described in graphical terms. An event time-slice could be used as an anchor for the hairpin end, to precisely indicate the implied temporal relationship between it and the whole note's start and end. The program should calculate for the anchor time-slice's start time a value with the proper proportion to the start and end times of the whole note. The reading program could then use the temporal proportion of the hairpin end relative to the start and end times of the whole note to calculate the symbols' proportional placement.

In mathematical terms: P0 = position of previous timeslice
T0 = time of previous timeslice
P1 = position of next timeslice
T1 = time of next timeslice
P = position of hairpin end
T = start time on anchor time-slice of hairpin end

P = P0 + (T - T0) * (P1 - P0) / (T1 - T0).


Previous | Up | Home | Next