• Advertisement
Sign in to follow this  

IDirectSound8::CreateSoundBuffer() - Invalid call?

This topic is 4228 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've just finished writing some classes to provide access to basic sound playing features via DirectSound but I've run into a problem with creating secondary sound buffers via IDirectSound8::CreateSoundBuffer(). I'm not sure if my code is missing something or what because I've not really used DirectSound much so I've put together a minimal example of the code that produces the error, can anyone see anything wrong with this code?
//Note: I do check all function return values and everything goes fine
//      up until the call to IDirectSound8::CreateSoundBuffer()
LPDIRECTSOUND8 lpds = 0;
LPDIRECTSOUNDBUFFER lpdsb = 0;
DSBUFFERDESC dsbd;
WAVEFORMATEX wfmt;
HWND hWnd; //The application window handle, created elsewhere

//Create the DirectSound8 object and set the cooperative level
DirectSoundCreate8(0, &lpds, 0);
lpds->SetCooperativeLevel(hWnd, DSSCL_EXCLUSIVE);

//Here I call a function that uses winmm.lib functions (mmio*)
//to load a wav file into memory, everything works fine here
//and dsbd and wfmt are filled with information describing the
//loaded file.
LoadWavFile("w1.wav", &dsbd, &wfmt);

/*
dsbd now contains the following data
    dwSize = 36
    dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME
    dwBufferBytes = 1976
    dwReserved = 0
    lpwfxFormat = &wfmt
    guid3DAlgorithm = GUID_NULL

wfmt now contains the following data
    wFormatTag = 85
    nChannels = 1
    nSamplesPerSec = 11025
    nAvgBytesPerSec = 2000
    nBlockAlign = 1
    wBitsPerSample = 0
    cbSize = 12
*/

//Create the LPDIRECTSOUNDBUFFER object - Code fails here
//and returns DSERR_INVALIDCALL
lpds->CreateSoundBuffer(&dsbd, &lpdsb, 0);





The only thing I can think of is I remember having to set a sound format or something when I've used DirectSound in the past but unfortunately I don't have any of my old code or books as a reference at the moment, and I haven't used DirectSound for a while so I could be thinking of some other sound lib that I've used at some point. [Edited by - InsaneBoarder234 on July 28, 2006 6:57:37 AM]

Share this post


Link to post
Share on other sites
Advertisement
If you install the debug runtimes, they should tell you what's wrong. You need the same SDK version as your DirectX version (or later), and goto control pannel -> DirectX, and enable the debug runtimes for DirectSound.

Share this post


Link to post
Share on other sites
VC++ 2003, and I'm not getting any output from DirectSound in the debug window.


'Test.exe': Loaded 'C:\C++\Test\Debug\Test.exe', Symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\ntdll.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\kernel32.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\user32.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\gdi32.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\dsound.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\msvcrt.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\advapi32.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\rpcrt4.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\ole32.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\winmm.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\version.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\imm32.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\lpk.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\usp10.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\uxtheme.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\MSCTFIME.IME', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\wdmaud.drv', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\setupapi.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\wintrust.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\crypt32.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\msasn1.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\imagehlp.dll', No symbols loaded.
'Test.exe': Unloaded 'C:\WINDOWS\system32\setupapi.dll'
'Test.exe': Unloaded 'C:\WINDOWS\system32\wdmaud.drv'
'Test.exe': Loaded 'C:\WINDOWS\system32\wdmaud.drv', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\setupapi.dll', No symbols loaded.
'Test.exe': Unloaded 'C:\WINDOWS\system32\setupapi.dll'
'Test.exe': Loaded 'C:\WINDOWS\system32\msacm32.drv', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\msacm32.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\midimap.dll', No symbols loaded.
'Test.exe': Loaded 'C:\WINDOWS\system32\setupapi.dll', No symbols loaded.
'Test.exe': Unloaded 'C:\WINDOWS\system32\setupapi.dll'
'Test.exe': Loaded 'C:\WINDOWS\system32\setupapi.dll', No symbols loaded.
'Test.exe': Unloaded 'C:\WINDOWS\system32\setupapi.dll'
'Test.exe': Loaded 'C:\WINDOWS\system32\setupapi.dll', No symbols loaded.
'Test.exe': Unloaded 'C:\WINDOWS\system32\setupapi.dll'
'Test.exe': Loaded 'C:\WINDOWS\system32\setupapi.dll', No symbols loaded.
'Test.exe': Unloaded 'C:\WINDOWS\system32\setupapi.dll'
'Test.exe': Loaded 'C:\WINDOWS\system32\ksuser.dll', No symbols loaded.
The thread 'Win32 Thread' (0x8f4) has exited with code 0 (0x0).
The thread 'Win32 Thread' (0xf0c) has exited with code 0 (0x0).
The thread 'Win32 Thread' (0xa90) has exited with code 0 (0x0).
The program '[2548] Test.exe: Native' has exited with code 0 (0x0).



This is from the minimal code that I posted in the first post, it still fails with DSERR_INVALIDCALL on the call to IDirectSound8::CreateSoundBuffer().

Share this post


Link to post
Share on other sites
I'm using the June 2006 SDK, and just to clarify I have enabled the debug runtimes for both DirectSound(displayed as Audio on the control panel applet) and DirectMusic and turned the output up to the maximum.

The exact code I'm using to reproduce the problem outside of my main project is this:


#pragma comment(lib, "dsound.lib")
#include <dsound.h>
#include <sstream>

LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if(msg == WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
else
{
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
//-----------------
// Create the window
//-----------------
WNDCLASSEX wc;
HWND hwnd;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hIconSm = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = WinProc;
wc.lpszClassName = "DSTEST";
wc.lpszMenuName = 0;
wc.style = CS_OWNDC;
if(!RegisterClassEx(&wc))
{
return 0;
}
hwnd = CreateWindowEx(0, "DSTEST", "DirectSound Test",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT,
CW_USEDEFAULT, 400, 400, 0, 0, GetModuleHandle(0), 0);
if(!hwnd)
{
return 0;
}

//-----------------
// Minimal DS Create Buffer test
//-----------------
LPDIRECTSOUND8 lpds = 0;
LPDIRECTSOUNDBUFFER lpdsb = 0;
DSBUFFERDESC dsbd;
WAVEFORMATEX wfmt;

if(FAILED(DirectSoundCreate8(0, &lpds, 0))
{
return 0;
}
if(FAILED(lpds->SetCooperativeLevel(hwnd, DSSCL_NORMAL))
{
return 0;
}

dsbd.dwSize = 36;
dsbd.dwFlags = 0;
dsbd.dwBufferBytes = 1976;
dsbd.dwReserved = 0;
dsbd.lpwfxFormat = &wfmt;
dsbd.guid3DAlgorithm = GUID_NULL;

wfmt.wFormatTag = 85;
wfmt.nChannels = 1;
wfmt.nSamplesPerSec = 11025;
wfmt.nAvgBytesPerSec = 2000;
wfmt.nBlockAlign = 1;
wfmt.wBitsPerSample = 0;
wfmt.cbSize = 0;

HRESULT hr = lpds->CreateSoundBuffer(&dsbd, &lpdsb, 0);
if(FAILED(hr))
{
std::stringstream ss;
ss<<"Error creating sound buffer: "<<hr;
MessageBox(hwnd, ss.str().c_str(), "Error", MB_OK);
lpds->Release();
DestroyWindow(hwnd);
return 0;
}
MessageBox(hwnd, "Sound buffer created successfully.", "Error", MB_OK);

lpdsb->Release();
lpds->Release();
DestroyWindow(hwnd);

return 0;
}




The code aways ends with the error DSERR_INVALIDCALL returned from CreateSoundBuffer(). And the debug output only displays what I shown in the previous post.

Share this post


Link to post
Share on other sites
I'll take a look when I get home. One thing you could try - set the format tag of WAVEFORMATEX to WAVE_FORMAT_PCM. ISTR that's all DirectSound supports.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
set the format tag of WAVEFORMATEX to WAVE_FORMAT_PCM. ISTR that's all DirectSound supports.


nope.

tag can be WAVE_FORMAT_EXTENSIBLE nowadays.
(neway this is not very important for him..ya ya i know )

by the way,
theres no code that for loading the WAV data.

theres just a "calling" function for load the wav.
"LoadWavFile("w1.wav", &dsbd, &wfmt);"
this function work fine?

Share this post


Link to post
Share on other sites
One thing I noticed: You said that after loading the file, wfmt.cbSize = 12. Which means that in addition to the size of the WAVEFORMATEX structure, there are 12 more bytes of data. But you had LoadWavFile() load all this data into a WAVEFORMATEX structure, which doesn't have those 12 extra bytes. Which means that you're writing to memory that you shouldn't be; by itself this is bad, and that extra 12 bytes is probably getting altered before or while you pass the wfmt structure to DirectSound. When DirectSound tries to get info from those 12 bytes, it's all corrupt, so it issues an invalid call.

What those 12 bytes are for, I don't know. It's apparently not a WAVEFORMATEXTENSIBLE, since that should add 22 bytes extra, I believe. Perhaps the cbSize member should be 0, but you simply never initialized it properly?

Share this post


Link to post
Share on other sites
Also, it seems that your dsbd.dwBufferBytes, wfmt.nChannels, wfmt.nSamplesPerSec, wfmt.nAvgBytesPerSec, wfmt.nBlockAlign, and wfmt.wBitsPerSample completley disagree.

If there are indeed an average of 2000 bytes per second, and there are a total of 1976 bytes, then that means that your file is 0.988 seconds long. If there is one channel and each block is 1 byte, then your bits per sample should be 8, not 0. And if you have 1 byte per sample/block, then you should have 2000 samples per second, to match your bytes per second, instead of 11025. Because otherwise, if your file is actually 0.988 seconds long, and you have 11025 samples per second, then you should have ~10893 samples, and thus ~10893 bytes.

So it seems that the LoadWavFile() is doing a poor job of initializing the data in wfmt.

Share this post


Link to post
Share on other sites
Here is the source for the LoadWav function.
m_dsbd is the DSBUFFERDESC object.
m_wfmt is the WAVEFORMATEX object.


bool SoundLoader::LoadWav(std::string sFilename)
{
HMMIO hFile;
MMCKINFO ckParent;
MMCKINFO ckChild;

//-----------------
// Load wav file
//-----------------
//Open the file
hFile = mmioOpen((char*)sFilename.c_str(), 0, MMIO_READ | MMIO_ALLOCBUF);
if(hFile == 0)
{
//Error
Log::get()<<"[Sound] ERROR: LoadWav("<<sFilename<<") mmioOpen failed.\n";
return false;
}

//Search for a WAVE chunk header
ckParent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
if(mmioDescend(hFile, &ckParent, 0, MMIO_FINDRIFF) != MMSYSERR_NOERROR)
{
//Error, the file doesn't contain WAVE data
Log::get()<<"[Sound] ERROR: LoadWav("<<sFilename<<") WAVE chunk not found.\n";
mmioClose(hFile, 0);
return false;
}

//Search for the fmt chunk
ckChild.ckid = mmioFOURCC('f', 'm', 't', ' ');
if(mmioDescend(hFile, &ckChild, &ckParent, MMIO_FINDCHUNK) != MMSYSERR_NOERROR)
{
//Error, fmt chunk not found
Log::get()<<"[Sound] ERROR: LoadWav("<<sFilename<<") fmt chunk not found.\n";
mmioClose(hFile, 0);
return false;
}

//Read in the fmt chunk
if(mmioRead(hFile, (HPSTR)&m_wfmt, sizeof(WAVEFORMATEX)) != sizeof(WAVEFORMATEX))
{
//Error reading in the wave format
Log::get()<<"[Sound] ERROR: LoadWav("<<sFilename<<") error reading fmt chunk.\n";
mmioClose(hFile, 0);
return false;
}

//Ascend out of the fmt chunk
mmioAscend(hFile, &ckChild, 0);

//Search for the data chunk
ckChild.ckid = mmioFOURCC('d', 'a', 't', 'a');
if(mmioDescend(hFile, &ckChild, &ckParent, MMIO_FINDCHUNK) != MMSYSERR_NOERROR)
{
//Error finding the data chunk
Log::get()<<"[Sound] ERROR: LoadWav("<<sFilename<<") data chunk not found.\n";
mmioClose(hFile, 0);
return false;
}

//Get the size of the sound data
m_Length = ckChild.cksize;

//Allocate a buffer for the sound data
m_Data = new unsigned char[m_Length];

//Read in the sound data
if(mmioRead(hFile, (HPSTR)m_Data, m_Length) != m_Length)
{
//Error reading in the wave data
Log::get()<<"[Sound] ERROR: LoadWav("<<sFilename<<") error reading in the sound data.\n";
mmioClose(hFile, 0);
delete[] m_Data;
return false;
}

//Close the file
mmioClose(hFile, 0);

//-----------------
// Set up the DSBUFFERDESC object
//-----------------
m_dsbd.dwSize = sizeof(DSBUFFERDESC);
m_dsbd.dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME;
m_dsbd.dwBufferBytes = m_Length;
m_dsbd.dwReserved = 0;
m_dsbd.lpwfxFormat = &m_wfmt;
m_dsbd.guid3DAlgorithm = GUID_NULL;

//-----------------
// Success
//-----------------
return true;
}




Also, the wav file I'm opening opens and plays fine in Windows Media Player.

[Edited by - InsaneBoarder234 on July 29, 2006 8:42:02 AM]

Share this post


Link to post
Share on other sites
I tried the WAVEFORMAT change and it was still reading in the same values, so as those values are invalid I thought I'd check them via some other method and checked the file properties in explorer to find that the wav file was MP3 encoded. Argh!

I'll add a check in there to make sure that the format is WAVE_FORMAT_PCM. I've tested the code with one of the .wav files that comes with Windows and it works up to a different point that I'm about to look into.

Thanks for the help all, and I apologise for the dodgy wav file!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement