The required "MHDR" chunk immediately follows the "SAMP" header and consists of the following components: #define ID_MHDR MakeID('M','H','D','R') /* MHDR size is dependant on the size of the imbedded PlayMap. */ typedef struct{ UBYTE NumOfWaves, /* The number of waves in this file */ Format, /* # of ORIGINAL significant bits from 8-28 */ Flags, /* Various bits indicate various functions */ PlayMode, /* determines play MODE of the PlayMap */ NumOfChans, Pad, PlayMap[128*4], /* a map of which wave numbers to use for each of 128 possible Midi Notes. Default to 4 */ } MHDRChunk; The PlayMap is an array of bytes representing wave numbers. There can be a total of 255 waves in a "SAMP" file. They are numbered from 1 to 255. A wave number of 0 is reserved to indicate "NO WAVE". The Midi Spec 1.0 designates that there are 128 possible note numbers (pitches), 0 to 127. The size of an MHDR's PlayMap is determined by (NumOfChans * 128). For example, if NumOfChans = 4, then an MHDR's PlayMap is 512 bytes. There are 4 bytes in the PlayMap for EACH of the 128 Midi Note numbers. For example, the first 4 bytes in PlayMap pertain to Midi Note #0. Of those 4 bytes, the first byte is the wave number to play back on Amiga audio channel 0. The second byte is the wave number to play back on Amiga audio channel 1, etc. In this way, a single Midi Note Number could simultaneously trigger a sound event on each of the 4 Amiga audio channels. If NumOfChans is 1, then the PlayMap is 128 bytes and each midi note has only 1 byte in the PlayMap. The first byte pertains to midi note #0, the second pertains to midi note #1, etc. In this case, a player program might elect to simply play back the PlayMap wave number on any available amiga audio channel. If NumOfChans = 0, then there is no imbedded PlayMap in the MHDR, no midi note assignments for the waves, and an application should play back waves on any channel at their default sampleRates. In effect, the purpose of the PlayMap array is to determine which (if any) waves are to be played back for each of the 128 possible Midi Note Numbers. Usually, the MHDR's NumOfChans will be set to 4 since the Amiga has 4 audio channels. For the rest of this document, the NumOfChans is assumed to be 4. As mentioned, there can be a total of 255 waves in a "SAMP" file, numbered from 1 to 255. A PlayMap wave number of 0 is reserved to indicate that NO WAVE number should be played back. Consider the following example: The first 4 bytes of PlayMap are 1,3,0,200. If a sample playing program receives (from the serial port or another task perhaps) Midi Note Number 0, the following should occur: 1) The sampler plays back wave 1 on Amiga audio channel number 0 (because the first PlayMap byte is 1). 2) The sampler plays back wave 3 on Amiga audio channel number 1 (because the second PlayMap byte is 3). 3) The sampler does not effect Amiga audio channel 2 in any way (because the third PlayMap byte is a 0). 4) The sampler plays back wave 200 on Amiga audio channel number 4 (because the fourth PlayMap byte is 200). (This assumes INDEPENDANT CHANNEL play MODE to be discussed later in this document.) All four of the PlayMap bytes could even be the same wave number. This would cause that wave to be output of all 4 Amiga channels simultaneously. NumOfWaves is simply the number of waves in the sound file. Format is the number of significant bits in every sample of a wave. For example, if Format = 8, then this means that the sample data is an 8 bit format, and that every sample of the wave can be expressed by a single BYTE. (A 16 bit sample would need a WORD for every sample point). Each bit of the Flags byte, when set, means the following: Bit #0 - File continued on another disc. This might occur if the SAMP file was too large to fit on 1 floppy. The accepted practice (as incor- porated by Yamaha's TX sampler and Casio's FZ-1 for example) is to dump as much as possible onto one disc and set a flag to indicate that more is on another disc's file. The name of the files must be the related. The continuation file should have its own SAMP header MHDR, and BODY chunks. This file could even have its continuation bit set, etc. Never chop a sample wave in half. Always close the file on 1 disc after the last wave which can be completely saved. Resume with the next wave within the BODY of the continuation file. Also, the NumOfWaves in each file's BODY should be the number saved on that disc (not the total number in all combined disk files). See the end of this document for filename conventions. In C, here is how the PlayMap is used when receiving a midi note-on event: MapOffset = (UBYTE) MidiNoteNumber * numOfChans; /* MidiNoteNumber is the received note number (i.e. the second byte of a midi note-on event. numOfChans is from the SAMP MHDR. */ chan0waveNum = (UBYTE) playMap[MapOffset]; chan1waveNum = (UBYTE) playMap[MapOffset+1]; chan2waveNum = (UBYTE) playMap[MapOffset+2]; chan3waveNum = (UBYTE) playMap[MapOffset+3]; if (chan0waveNum != 0) { /* get the pointer to wave #1's data, determine the values that need to be passed to the audio device, and play this wave on Amiga audio channel #0 (if INDEPENDANT PlayMode) */ } /* do the same with the other 3 channel's wave numbers */ In assembly, the "MHDR" structure looks like this: CNOP 0,2 MHDR dc.b 'MHDR' sizeOfMHDR dc.l [this is 6 + (NumOfChans * 128) ] NumOfWaves dc.b [a byte count of # of waves in the file] Format dc.b [a byte count of # of significant bits in a sample point] Flags dc.b [bit mask] PlayMode dc.b [play MODE discussed later] NumOfChans dc.b [# of bytes per midi note for PlayMap] PlayMap ds.b [128 x NumOfChans bytes of initialized values] and a received MidiNoteNumber is interpreted as follows: moveq #0,d0 move.b MidiNoteNumber,d0 ;this is the received midi note # bmi.s Illegal_Number ;exit, as this is an illegal midi note # moveq #0,d1 move.b NumOfChans,d1 mulu.w d1,d0 ;MidiNoteNumber x NumOfChans lea PlayMap,a0 adda.l d0,a0 move.b (a0)+,chan0waveNum move.b (a0)+,chan1waveNum move.b (a0)+,chan2waveNum move.b (a0),chan3waveNum tst.b chan0waveNum beq.s Chan1 ;Now get the address of this wave number's sample data, determine the ;values that need to be passed to the audio device, and output the wave's ;data on Amiga chan 0 (assuming INDEPENDANT PlayMode). Chan1 tst.b chan1waveNum beq.s Chan2 ;do the same for the other wave numbers, etc.