Here's some stuff about how to get rid of echo in your ports by ergazoobi, here's the features of M64, M64 Parser.
In M64, we have the header, the track and music event table, the header is the beginning of the M64, what all M64s must have, it contains necessary information about the M64, like the NLST, amount of channels, tempo and master volume.
HEADER FORMAT AND COMMAND TABLE
TRACKER FORMAT AND COMMAND TABLE
MUSIC FORMAT AND COMMAND TABLE
In M64, we have the header, the track and music event table, the header is the beginning of the M64, what all M64s must have, it contains necessary information about the M64, like the NLST, amount of channels, tempo and master volume.
HEADER FORMAT AND COMMAND TABLE
Status Byte | Parameters | Description |
0x90 - 0x9F | Offset (2 bytes) | Points to track data for a specific channel, indicated by the second nibble of status byte. |
0xD3 | 1 byte | Sequence type 80 for variable sequence, 0x00 - 0x25 for bank 00 to 37or 20. 60 is used for the 'Mario sounds' sequence. |
0xD6 | Channels (16 bits) | Disable channels flag. Each bit = one channel. |
0xDB | Master Volume (1 byte) | Master Volume (unsigned integer). |
0xDD | Tempo in BMP (1 byte) | Tempo setting (BPM). |
0xD5 | 16 bits | Not sure. Used in the very beggining of sequences (before channel enable flag). |
0xD7 | Channels (16 bits) | Enable channels flag. Each bit = one channel. |
0xFD | Variable-length (1 or 2 bytes) | Timestamp (used between track chunks and to ensure right looping). |
0xFB | Offset (2 bytes) | Loop from the specified offset. |
0xFF | No param | End of header |
TRACKER FORMAT AND COMMAND TABLE
Status Byte | Parameters | Description |
0x90 - 0x9F | Offset (2 bytes) | Loads music data (divided in "layers"). Since simultaneous notes (using a "0" timestamp) aren't possible, many layers are loaded and played simultaneously. The second nibble of the status byte indicates the layer number. |
0xC1 | Program (1 byte) | "Set program" related. There isn't a master index for instruments, this seems to refer to the current set of instruments, which is not specified in the sequence data but loaded by something external to it. Drums tracks usually use program 0x7f (127). |
0xC2 | Transposition (1 signed byte) | Transposition in semitones. |
0xC4 | No Param. | Mark the beggining of track data. |
0xD3 | Pitch bend (1 byte) | Pitch Bend (signed integer) |
0xD4 | Echo (1 byte) | Amount of echos for the track (1 byte) |
0xD8 | Vibrato (1 byte) | Vibrato range |
0xDC | unknown (1 byte) | Drum-related? |
0xDD | Pan (1 byte) | Set pan for this track (01 = left, 64 = center, 127 = right) |
0xDF | Track Volume (1 bytes) | Volume for this track (unsigned integer). |
0xFD | Variable-length (1 or 2 bytes) | Timestamp (used between track chunks and to ensure right looping). |
0xFF | No Param | End of Track Data |
MUSIC FORMAT AND COMMAND TABLE
Status Byte | Parameters | Description |
0x00-0x3F | Timestamp (1 or 2 bytes) Velocity (1 byte) Duration (1 byte) | "Play Note" commands ('Type 0'). Unlike MIDI, 0 = A0. Timestamp is variable lenght (see below). Duration byte seems to be timestamp before "NoteOff" |
0x40-0x7F | Timestamp (1 or 2 bytes) Velocity (1 byte) | "Play Note" commands ('Type 1') Duration = previous specified (producing more compact data). |
0x80-0xBF | Velocity (1 byte) Duration (1 byte) | "Play Note" commands ('Type 2'). Timestamp = previous specified (producing more compact data). |
0xC0 | Timestamp (1 or 2 bytes) | Timestamp used for rests. |
0xC2 | Transposition (1 byte) | Transposition in semitones. Since the 'PlayNote' commands just cover a range of 0x40 notes (as opposed to 0x7F possible MIDI notes), this is used to shift the range when needed. |
0xE0 - E8 | ? | ? |
0xFC | 2 bytes | Jump (used for loops). There isn't a loop counter, so the command is repeated. Offset is relative to individual sequence start. |
0xFF | No Param. | End of music track / Return from jump |