Sign in to follow this  
PhilKing83

Issues with multiple sound buffers using D3DSounds

Recommended Posts

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[i])
			{
				m_pBuffers[i]->Release();
				m_pBuffers[i] = 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[i], NULL );
		hr = m_pSoundDevice->CreateSoundBuffer( &bufferDesc, &pNew3DSound->m_pBuffers[i], 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[i]->Lock( 0, nbytes, ( void** )&pData1, &szData1, ( void** )&pData2, &szData2, 0 );
		memcpy( pData1, pcmData, szData1 );
		memcpy( pData2, pcmData + szData1, szData2 );
		pNew3DSound->m_pBuffers[i]->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]

Share this post


Link to post
Share on other sites
Welcome to GDNet PhilKing83!

When you have this large amount of source, chances of someone looking through the code to search for a solution will be much greater if you enclose it in [source][/source] tags, so it looks like this:


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[i])
{
m_pBuffers[i]->Release();
m_pBuffers[i] = 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[i], NULL );
hr = m_pSoundDevice->CreateSoundBuffer( &bufferDesc, &pNew3DSound->m_pBuffers[i], 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[i]->Lock( 0, nbytes, ( void** )&pData1, &szData1, ( void** )&pData2, &szData2, 0 );
memcpy( pData1, pcmData, szData1 );
memcpy( pData2, pcmData + szData1, szData2 );
pNew3DSound->m_pBuffers[i]->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;
}






For other useful formating tips, check out the Forum FAQ.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this