Issues with multiple sound buffers using D3DSounds

Started by
1 comment, last by PhilKing83 17 years, 9 months ago
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]
Advertisement
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 Soundsstruct 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;}


For other useful formating tips, check out the Forum FAQ.
[s]--------------------------------------------------------[/s]chromecode.com - software with source code
Thank you very much, the change has been made!

This topic is closed to new replies.

Advertisement