If you are writing a DirectMusic application that edits DLS collections, you need to be able to download instrument data to the synthesizer without encapsulating it in a DirectMusicInstrument object. The following overview describes how to do this.
Working with DLS data requires knowledge of the DLS specification and file structure. For detailed information on these topics, see the document entitled Downloadable Sounds Level 1, published by the MIDI Manufacturers Association.
To download raw instrument data, you first need to get a pointer to the IDirectMusicPortDownload interface, as show in the following example, where it is assumed that pIPort is a valid pointer to an IDirectMusicPort interface:
IDirectMusicPortDownload **ppIDownloadPort;
HRESULT hr = pIPort->QueryInterface(IID_IDirectMusicPortDownload,
(void **) ppIDownloadPort);
If the HRESULT is not S_OK, the port does not support DLS downloading.
Next identify the buffers that need to be prepared and downloaded. To send an instrument to the synthesizer, you must create one instrument buffer that represents the entire instrument definition with all the regions and articulations, and a series of wave buffers, one for each wave the instrument references for its regions.
Each buffer must be tagged with a unique identifier. Identifiers are used to resolve linkages between buffers, in particular the links between regions and waves. Tally the number of buffers you need to download and call IDirectMusicPortDownload::GetDLId to allocate a range of identifiers. For example, if you are downloading an instrument with three waves, you will need to download four buffers in total, so request a set of four identifiers.
For each buffer, calculate the size needed, then call IDirectMusicPortDownload::AllocateBuffer to allocate it. This method returns an IDirectMusicDownload interface representing the buffer. Call IDirectMusicDownload::GetBuffer to access the actual memory.
Note There are two methods called GetBuffer:
IDirectMusicPortDownload::GetBuffer returns an IDirectMusicDownload interface pointer for a buffer object whose download identifier is known.
IDirectMusicDownload::GetBuffer returns a pointer to the actual memory in the buffer.
Now write the data into each buffer. Each buffer starts with a DMUS_DOWNLOADINFO structure, which defines the size and functionality of the download. This structure must be prepared as follows:
The DMUS_DOWNLOADINFO structure is always followed by a DMUS_OFFSETTABLE structure. This offset table is used to manage all links within the data. Whenever a structure in the data references another structure, it addresses it with an integer index instead of a pointer. For every structure within the data that can be referenced, there is a unique index. The DMUS_OFFSETTABLE translates this integer index into a byte offset into the data.
The actual instrument or wave data follows the DMUS_OFFSETTABLE. If the download is an instrument, the data starts with the DMUS_INSTRUMENT structure. Otherwise it starts with the DMUS_WAVE structure.
The instrument data that follows the DMUS_INSTRUMENT structure is organized in the following structures:
The wave data pointed to by the DMUS_WAVE structure is organized in a DMUS_WAVEDATA structure.
When the buffers are all ready, download them by using IDirectMusicPortDownload::Download. Download the wave buffers first, so they are in place and can be referenced when the instrument is downloaded.
Once the buffers have been downloaded, the synthesizer is ready to play the instrument. The memory in the buffer is no longer accessible.
Later, when done playing the instrument, unload the buffers and release them. First unload the instrument buffer, then all the wave buffers. To unload, call IDirectMusicPortDownload::Unload and pass it the IDirectMusicDownload objects. Then, release each buffer with a call to IDirectMusicDownload::Release.
To update an instrument that has already been downloaded, you cannot write over the previously downloaded buffer. Instead, replace the instrument, but not the waves. To do this, call IDirectMusicPortDownload::AllocateBuffer to allocate a new IDirectMusicDownload interface with a buffer of the correct size. Be sure to generate a new identifier for the buffer with a call to IDirectMusicPortDownload::GetDLId. Write the new articulation information into the buffer, then download it. Then unload the previously downloaded buffer with a call to IDirectMusicPortDownload::Unload.
To update a wave buffer, take one extra step. Create both a new wave buffer and an updated instrument buffer that references it. Download the new wave, then the new instrument. Then unload the old instrument followed by the old wave.