Working with Instruments
When a collection object is created and loaded from a collection file or resource, it is not bound to any specific port. You can download different instruments to different ports or download a single instrument to multiple ports.
You can retrieve the patch number and name of all the available instruments by using the IDirectMusicCollection8::EnumInstrument method.
The following example function enumerates all instruments in a collection:
void ListInstruments(IDirectMusicCollection8 *pCollection)
{
HRESULT hr = S_OK;
DWORD dwPatch;
WCHAR wszName[MAX_PATH];
DWORD dwIndex;
for (dwIndex = 0; hr == S_OK; dwIndex++)
{
hr = pCollection->EnumInstrument(
dwIndex, &dwPatch, wszName, MAX_PATH);
if (hr == S_OK)
{
// Do something with name of patch in wszName.
}
}
}
Obtain a pointer to a specific instrument by passing its patch number to the IDirectMusicCollection8::GetInstrument method.
After obtaining an instrument, you can change its patch number by using the IDirectMusicInstrument8::SetPatch method.
To download a single instrument to a port, pass an IDirectMusicInstrument8 interface pointer to the IDirectMusicPort8::DownloadInstrument or IDirectMusicPerformance8::DownloadInstrument method. This call makes the DLS data available on the port; it does not associate the instrument with any particular performance or audiopath.
To save memory, only waveforms and articulation required for given ranges of notes are downloaded. For example, for a bassoon you might specify that only data for the note range from low C through middle B is to be downloaded. Data for regions falling entirely outside that range is not downloaded.
The following code example, given a collection, a patch number, a port, and a range of notes, retrieves the instrument from the collection and downloads it. It sets up an array of one DMUS_NOTERANGE structure and passes this to the IDirectMusicPort8::DownloadInstrument method. Typically, only a single range of notes is specified, but it is possible to specify multiple ranges. If you pass NULL instead of an array, the data for all regions is downloaded.
HRESULT DownloadCollection(
IDirectMusicCollection8 *pCollection,
IDirectMusicPort8 *pPort,
IDirectMusicDownloadedInstrument8 **ppDLInstrument,
DWORD dwPatch,
DWORD dwLowNote,
DWORD dwHighNote)
{
HRESULT hr;
if ((NULL == pCollection) || (NULL == pPort) || (NULL == ppDLInstrument))
{
return E_INVALIDARG;
}
IDirectMusicInstrument8* pInstrument;
hr = pCollection->GetInstrument(dwPatch, &pInstrument);
if (SUCCEEDED(hr))
{
DMUS_NOTERANGE NoteRange[1];
NoteRange[0].dwLowNote = dwLowNote;
NoteRange[0].dwHighNote = dwHighNote;
hr = pPort->DownloadInstrument(pInstrument, ppDLInstrument, NoteRange, 1);
pInstrument->Release();
}
return hr;
}
The DownloadInstrument method returns a pointer to the IDirectMusicDownloadedInstrument8 interface. This pointer has just one purpose: to identify the instrument in a subsequent call to the IDirectMusicPort8::UnloadInstrument method, which unloads the instance of the instrument on a particular port.
The following function downloads an instrument and then unloads it, which is not useful except to illustrate how the IDirectMusicDownloadedInstrument8 pointer can be used:
HRESULT DownloadAndUnload(
IDirectMusicInstrument8* pInstrument,
IDirectMusicPort8 *pPort)
{
HRESULT hr;
IDirectMusicDownloadedInstrument* pDLInstrument;
if ((NULL == pInstrument) || (NULL == pPort)) return E_INVALIDARG;
hr = pPort->DownloadInstrument(pInstrument, &pDLInstrument, NULL, 0);
if (SUCCEEDED(hr))
{
hr = pPort->UnloadInstrument(pDLInstrument);
pDLInstrument->Release();
}
return hr;
}