DirectMusic problem with midi events



Hello i encounter a strange problem with DirectMusic.

I want to play a Midi file.

I need to use DirectMusic to have the DLS support.
I already decode the Midi file (without DirectMusic).
I just want to use DirectMusic as an output port for my Midi messages.

The following code works fine a lot of Midi files.

If i use another IDirectMusicPort8 than CLSID_DirectMusicSynth the result is
OK (but i don't have all the DirectMusic possibilities).
If i use CLSID_DirectMusicSynth i have a problem. It's like if i "lost" some
Midi messages (often in a Midi with many active channels and the "lost"
messages are often in the drum channel 10).

DirectMusic producer seems to play correctly theses midi files...
I don't understand what's wrong in my code...
Any idea ?

Thanks for help


#define NCHANNELS 16

class CDirectMidiDevice
{
private:

IDirectMusic8 *m_pDM;
IDirectMusicLoader8 *m_pDMLoader;
IDirectMusicPort8 *m_pOutPort;
IDirectMusicBuffer8 *m_pDMBuffer;
IReferenceClock *m_pLClock;
IDirectMusicCollection8 *m_pDLSCollection;
IDirectMusicDownloadedInstrument8 *m_pDLSInst[NCHANNELS];

void setSynthetizerProperty( DWORD dwLatency, DWORD dwPeriod );
void loadDLS( void );
void setDLSInstrument( long patch1, int channel );

public:

CDirectMidiDevice( HWND hWnd );
~CDirectMidiDevice( void );

void midiOutMessage( int iStatus, int iChannel, int iData1, int iData2 );
};

CDirectMidiDevice::CDirectMidiDevice( HWND hWnd )
{
DMUS_PORTPARAMS8 portParam;
DMUS_BUFFERDESC desc;
long i;
HRESULT hr;


m_pDM = NULL;
m_pDMLoader = NULL;
m_pOutPort = NULL;
m_pDMBuffer = NULL;
m_pLClock = NULL;
m_pDLSCollection = NULL;

memset( m_pDLSInst, 0, NCHANNELS * sizeof(
IDirectMusicDownloadedInstrument8 * ) );

CoInitialize( NULL );

CoCreateInstance( CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER,
IID_IDirectMusic8, ( void ** ) &m_pDM );
CoCreateInstance( CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC_SERVER,
IID_IDirectMusicLoader8, ( void ** ) &m_pDMLoader );

hr = m_pDM->SetDirectSound( NULL, NULL );
if( FAILED( hr ) )
MessageBeep( 0 );

memset( &portParam, 0, sizeof( DMUS_PORTPARAMS8 ) );

portParam.dwSize = sizeof( DMUS_PORTPARAMS8 );
portParam.dwValidParams = DMUS_PORTPARAMS_VOICES |
DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_EFFECTS |
DMUS_PORTPARAMS_SAMPLERATE;
portParam.dwSampleRate = 44100;
portParam.dwEffectFlags = DMUS_EFFECT_REVERB | DMUS_EFFECT_CHORUS;
portParam.dwChannelGroups = 1;
portParam.dwVoices = 1024;

hr = m_pDM->CreatePort( CLSID_DirectMusicSynth, &portParam, &m_pOutPort,
NULL );
if( FAILED( hr ) )
MessageBeep( 0 );

hr = m_pOutPort->Activate( TRUE );
if( FAILED( hr ) )
MessageBeep( 0 );

memset( &desc, 0, sizeof( desc ) );

desc.dwSize = sizeof( DMUS_BUFFERDESC );
desc.guidBufferFormat = GUID_NULL;
desc.cbBuffer = 32;
desc.dwFlags = 0;

hr = m_pDM->CreateMusicBuffer( &desc, &m_pDMBuffer, NULL );
if( FAILED( hr ) )
MessageBeep( 0 );

hr = m_pOutPort->GetLatencyClock( &m_pLClock );
if( FAILED( hr ) )
MessageBeep( 0 );

setSynthetizerProperty( 10, 2 );

loadDLS();

for( i = 0; i < NCHANNELS; i++ )
setDLSInstrument( 0, i );
}

CDirectMidiDevice::~CDirectMidiDevice( void )
{
long i;


for( i = 0; i < NCHANNELS; i++ )
{
if( m_pDLSInst[i] != NULL )
{
m_pOutPort->UnloadInstrument( m_pDLSInst[i] );
m_pDLSInst[i]->Release();
m_pDLSInst[i] = NULL;
}
}

if( m_pDLSCollection != NULL )
{
m_pDLSCollection->Release();
m_pDLSCollection = NULL;
}

if( m_pLClock != NULL )
{
m_pLClock->Release();
m_pLClock = NULL;
}

if( m_pDMBuffer != NULL )
{
m_pDMBuffer->Release();
m_pDMBuffer = NULL;
}

if( m_pOutPort != NULL )
{
m_pOutPort->Activate( FALSE );
m_pOutPort->Release();
m_pOutPort = NULL;
}

if( m_pDMLoader != NULL )
{
m_pDMLoader->Release();
m_pDMLoader = NULL;
}

if( m_pDM != NULL )
{
m_pDM->Release();
m_pDM = NULL;
}

CoUninitialize();
}

void CDirectMidiDevice::midiOutMessage( int iStatus, int iChannel, int
iData1, int iData2 )
{
REFERENCE_TIME rt;
DWORD dwMessage;
HRESULT hr;


if( iStatus == 0xB0 && ( ( iData1 == 32 ) || ( iData1 == 0 ) ) )
return;

if( iStatus == 0xC0 )
setDLSInstrument( iData1, iChannel );

dwMessage = iStatus | iChannel | ( iData1 << 8 ) | ( ( long ) iData2 << 16 );

hr = m_pLClock->GetTime( &rt );
if( FAILED( hr ) )
MessageBeep( 0 );

hr = m_pDMBuffer->PackStructured( rt, 1, dwMessage );
if( FAILED( hr ) )
MessageBeep( 0 );

hr = m_pOutPort->PlayBuffer( m_pDMBuffer );
if( FAILED( hr ) )
MessageBeep( 0 );

hr = m_pDMBuffer->Flush();
if( FAILED( hr ) )
MessageBeep( 0 );
}

void CDirectMidiDevice::setSynthetizerProperty( DWORD dwLatency, DWORD
dwPeriod )
{
KSPROPERTY ksp;
ULONG cb;
HRESULT hr;
IKsControl *pCtrl;

m_pOutPort->QueryInterface( IID_IKsControl, ( void ** ) &pCtrl );

memset( &ksp, 0, sizeof( KSPROPERTY ) );
ksp.Set = GUID_DMUS_PROP_WriteLatency;
ksp.Flags = KSPROPERTY_TYPE_SET;
hr = pCtrl->KsProperty( &ksp, sizeof( KSPROPERTY ), ( LPVOID ) &dwLatency,
sizeof( DWORD ), &cb );
if( FAILED( hr ) )
MessageBeep( 0 );

memset( &ksp, 0, sizeof( KSPROPERTY ) );
ksp.Set = GUID_DMUS_PROP_WritePeriod;
ksp.Flags = KSPROPERTY_TYPE_SET;
hr = pCtrl->KsProperty( &ksp, sizeof( KSPROPERTY ), ( LPVOID ) &dwPeriod,
sizeof( DWORD ), &cb );
if( FAILED( hr ) )
MessageBeep( 0 );

pCtrl->Release();
}

void CDirectMidiDevice::loadDLS( void )
{
DMUS_OBJECTDESC desc;
HRESULT hr;

memset( &desc, 0, sizeof( DMUS_OBJECTDESC ) );

desc.dwSize = sizeof( DMUS_OBJECTDESC );
desc.guidClass = CLSID_DirectMusicCollection;
desc.guidObject = GUID_DefaultGMCollection;
desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_OBJECT;

hr = m_pDMLoader->GetObject( &desc, IID_IDirectMusicCollection8, ( void **
) &m_pDLSCollection );
if( FAILED( hr ) )
MessageBeep( 0 );
}

void CDirectMidiDevice::setDLSInstrument( long patch, int channel )
{
IDirectMusicInstrument8 *pDMInst;
long p;
HRESULT hr;


if( m_pDLSInst[channel] )
{
hr = m_pOutPort->UnloadInstrument( m_pDLSInst[channel] );
if( FAILED( hr ) )
MessageBeep( 0 );

m_pDLSInst[channel]->Release();
m_pDLSInst[channel] = NULL;
}

p = patch;
if( channel == 9 )
p |= 0x80000000;

hr = m_pDLSCollection->GetInstrument( p, &pDMInst );
if( FAILED( hr ) )
{
if( channel == 9 )
p = 0x80000000;
else
p = 0;

hr = m_pDLSCollection->GetInstrument( p, &pDMInst );
if( FAILED( hr ) )
MessageBeep( 0 );
}

hr = m_pOutPort->DownloadInstrument( pDMInst, &( m_pDLSInst[channel] ),
NULL, 0 );
if( FAILED( hr ) )
MessageBeep( 0 );

pDMInst->Release();
}

.