Microsoft DirectX 8.1 (C++)

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 code example enumerates all instruments in a collection and displays their names and patch numbers:

void myListInstruments(
    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)
    {
     printf("Patch %lx is %S\n",dwPatch,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 waves 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 myDownload(
  IDirectMusicCollection8 *pCollection,  // DLS collection
  IDirectMusicPort8 *pPort,      // Destination port
  IDirectMusicDownloadedInstrument8 **ppDLInstrument, 
  DWORD dwPatch,          // Requested instrument
  DWORD dwLowNote,        // Low note of range
  DWORD dwHighNote)         // High note of range
 
{
  HRESULT hr;
  IDirectMusicInstrument8* pInstrument;
  hr = pCollection->GetInstrument(dwPatch, &pInstrument);
  if (SUCCEEDED(hr))
  {
    DMUS_NOTERANGE NoteRange[1];   // Optional note range
    NoteRange[0].dwLowNote = dwLowNote;
    NoteRange[0].dwHighNote = dwHighNote;
    hr = pPort->DownloadInstrument(pInstrument, 
      ppDLInstrument, 
      NoteRange, // Array of ranges
      1);    // Number of elements in the array
    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 myFickleDownload(
    IDirectMusicInstrument8* pInstrument,
    IDirectMusicPort8 *pPort,
    DWORD dwPatch)
 
{
  HRESULT hr;
  IDirectMusicDownloadedInstrument * pDLInstrument;
  hr = pPort->DownloadInstrument(
    pInstrument, &pDLInstrument, 
    NULL, 0);
  if (SUCCEEDED(hr))
  {
    pPort->UnloadInstrument(pDLInstrument);
    pDLInstrument->Release();
  }
  return hr;
}