DirectX SDK

Working with Instruments

[Visual Basic]

This topic pertains only to applications written in C++. DirectX for Visual Basic does not allow applications to work with individual instruments from a collection.

[C++]

Once a DirectMusicCollection is created and loaded from a collection file, you can retrieve the patch number and name of all the available instruments by using the IDirectMusicCollection::EnumInstrument method.

The following code example enumerates all instruments in a collection and displays their names and patch numbers.

void myListInstruments(
        IDirectMusicCollection *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);
        }
    }
}

You can obtain a pointer to a specific instrument by passing its patch number to the IDirectMusicCollection::GetInstrument method.

After obtaining an instrument, you can change its patch number by using the IDirectMusicInstrument::SetPatch method.

Loading a collection and retrieving the instruments is only the first step in making the instruments available. You must next download them to the port.

To download an instrument to a port, pass an IDirectMusicInstrument interface pointer to the IDirectMusicPort::DownloadInstrument method. This method makes the DLS data available on the port; it does not actually associate the instrument with any particular performance.

You can also download an instrument by using the IDirectMusicPerformance::DownloadInstrument method. In addition to downloading the DLS data, this method assigns the instrument to a particular performance channel.

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. Only the data for the regions falling within that range would be 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 IDirectMusicPort::DownloadInstrument method. Typically, only a single range of notes is specified, but you can specify multiple ranges. If you pass NULL instead of a pointer to an array, the data for all regions is downloaded.

HRESULT myDownload(
    IDirectMusicCollection *pCollection,    // DLS collection
    IDirectMusicPort *pPort,                // Destination port
    IDirectMusicDownloadedInstrument **ppDLInstrument, 
    DWORD dwPatch,                          // Requested instrument
    DWORD dwLowNote,                        // Low note of range
    DWORD dwHighNote)                       // High note of range
 
{
    HRESULT hr;
    IDirectMusicInstrument* 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 IDirectMusicDownloadedInstrument interface. This pointer has just one purpose: to identify the instrument in a subsequent call to the IDirectMusicPort::UnloadInstrument method, which unloads the instance of the instrument on a particular port. (The DirectMusicCollection is not bound to any specific port. You can download different instruments to different ports or download a single instrument to multiple ports.)

The following code example downloads an instrument, and then unloads it, which illustrates how the IDirectMusicDownloadedInstrument pointer can be used:

HRESULT myFickleDownload(
        IDirectMusicInstrument* pInstrument,
        IDirectMusicPort *pPort,
        DWORD dwPatch)
 
{
    HRESULT hr;
    IDirectMusicDownloadedInstrument * pDLInstrument;
    hr = pPort->DownloadInstrument(
            pInstrument, &pDLInstrument, 
            NULL, 0);
    if (SUCCEEDED(hr))
    {
        pPort->UnloadInstrument(pDLInstrument);
        pDLInstrument->Release();
    }
    return hr;
}

The IDirectMusicBand::Download method automates the downloading of all instruments in a band. You supply a pointer to a performance, and the method downloads each instrument to the appropriate port attached to that performance.