Archived

This topic is now archived and is closed to further replies.

How to load a sound?

This topic is 5022 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I know it sounds trivial but I started learning DirectSound an hour ago Initialization is complete, primary and secondary buffers are ready and here I hit the wall. How to load a small wave file and put it into the buffer? Is there a method to do this? (just like loading bitmaps onto surfaces) Or do I have to create my own function from scratch? Anyone got a "LoadSound()" function? Or anybody knows where to get it? Thanks

Share this post


Link to post
Share on other sites
What version of DirectX are you using? If you''re using 8 you can use this (from the tutorial on this site):

char SearchPath[MAX_PATH];
IDirectMusicSegment8* pSegment = NULL;

CoCreateInstance(CLSID_IDirectMusicSegment, NULL, CLSTX_INPROC, IID_IDirectMusicSegment8, (void**)&pSegment);

GetCurrentDirectory(MAX_PATH, SearchPath);

// g_pMusicLoader: Predefined IDirectMusicLoader8*

g_pMusicLoader->SetSearchDirectory(GUID_DirectMusicAllTypes, SearchPath, FALSE);

g_pMusicLoader->LoadObjectFromFile(CLSID_DirectMusicSegment, IID_IDirectMusicSebment8, Filename, (void**)&pSegment);

// g_pPerformance: Predefined IDirectMusicPerformance8*

pSegment->Download(g_pPerformance);

g_pPerformance->PlaySegmentEx(pSegment, NULL, NULL, 0, 0, NULL, NULL, NULL);

// To stop

g_pPerformance->StopEx(pSegment, 0, 0);


This is just a modified version of the DirectAudio8 tutorial here on GameDev.

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

Share this post


Link to post
Share on other sites
Yes, have a look at the dsutil.h and dsutil.cpp files in DXSDK\Samples\C++\Common\Include
Use a CSoundManager class to create CSound objects. You specify a filename on creation so everything is already done Unless you are doing this as a learning excercise in which case you will learn next to nothing using this method.

Share this post


Link to post
Share on other sites
i ripped the stuff out of the 3d directsound example and made a class out of it, its quite messy looking but works nicely

you need to include string header

class DWave
{
private:
LPDIRECTSOUND8 m_pDS;

WAVEFORMATEX* m_pwfx;
HMMIO m_hmmio;
MMCKINFO m_ck;
MMCKINFO m_ckRiff;
MMIOINFO m_mmioinfoOut;
DWORD m_dwFlags;

BYTE* m_pbData;
BYTE* m_pbDataCur;
ULONG m_ulDataSize;
CHAR* m_pResourceBuffer;

void Open( char strFileName[], WAVEFORMATEX* pwfx, DWORD dwFlags )
{
m_dwFlags = dwFlags;

if( m_dwFlags == 1 )
{
if(m_pwfx)
{
delete[] m_pwfx;
m_pwfx=NULL;
}

m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ );

if( NULL == m_hmmio )
{
DWORD dwSize=0;
VOID* pvRes=NULL;

m_pResourceBuffer = new CHAR[ dwSize ];
memcpy( m_pResourceBuffer, pvRes, dwSize );

MMIOINFO mmioInfo;
ZeroMemory( &mmioInfo, sizeof(mmioInfo) );
mmioInfo.fccIOProc = FOURCC_MEM;
mmioInfo.cchBuffer = dwSize;
mmioInfo.pchBuffer = (CHAR*) m_pResourceBuffer;

m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ );
}

ReadMMIO();
ResetFile();

m_ck.cksize = m_ck.cksize;
}
else
{
m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_CREATE );
WriteMMIO( pwfx );
ResetFile();
}
}


void ReadMMIO()
{
MMCKINFO ckIn;
PCMWAVEFORMAT pcmWaveFormat;
m_pwfx = NULL;

mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 );
ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ;
mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat));

if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM )
{
m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ];
memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
m_pwfx->cbSize = 0;
}
else
{
WORD cbExtraBytes = 0L;
mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) ;
m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ];

memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
m_pwfx->cbSize = cbExtraBytes;

if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), cbExtraBytes ) != cbExtraBytes )
{
if(m_pwfx)
{
delete m_pwfx;
m_pwfx=NULL;
}
}
}

if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) )
{
if(m_pwfx)
{
delete m_pwfx;
m_pwfx=NULL;
}
}


}

void ResetFile()
{
if( m_dwFlags == 1 )
{
mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC),SEEK_SET );
m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ;
}
else
{
m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
m_ck.cksize = 0;
mmioCreateChunk( m_hmmio, &m_ck, 0 ) ;
mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 );
}
}

void Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead )
{
MMIOINFO mmioinfoIn;

if( pdwSizeRead != NULL )
*pdwSizeRead = 0;

mmioGetInfo( m_hmmio, &mmioinfoIn, 0 );
UINT cbDataIn = dwSizeToRead;

if( cbDataIn > m_ck.cksize )
cbDataIn = m_ck.cksize;

m_ck.cksize -= cbDataIn;

for( DWORD cT = 0; cT < cbDataIn; cT++ )
{
if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ );

*((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext);
mmioinfoIn.pchNext++;
}

mmioSetInfo( m_hmmio, &mmioinfoIn, 0 );

if( pdwSizeRead != NULL )
*pdwSizeRead = cbDataIn;
}

void Close()
{
if( m_dwFlags == 1 )
{
mmioClose( m_hmmio, 0 );
m_hmmio = NULL;

if(m_pResourceBuffer)
{
delete[] m_pResourceBuffer;
m_pResourceBuffer=NULL;
}
}
else
{
m_mmioinfoOut.dwFlags |= MMIO_DIRTY;
mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 );
mmioAscend( m_hmmio, &m_ck, 0 );
mmioAscend( m_hmmio, &m_ckRiff, 0 ) ;
mmioSeek( m_hmmio, 0, SEEK_SET );
(INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 );
m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't');

if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) )
{
DWORD dwSamples = 0;
mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) );
mmioAscend( m_hmmio, &m_ck, 0 );
}

mmioAscend( m_hmmio, &m_ckRiff, 0 );
mmioClose( m_hmmio, 0 );
m_hmmio = NULL;
}
}

void WriteMMIO( WAVEFORMATEX *pwfxDest )
{
DWORD dwFactChunk;
MMCKINFO ckOut1;
dwFactChunk = (DWORD)-1;

m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E');
m_ckRiff.cksize = 0;
mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ;

m_ck.ckid = mmioFOURCC('f', 'm', 't', ' ');
m_ck.cksize = sizeof(PCMWAVEFORMAT);
mmioCreateChunk( m_hmmio, &m_ck, 0 );

if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM )
mmioWrite( m_hmmio, (HPSTR) pwfxDest, sizeof(PCMWAVEFORMAT));
else
(UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, sizeof(*pwfxDest) + pwfxDest->cbSize );

mmioAscend( m_hmmio, &m_ck, 0 ) ;
ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't');
ckOut1.cksize = 0;
mmioCreateChunk( m_hmmio, &ckOut1, 0 );

mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk));
mmioAscend( m_hmmio, &ckOut1, 0 );
}

LPDIRECTSOUNDBUFFER m_apDSBuffer;
DWORD m_dwDSBufferSize;
DWORD m_dwCreationFlags;

void CSoundA(char filename[] , GUID guid3DAlgorithm ,DWORD dwFlags = 0)
{
m_pwfx = NULL;
m_hmmio = NULL;
m_pResourceBuffer = NULL;

Open( filename, NULL, 1 );
DSBUFFERDESC dsbd;
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = dwFlags;
dsbd.dwBufferBytes = m_ck.cksize;
dsbd.guid3DAlgorithm = guid3DAlgorithm;
dsbd.lpwfxFormat = m_pwfx;
m_pDS->CreateSoundBuffer( &dsbd, &m_apDSBuffer, NULL );
m_dwDSBufferSize = m_ck.cksize;
m_dwCreationFlags = dwFlags;
FillBufferWithSound( m_apDSBuffer, FALSE );

Close();
}

void FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger )
{

VOID* pDSLockedBuffer = NULL;
DWORD dwDSLockedBufferSize = 0;
DWORD dwWavDataRead = 0;

RestoreBuffer( pDSB, NULL );
pDSB->Lock( 0, m_dwDSBufferSize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L );

ResetFile();
Read( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, &dwWavDataRead ) ;

if( dwWavDataRead == 0 )
FillMemory( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, (BYTE)(m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
else if( dwWavDataRead < dwDSLockedBufferSize )
{
if( bRepeatWavIfBufferLarger )
{
DWORD dwReadSoFar = dwWavDataRead;
while( dwReadSoFar < dwDSLockedBufferSize )
{
ResetFile();
Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, dwDSLockedBufferSize - dwReadSoFar, &dwWavDataRead );
dwReadSoFar += dwWavDataRead;
}
}
else
FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, dwDSLockedBufferSize - dwWavDataRead, (BYTE)(m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) );
}

pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );
}

void RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored )
{
HRESULT hr;

if( pbWasRestored )
*pbWasRestored = FALSE;

DWORD dwStatus;
pDSB->GetStatus( &dwStatus );

if( dwStatus & DSBSTATUS_BUFFERLOST )
{
do
{
hr = pDSB->Restore();
if( hr == DSERR_BUFFERLOST )
Sleep( 10 );
}
while( ( pDSB->Restore() ) == DSERR_BUFFERLOST );

if( pbWasRestored != NULL )
*pbWasRestored = TRUE;
}
}

HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer )
{
*ppDS3DBuffer = NULL;
return m_apDSBuffer->QueryInterface( IID_IDirectSound3DBuffer, (VOID**)ppDS3DBuffer );
}

LPDIRECTSOUND3DBUFFER g_pDS3DBuffer;
DS3DBUFFER g_dsBufferParams;
bool threeDFlag;

long volume;
float posX, posY, posZ;
float minDist;
float maxDist;
float rolloff;

public:
~DWave()
{
if(m_apDSBuffer)
{
m_apDSBuffer->Release();
m_apDSBuffer=NULL;
}

if(g_pDS3DBuffer)
{
g_pDS3DBuffer->Release();
g_pDS3DBuffer=NULL;
}
}

void create(LPDIRECTSOUND8 dsDevice,string filename, int threeDimensionLevel=0)
{
m_pDS=dsDevice;

LPSTR cfilename =strdup(filename.c_str());
switch (threeDimensionLevel) {
case 0:
CSoundA(cfilename,GUID_NULL,DSBCAPS_CTRLVOLUME);
threeDFlag=false;
break;

case 1:
CSoundA(cfilename,GUID_NULL,DSBCAPS_CTRL3D|DSBCAPS_CTRLVOLUME);
break;

case 2:
CSoundA(cfilename,DS3DALG_NO_VIRTUALIZATION,DSBCAPS_CTRL3D|DSBCAPS_CTRLVOLUME);
break;

case 3:
CSoundA(cfilename,DS3DALG_HRTF_LIGHT,DSBCAPS_CTRL3D|DSBCAPS_CTRLVOLUME);
break;

case 4:
CSoundA(cfilename,DS3DALG_HRTF_FULL,DSBCAPS_CTRL3D|DSBCAPS_CTRLVOLUME);
break;
}



if (threeDimensionLevel!=0)
{

Get3DBufferInterface( 0, &g_pDS3DBuffer );
g_dsBufferParams.dwSize = sizeof(DS3DBUFFER);
g_pDS3DBuffer->GetAllParameters( &g_dsBufferParams );
g_dsBufferParams.dwMode = DS3DMODE_HEADRELATIVE;
g_pDS3DBuffer->SetAllParameters( &g_dsBufferParams, DS3D_IMMEDIATE );

DSBCAPS dsbcaps;
ZeroMemory( &dsbcaps, sizeof(DSBCAPS) );
dsbcaps.dwSize = sizeof(DSBCAPS);

m_apDSBuffer->GetCaps( &dsbcaps );
threeDFlag=true;
}

threeDFlag=false;
setMinDistance(1);
setMaxDistance(1);
setPosition(0,0,0);
setVolume(0);
}

void setPosition(float x, float y, float z)
{
if (threeDFlag)
g_pDS3DBuffer->SetPosition(x ,y,z,DS3D_IMMEDIATE);
}

void setMinDistance(float value)
{
if (threeDFlag)
g_pDS3DBuffer->SetMinDistance(value,DS3D_IMMEDIATE);

}

void setMaxDistance(float value)
{
if (threeDFlag)
g_pDS3DBuffer->SetMaxDistance(value,DS3D_IMMEDIATE);

}

void setVolume(int value)
{
m_apDSBuffer ->SetVolume(volume);
}

void play()
{
m_apDSBuffer ->Stop();
m_apDSBuffer ->SetCurrentPosition(0);
m_apDSBuffer->Play(0,0,0 );
}


void stop()
{
m_apDSBuffer ->Stop();
m_apDSBuffer ->SetCurrentPosition(0);
}

bool isPlaying()
{
bool answer=false;
DWORD dwStatus = 0;
m_apDSBuffer->GetStatus( &dwStatus );
answer |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 );

return answer;
}
};



basically to use it is:
//initialise
DWave sndGunshot;

//load
sndGunshot.create(dsDevice,"gunshot.wav",0);

//play
sndGunshot.play();


The 0 at the end represents the 3d sound level,
0 is none, 1 -4 , 4 being slowest but best 3d level.

ive got other functions that set the position etc

.............dammmit programmer16 thats direct music stop getting mixed up!


[edited by - johnnyBravo on March 17, 2004 6:39:04 PM]

Share this post


Link to post
Share on other sites
All you need to do is to use the DirectSoundBuffer methods ->Lock() and ->Unlock() to load your buffer. If it is a sound that will be repeated over and over again all you need to do is load it once and then call ->Play() when you want to use it. If you have a huge amount of sound that will be continuously loaded (like a CD track) then you will have to do a streaming buffer.

The ->Lock() function opens the buffer for writing. You specify where and how much you want to write (maybe the whole buffer) and it returns a set of pointers (two pointers because it is a circular buffer). Then you can just ''memcpy()'' your sound into the buffer. Then you call the ->Unlock() function and the job is done. To hear it call ->Play().

Here''s some simple code from a streaming example:

===================================================
void Mtransceiver::SendData(void)
{
void *firstBuf, *secondBuf;
DWORD firstLen, secondLen;

// Lock the send buffer and load some data
if (FAILED(pdsTXSecBufOb->Lock(
txwriteposition,// Offset in bytes from start to where lock begins (this is my pointer needed to keep track of where I am for streaming purposes)
bytestoread, // Number of bytes to lock
&firstBuf, // Returns a pointer to start of first buffer
&firstLen, // Returns number of bytes in first buffer
&secondBuf, // Returns pointer to start of second buffer (may be NULL)
&secondLen, // Returns number of bytes in second buffer (not needed if second buffer is NULL)
0)))
{
StopSending(0);
return;
}

// Copy the data into the first buffer (txbuffer is my pre-loaded junk)
memcpy(firstBuf, txbuffer, firstLen);

// Is there more (wrapped) data to copy? If so, append it to the first chunk of copied data
if (secondLen)
{
memcpy(secondBuf, txbuffer + firstLen, secondLen);
}

// Unlock the buffer
if (FAILED(pdsTXSecBufOb->Unlock(firstBuf, firstLen, secondBuf, secondLen)))
{
StopSending(0);
return;
}

LoadSendBuffer(); // THis loads ''txbuffer'' for next time (only needed for streaming)
}
=========================================

Hope it helps. Its a little more low level than the other approaches, but that''s how it works.

Brian

Share this post


Link to post
Share on other sites
Thanks Gyannea.

I like low level But that''s not the point. You see, I need to see a code sample which would tell me how to load a specific file ("sound.wav") to the sound buffer (or to any buffer )

I''m a beginner in windows programming, but I managed to startup and use DirectDraw so I make terribly coded,mute games for the pleeasure of creation itself. I would never suspect that loading a wave file is more complicated than loading a bitmap onto a surface... But it''s probably just my lack of knowledge.

Thanks anyway!

Share this post


Link to post
Share on other sites
uh, johnnyBravo, i''m having problems using your code. i get some wierd error with the GUID_NULL

c:\documents and settings\owner\desktop\game - english class\game\dwave.h(334) : error C2065: ''GUID_NULL'' : undeclared identifier

any ideas on how to fix that?

Share this post


Link to post
Share on other sites
try adding these
#define INITGUID
#include <dsound.h>
#include <string>

and add these to the linkers:
dxguid.lib, dsound.lib

but see if you can run the directsound sdk samples, the 3d one would be ideal.

if that runs,mine will work

(you probably dont need INITGUID, i think i had that in mine because i was attempting dplay)

[edited by - johnnyBravo on March 18, 2004 7:10:04 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by johnnyBravo
.............dammmit programmer16 thats direct music stop getting mixed up!
[edited by - johnnyBravo on March 17, 2004 6:39:04 PM]


I''m sorry, I was just copying what I learned from the DirectAudio 8 tutorial here on GameDev.net. Whats the difference between DirectMusic and DirectSound (weren''t they combined into DirectAudio 8)? Thanks!


/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

Share this post


Link to post
Share on other sites