FIXME To complete.

Export music

The music is exported only as a data stream (similar to Leonard's YM ST-Sound format), no external player is provided which decodes the data of instrument, pattern, etc.

The output stream gives for each frame the values to be programmed to AY registers, the information needed to manage SID, samples and the “Entry” and “Signal” options.

Two export formats are available:

  • full stream: gives the value of all the streams for each frame
  • delta stream: gives only the values modified compared to the previous frame, this is a form of compression. The generated file is easily three times smaller.

Both formats use the same SDS filename extension.

Frame data

Each frame contains 16 streams of one byte each which represent, in order, the calculated values to be sent in the AY registers 0 to 13, the SID period (encoded on 9 bits) and the Signal/Entry information (combined into one byte).

The values of the period (0, 1, 2, 3, 4, 5, 11, 12) and noise (6) registers are stored directly as they are to be sent to the AY. Therefore, the most significant nibble of the streams of registers 1, 2 and 5 will always be 0, the 3 most significant bits of the stream of register 6 will always be 0.

For register 13, the special value &ff indicates that the register should not be written for this frame.

The streams of registers 7, 8, 9 and 10 have bits added with respect to AY registers which are used to encode the information for SID and sample.

Stream Used bits [7:0] Meaning
0 n n n n n n n n Value of register 0 of AY (channel A period LSB)
1 . . . . n n n n Value of register 1 of AY (channel A period MSB)
2 n n n n n n n n Value of register 2 of AY (channel B period LSB)
3 . . . . n n n n Value of register 3 of AY (channel B period MSB)
4 n n n n n n n n Value of register 4 of AY (channel C period LSB)
5 . . . . n n n n Value of register 5 of AY (channel C period MSB)
6 . . . n n n n n Value of register 6 of AY (noise period)
7 s . n n n n n n n = value of register 7 of AY (mixer control)
s = most significant bit of the SID period
8 n n n n n n n n For channel A, depending on the value of bit[7:5]
= %1xx, sample. bit[6:0] give sample number, except 0 which indicates a sample is in progress
= %01m, SID of type m (uses bit[4:0])
= %00x, bit[4:0] is the value to write to register 8 of AY (volume of channel A)
9 n n n n n n n n Like stream 8 for channel B
10 n n n n n n n n Like stream 8 for channel C
11 n n n n n n n n Value of register 11 of AY (envelope period LSB)
12 n n n n n n n n Value of register 12 of AY (envelope period MSB)
13 n n n n n n n n If 255, indicates that register 13 should not be written
Else, value to write to register 13 of AY (envelope shape 8 to 15)
14 n n n n n n n n SID period LSB
15 n n n n n n n n Signal/Entry :
If &00 to &7F, this is a signal (displayed as S.00 to S.7F in a pattern)
If &80 to &BF, this is an entry point (displayed as E.00 to E.3F in a pattern)
If &FF, no signal nor entry

During export processing, the idea is rather not to keep the last “Signal/Entry” stream in the compressed data. Instead, it is more efficient to generate two separate pointer/value arrays, one for the signals and the other to be able to force complete frames and thus have several entry points in the music (including “loop to”).

File format

A stream file is made up of:

  • 5 bytes of file signature: “SDST” followed by one &1A byte
  • 1 byte &00 (format version number)
  • 1 byte &20 (version of the software that created the file, in BCD)
  • one MHDR chunk which contains information about the module
  • one STHD header chunk
  • one chunk which contains stream data: STF for a full stream or STD for a delta stream
  • where applicable, AYL and AYLA chunks for the samples and aliases used in the music
  • one &1A byte which marks the end of the file

A chunk always starts with its name on 4 characters, followed by the 32 bits data size of the chunk. The values are stored in little-endian.

"Module header" chunk

Name Description Content
MHDR Module header
Module information
4 bytes: chunk length
Music title (null-terminated string, maximum length is 14+1)
Author (null-terminated string, maximum length is 30+1)
Comment 1 (null-terminated string, maximum length is 30+1)
Comment 2 (null-terminated string, maximum length is 30+1)

"Stream header" chunk

Name Description Content
STHD Stream header 4 bytes: chunk length
1 byte: number of streams per frame (can be used to deduce the size of an STF frame and the size of the STD bitmask)
4 bytes: number of frames (0 if unknown)
4 bytes: “loop to” frame number (0 for the first frame)
2 bytes: reserved, set to 0

"Full stream" chunk

Name Description Content
STF Stream Full
Data of each frame
(all streams for each frame)
4 bytes: chunk length (0 if unknown)
16 bytes for each frame: 1 byte per stream, starting with stream 0
4 bytes at &FF: end of stream marker

"Delta stream" chunk

Name Description Content
STD Stream Delta
Data of each frame
(only values that change)
4 bytes: chunk length (0 if unknown)
<frame data>
4 bytes at &FF: end of stream marker

Only the streams whose value changes compared to the previous frame are stored in a STD chunk. A bitmask indicates which streams are populated in the following bytes.

A frame is therefore coded as follows:

  • 2 bytes of bitmask: 1 bit per stream (0=stream inactive; 1=stream active). By convention, bit15 corresponds to stream 0
  • n bytes: byte of each active stream (stream 0 first)

The first frame (frame 0) is always complete.

"AY-List" chunk

Name Description Content
AYL AY-List
Sample stored as an AY-List
4 bytes: chunk length
1 byte: sample number (1 to 127)
12 bytes: sample name (fixed-size string)
<data in AY-List format>

The samples used in the music are saved in AYL chunks. The AY-List of the sample must be terminated with a STOP instruction.

"AY-List alias" chunk

Name Description Content
AYLA Alias of an AY-List
Sample alias (offset in a parent sample)
4 bytes: chunk length
1 byte: alias number (1 to 127)
12 bytes: alias name (fixed-size string)
1 byte: parent sample number (1 to 127)
2 bytes: offset in parent sample (even value)

The aliases of samples used in the music are saved in AYLA chunks. The AYL chunk of the parent sample of the alias must have been encountered previously.

Using a music once exported

Once the music is exported, the SDS file contains all the data needed to replay the music in your application. But before that, an additional step is necessary to apply a compression algorithm to the stream data part to reduce its size. Several methods are proposed below.

Kit AY method

Madram's Kit AY is originally intended to convert and compress a YM file. A modified version adapted to the SDS “Stream Full” format of Soundtracker DMA is available in the Downloads section.

It is a tool that runs on CPC and I am warning you, it is very slow, be patient.

Start the Basic file and indicate the SDS file to process. It will generate:

  • an OUT.AYC file which contains the streams compressed in AYC format
  • an OUT.ASM file which defines the address table of AY-lists (samples)
  • an OUT.AYL file which contains the AY-Lists of the samples

The assembler source stkdma_ayc_player.asm contains the code for the decompressor and the player, it includes the three previous files.

The AYC toolkit achieves a very good compression ratio and the decompression routine is very fast, but it requires a 256 byte buffer for each stream. The downside of this method is the amount of RAM needed for these buffers.

FIXME to complete (other method)