next up previous contents
Next: Score Following Mode Up: Intonation Software Previous: MIDI Tuning Technique

SMF Mode

One major function of Helm is to allow the realization of score files as MIDI files. There are four major software components that make this possible. All of these were written in the Java programming language [10]. The first is an SDL (Score Description Language) parser. This reads a score file and turns it into a corresponding data structure in memory. The second major component is the score serializer. This converts the representation of the score from a set of parallel parts with events that have duration to a single series of point-like events in time. The third major software component takes this serial version of the score and converts it a series of MIDI events. The major work of this component is implementing the MIDI tuning technique described above. The fourth major component is the MIDI file writer, which takes a series of MIDI events in memory and turns them into a Standard MIDI File.

The SDL parser does its lexical analysis using the StreamTokenizer utility class of the Java Language. The data structure it uses to represent scores is a nested hierarchy of objects that reflects the nested nature of musical structure. This nested structure can be seen from the Backus-Naur syntax; for example, a letter is part of a pitch which is part of a note which is part of an event which is part of a part which is part of a score. Although SDL has no provisions for it, this data structure can handle melismatic intonation information.

The major challenge of the score serializer is to convert events with duration to a chronological series of events without duration. The most important example of this is converting a single note event to a note on event and a note off event. What is slightly tricky about this task is using a data structure that can serialize events but still maintain associations between them. In particular, when the note on and off are separated due to chronological ordering, it is still important to be able to find the ``on'' that corresponds to a given ``off.'' This becomes important during the implementation of the MIDI tuning technique because the note off event must have the same channel as its corresponding note on.

The conversion from a serial score to a series of tuned MIDI events carefully seeks to minimize the number of pitch bend messages that are created. The idea behind this is that some synthesizers may not respond well to the dense MIDI stream that would result from sending pitch bend changes before every note. The most naive implementation of the MIDI tuning technique is to send a pitch bend before every note, rotating through all 16 channels sequentially. This ignores the fact that a pitch bend needs to be sent out before a note of class c only if more than 15 unique pitch classes have been used since the last time a note of class c was used. Pitch class is the relevant datum here because no retuning is necessary to play an octave multiple of a pitch that has had a channel tuned for it. The algorithm that converts a serial score into MIDI events tries to reuse channels that are already tuned correctly, and when it must retune a channel, it picks one that has not been heavily used, under the assumption that it probably won't come in handy later.

Channel assignment is also affected by the presence of unisons. To understand this, we need to introduce a little history. Initially, the primary application of MIDI was as a way for keyboards to control separate synthesizers. Due to the nature of the keyboard mechanism, a unison can never be played. This means that two Note Ons for the same key are always separated by a Note Off for that key. Because of its heritage as a keyboard control protocol, MIDI does not define the behavior a synthesizer should have in the presence of a unison.

Even if MIDI did define a behavior in the presence of unisons, it could not be defined in a musically satisfying manner. This inherent limitation comes from the fact that it is impossible for a synthesizer to figure out which Note Ons match with which Note Offs. Imagine a MIDI stream of the following three messages, all on the same channel and for the same key, with 500ms between them: Note On with velocity 30, Note On with velocity 120, Note Off, Note Off. How should the Note Ons and Offs be paired? It is impossible to tell, yet the musical result is quite different due to the fact that the two pending Note Ons have widely different velocities.

As a result of the fact that MIDI's behavior in the presence of unisons is undefined, the two (or more) notes of a unison must be assigned to separate channels. Thus a channel can be reused to play note n with pitch bend p only if its pitch bend state is already p and it is not currently in use playing note n. This seems like a minor point, but unisons are very common in polyphonic vocal music.

The conversion from a series of MIDI events in memory to a MIDI file is accomplished via the Rogus McJava MIDI Library. This is a library that allows the reading and writing of Standard MIDI Files from the Java language. It was written for use in Helm but is completely general, i.e. it is in no way specific to tuning.

In addition to creating a Standard MIDI File from an SDL score, Helm can also create a Csound [26] Score File (.sco file). The conversion from an SDL to a Csound score does not even require serialization of the score, since Csound can accept scores with parallel events. The Csound score can be used to create audio file realizations with stunning audio quality and intonation accuracy, all without the use of any external synthesizer hardware.


next up previous contents
Next: Score Following Mode Up: Intonation Software Previous: MIDI Tuning Technique
Ben Denckla
8/29/1997