# File Format for TSE3 Music Description Language (TSE3MDL)

### Pete Goodliffe
Issue 1.01
9th June 1999

### Introduction

The TSE3 Music Description Language provides an object-oriented description of a piece of music as MIDI data, in a linear sequencer form.

It is designed for use with TSE3, the Trax Sequencer Engine v3.00 and so parallels its song structure closely.

This file format is for use with TSE version 3.00 and later. Specifically, it is incompatible with the earlier format known as TSEMDL which was used with TSE v2.00.

TSE3MDL files commonly have a file extension of `.tse3` although the format can be deduced from the file contents: the first eight bytes are `"TSE3MDL\n"`

### TSE3MDL file conventions

TSE3MDL files are plain text files readable in any text editor. The data is arranged into hierarchical chunks which closely parallel the TSE3 Song class hierarchy.

Because TSE3MDL files are in text, all numbers are in ASCII decimal form. Times are represented in pulses, as integer values.

Each line of a TSE3MDL file may contain any amount of whitespace at it's start which is ignored. This is commonly used to enhance the readablilty of the chunk hierarchy. Additionally, any lines which start with a hash (#) symbol (after any whitespace) are ignored as comment lines.

Case is important when recognising identifiers.

Each file chunk follows a standard format. This is as shown below:

    CHUNK_TAG_IDENTIFIER
    {
        DATA_IDENTIFIER:DATA
    }

The CHUNK_TAG_IDENTIFIER is a single word containing any characters except '`:`'. If an identifier of this format is found then it signifies the beginning of a new chunk. The opening and closing braces will be on separate lines. Within the chunk data is commonly indented by four spaces, but this is not mandatory. Chunks can be hierarchically arranged - chunks can contain chunks. Chunk tag identifiers correspond the their related object names in the TSE3 Song hierarchy.

Lines other than CHUNK_TAG_IDENTIFIERs must be DATA_IDENTIFIER lines. These consist of a single word identifier which can contain any characters except '`:`' followed by a '`:`' and then the data associated with that identifier. The identifier name is local to each type of chunk. For example, there are several types of chunk with identifiers `Status`. In each chunk this refers to a different type of setting.

If you encounter a chunk that is not recognised then it should be ignored. You may warn the user if required. Similarly, if you encounter a data identifier that you do not recognise you should ignore it.

### File header

The TSE3MDL file consists of a single chunk, with a number of sub-chunks.

The top level chunk has tag identifier

    TSE3MDL

, with the rest of the file contents contained in it's pair of braces. As a special case, the first line cannot be prefixed by ant whitespace.

This first line identifies the file type as being TSE3MDL. To check whether a file is in TSE3MDL you only need to check the first eight bytes (don't forget the carriage return following the tag).

Insider this

    TSE3MDL

chunk there is usually a Header chunk, followed by a Song chunk.

### Header chunk

A Header chunk has chunk tag identifier `Header` and is defined to contain the following identifiers.

Identifier | Description | Default if not present
`Version-Major` | Major version number of this file * 100 | 100
`Version-Minor` | Minor version number of this file * 100 | 100
`Originator` | Identity of the program that created this file. | n/a
`PPQN` | PPQN resolution timestamps in this file are based upon. | 96

### Song chunk

A Song chunk has chunk tag identifier `Song` and is defined to contain the following identifiers.

Identifier | Description | Default if not present
`Title` | String containing the title of this Song | empty
`Author` | String containing the author of this Song | empty
`Copyright` | String containing the copyright message for this Song | empty
`Date` | String containing the date of this Song | empty
`NoTracks` | Number of Tracks in the Song. ??? | empty

A Song is also defined to contain TempoTrack, TimeSigTrack, FlagTrack, Phrase and Track chunks.

### TempoTrack chunk

A TempoTrack chunk has chunk tag identifier `TempoTrack` and is defined to contain the following identifiers.

Identifier | Description | Default if not present
`Status` | 'On' if tempo changes are enabled, or 'Off' disabled. | On

There then follows another chunk with identifier `Events` containing the TempoTrack events. There is one event per line in the form `TIME:TEMPO` where TIME and TEMPO are integer values.

### TimeSigTrack chunk

A TimeSigTrack chunk has chunk tag identifier `TimeSigTrack` and is defined to contain the following identifiers.

Identifier | Description | Default if not present
`Status` | 'On' if timesig changes are enabled, or 'Off' disabled. | On

There then follows another chunk with identifier `Events` containing the TimeSigTrack events. There is one event per line in the form `TIME:TOP/BOTTOM` where TIME, TOP and BOTTOM are integer values.

### FlagTrack chunk

A FlagTrack chunk has chunk tag identifier `FlagTrack` and is defined to contain no identifiers.

It contains another chunk with identifier `Events` containing the FlagTrack events. There is one event per line in the form `TIME:STRING` where TIME is a integer value and STRING is the associated flag string..

### Phrase chunk

A Phrase chunk has chunk tag identifier `Phrase` and is defined to contain the following identifiers.

Identifier | Description | Default if not present
`Title` | String containing unique reference name of this Phrase. | n/a

There then follows another chunk with identifier `Events` containing the Phrase events.

There is one event per line in the form `TIME:STATUS/DATA1/DATA2/CHANNEL/PORT` where all values are integers. STATUS contains the MidiCommand status nybble, DATA1 and DATA2 contain the data bytes (which will not have bit 7 set), CHANNEL contains a value from 0-15 and PORT the computer MIDI port number to send the data on.

If the MidiCommand is a MidiCommand_NoteOn (STATUS == 9) then the line is followed by `-OFFTIME:OFFSTATUS/OFFDATA1/OFFDATA2/OFFCHANNEL/OFFPORT` which contains the balancing MidiCommand_NoteOff. All values are as for the previous MidiCommand_NoteOn.

### Track chunk

A Track chunk has chunk tag identifier `Track` and is defined to contain the following identifiers.

Identifier | Description | Default if not present
`Title` | String containing name of this Track. | empty
`NoParts` | Number of Parts in this Track ??? | empty

The Track chunk is defined to contain MidiFilter, MidiParams and Part chunks.

### MidiFilter chunk

A MidiFilter chunk has chunk tag identifier `MidiFilter` and is defined to contain the following identifiers.

Identifier | Description | Default if not present
`Status` | 'On' to allow events to be generated by parent, false to mute the parent. | On
`Channel` | Channel to force MIDI events to be produced on. -1 to disable. | -1
`Port` | Port to force MIDI events to be produced on. -1 to disable. | -1
`Quantise` | Linear quantise value to snap events to. 0 has no effect. | 0
`Transpose` | Transpose value (added to note values, -127-127). | 0
`MinVelocity` | Min velocity clip window value. | 0
`MaxVelocity` | Max velocity clip window value. | 127
`VelocityScale` | Velocity scale percentage, 1 - 200. 0 disables | 0

### MidiParams chunk

A MidiParams chunk has chunk tag identifier `MidiParams` and is defined to contain the following identifiers. These identifiers have values 0-127, or -1 to disable.

Identifier | Description | Default if not present
`BankLSB` | Bank LSB byte sent at beginning of parent. | -1
`BankMSB` | Bank MSB byte sent at beginning of parent. | -1
`Program` | Program change sent at beginning of parent. | -1
`Pan` | Pan controller sent at beginning of parent. | -1
`Reverb` | Reverb controller sent at beginning of parent. | -1
`Chorus` | Chorus controller sent at beginning of parent. | -1
`Volume` | Volume controller sent at beginning of parent. | -1

### Part chunk

A Part chunk has chunk tag identifier `Part` and is defined to contain the following identifiers.

Identifier | Description | Default if not present
`Phrase` | Title of Phrase used by this Part. | n/a
`Start` | Start time of Part | n/a
`End` | End time of Part | n/a
`Repeat` | Repeat time value of Part | n/a
`Offset` | Offset time value of Part | n/a

The Part chunk is defined to contain MidiFilter and MidiParams chunks.

### See also

The MIDI Specification Level 1.0 for descriptions of MIDI commands.

### Revision history

9 June 1999 | 1.00 | First version. Implemented in TSE3.
1 September 2000 | 1.01 | Changed SimpleMidiEventFilter to MidiFilter.
29 January 2001 | 1.02 | Whole file is one big chunk. Comments.