Hey all,
I'm having a peculiar issue with my 3D Sound. The initial loaded sound works fine and correctly, but as soon as a new sound is loaded, that original 3D Sound does not reposition itself correctly, and sounds wrong. For example the object making the sound is to my right, but it still sounds like it's right in front of me. This is a cascading effect where if I then have three files, the last one to be loaded will be fine, and the other two will be out of whack.
Here is my load 3D sound function, as it's the only real place I can see this being a problem.
This is the Struct t3DSound used in the load function.
// Specialized struct for 3D Sounds
struct DNASOUND_API t3DSound
{
LPDIRECTSOUNDBUFFER *m_pBuffers; // Array of buffers
LPDIRECTSOUND3DBUFFER m_pDS3DBuffer; // 3D sound buffer
DS3DBUFFER m_dsBufferParams; // 3D buffer properties
DWORD m_dwNumBuffers; // The number of buffers
// Default constructor
t3DSound(void){ m_pBuffers = NULL; m_pDS3DBuffer = NULL; memset(&m_dsBufferParams, 0, sizeof(DS3DBUFFER)); }
~t3DSound(void)
{
// Loop through and clean up the buffers
for (unsigned int i = 0; i < 10; i++)
{
if (m_pBuffers)
{
m_pBuffers->Release();
m_pBuffers = NULL;
}
}
// Delete the whole array
delete [] m_pBuffers;
// Release the DS3D buffer
m_pDS3DBuffer->Release();
m_pDS3DBuffer = NULL;
}
};
the load function.
int CSoundManager::Load3DSound(char* szFileName, DWORD dwNumBuffers)
// Variables needed to hold data
char *pcmData;
DWORD nbytes;
WAVEFORMATEX wfx;
unsigned char *pData1, *pData2;
DWORD szData1, szData2;
DSBUFFERDESC bufferDesc;
HRESULT hr;
// Buffer to hold new data
//LPDIRECTSOUNDBUFFER *pTempBuffer = new LPDIRECTSOUNDBUFFER[dwNumBuffers];
t3DSound *pNew3DSound = new t3DSound;
pNew3DSound->m_dwNumBuffers = dwNumBuffers;
pNew3DSound->m_pBuffers = new LPDIRECTSOUNDBUFFER[dwNumBuffers];
// load wav file
pcmData = LoadWAVFile(szFileName, &nbytes, &wfx);
// Check data
if (pcmData == NULL)
return -1;
if( wfx.nChannels > 1 )
{
// Too many channels in wave. Sound must be mono when using DSBCAPS_CTRL3D
return -1;
}
if( wfx.wFormatTag != WAVE_FORMAT_PCM )
{
// Sound must be PCM when using DSBCAPS_CTRL3D
return -1;
}
// set up description buffer
memset( &bufferDesc, 0, sizeof( DSBUFFERDESC ) );
bufferDesc.dwSize = sizeof( DSBUFFERDESC );
bufferDesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE;
bufferDesc.dwBufferBytes = nbytes;
bufferDesc.guid3DAlgorithm = DS3DALG_HRTF_LIGHT;
bufferDesc.lpwfxFormat = &wfx;
// Make sure it's not a huge file being loaded
if (nbytes > MAX_BYTES3D)
{
MessageBox(NULL, "Trying to load 6MB+ file as 3D Sound, what a waste of space...", "No way!", MB_OK | MB_ICONERROR);
return -1;
}
// create buffer
hr = m_pSoundDevice->CreateSoundBuffer( &bufferDesc, &pNew3DSound->m_pBuffers[0], NULL );
if( FAILED(hr) )
{
// Cleanup the mess
if (pNew3DSound)
delete pNew3DSound;
return -1;
}
// Make the duplicate buffers now (so we can have more than one playing at a time
for(unsigned int i = 1; i < dwNumBuffers; i++ )
{
//hr = m_pSoundDevice->CreateSoundBuffer( &bufferDesc, &pTempBuffer, NULL );
hr = m_pSoundDevice->CreateSoundBuffer( &bufferDesc, &pNew3DSound->m_pBuffers, NULL );
if( FAILED(hr) )
{
// Cleanup
if (pNew3DSound)
delete pNew3DSound;
return -1;
}
}
// Make sure we have focus, and we didn't just switch in from
// an app which had a DirectSound device
DWORD dwStatus;
pNew3DSound->m_pBuffers[0]->GetStatus( &dwStatus );
if( dwStatus & DSBSTATUS_BUFFERLOST )
{
// Since the app could have just been activated, then
// DirectSound may not be giving us control yet, so
// the restoring the buffer may fail.
// If it does, sleep until DirectSound gives us control.
do
{
//hr = pTempBuffer[0]->Restore();
hr = pNew3DSound->m_pBuffers[0]->Restore();
if( hr == DSERR_BUFFERLOST )
Sleep( 10 );
}
while( ( hr = pNew3DSound->m_pBuffers[0]->Restore() ) == DSERR_BUFFERLOST );
}
// Copy to all the allocated buffers buffer
for (unsigned int i = 0; i < dwNumBuffers; i++)
{
// copy to buffer
pNew3DSound->m_pBuffers->Lock( 0, nbytes, ( void** )&pData1, &szData1, ( void** )&pData2, &szData2, 0 );
memcpy( pData1, pcmData, szData1 );
memcpy( pData2, pcmData + szData1, szData2 );
pNew3DSound->m_pBuffers->Unlock( pData1, szData1, pData2, szData2 );
}
//hr = pTempBuffer[0]->QueryInterface( IID_IDirectSound3DBuffer, (VOID**)&m_pDS3DBuffer );
hr = pNew3DSound->m_pBuffers[0]->QueryInterface( IID_IDirectSound3DBuffer, (VOID**)&pNew3DSound->m_pDS3DBuffer );
if (FAILED(hr))
{
MessageBox(NULL, "Could not get 3D Buffer", "Load3DSound() Error", MB_OK | MB_ICONERROR);
return -1;
}
// Get the 3D buffer parameters
pNew3DSound->m_dsBufferParams.dwSize = sizeof(DS3DBUFFER);
pNew3DSound->m_pDS3DBuffer->GetAllParameters( &pNew3DSound->m_dsBufferParams );
// Set Min Max volumes
pNew3DSound->m_dsBufferParams.flMinDistance = m_dsBufferParams.flMinDistance;
pNew3DSound->m_dsBufferParams.flMaxDistance = m_dsBufferParams.flMaxDistance;
// Set the
//m_dsBufferParams.dwMode = DS3DMODE_NORMAL;
//if( m_pDS3DBuffer )
// m_pDS3DBuffer->SetAllParameters( &m_dsBufferParams, DS3D_IMMEDIATE );
// Set new 3D buffer parameters
pNew3DSound->m_dsBufferParams.dwMode = DS3DMODE_NORMAL; //DS3DMODE_HEADRELATIVE;
pNew3DSound->m_pDS3DBuffer->SetAllParameters( &pNew3DSound->m_dsBufferParams, DS3D_IMMEDIATE );
m_3DSoundBuffers.push_back(pNew3DSound);
return m_3DSoundBuffers.size() - 1;
}
The functionis a member of a class, and the class has one Listener that I know is set up correctly, and is working as intended.
Any help would be appreciated, as Im at a loss. Each t3DSound has it's own buffers, both 3D and standard, etc etc.
If there are any questions I'll be happy to answer them to get to the route of this problem.
Thanks guys!
[Edited by - PhilKing83 on July 20, 2006 4:13:07 PM]