I'm looking for some help on a very strange issue I'm having with both DirectSound and Ogg files.
I have my own DirectX/C++ 2D engine which I have already used for games (http://www.spiritvg.com). It (mostly) works well on streaming Ogg audio and playing preloaded PCM Wavs.
But my new game takes a lot to load, so I'm moving from WAV to Ogg. Now I'm reading Ogg files into DSound buffers instead of doing it from PVM Wav files. The result should be the same, but I'm hearing glitches at the end of every sample.
I use the last version of LibOgg (1.2.0) and LibVorbis (1.3.1). I've also made sure that OGG files are converted using the last LibVorbis encoding (using the appropriate version of oggDropXPd for the test file). I've opened the test file with Winamp and Audacity, and works fine on both of them.
I've even tried to add some zeros at the end of the read data, but it won't help, as I inspected the buffer and found the glitch itself seems to be there. So it isn't DSound neither.
To finally make me mad, everything seems to be working fine when streaming (not preloading) audio.
I'm leaving the loading function source code here.
//--------------------------------------------------------------------//--------------------------------------------------------------------DWORD CSistemaSoAbstracte::LoadSoOgg(LPDIRECTSOUNDBUFFER *pSoundBuffer, char *pszFileName){ DWORD bufSize = -1; CSistemaFicheros::TFichero *pFile = NULL; char *pFileData = NULL; bool bOk = true; // Opening the file if (bOk) { pFile = g_pFileSys->OpenFile(pszFileName, CSistemaFicheros::FL_LECTURA | CSistemaFicheros::FL_BINARIO); if (!pFile) { GLOGERR(("Couldn't open file %s.", pszFileName)); bOk = false; } } // Assigning file to OggVorbis_File OggVorbis_File *pVF = NULL; if (bOk) { pVF = NEW(OggVorbis_File); bOk = pVF != NULL; } if (bOk) { ov_callbacks ovCallbacks; ovCallbacks.read_func = read_func; ovCallbacks.seek_func = seek_func; ovCallbacks.close_func = close_func; ovCallbacks.tell_func = tell_func; if (ov_open_callbacks(pFile, pVF, NULL, 0, ovCallbacks)) { bOk = false; GLOGERR(("File %s is not an appropriate OGG.", pszFileName)); } } // Decoding file data to memory DWORD dwSoundDataSize = 0; vorbis_info *vi = NULL; if (bOk) { vi = ov_info(pVF,-1); // Allocating data buffer dwSoundDataSize = (ov_pcm_total(pVF, -1) * vi->channels * 2); pFileData = NEW (char[dwSoundDataSize]); // Loop for decoding int iSizeRead = -1; int bitstream = 0; DWORD dwBytesLeidos = 0; while (iSizeRead != 0) { iSizeRead = ov_read(pVF, ((char *)&pFileData[dwBytesLeidos]), dwSoundDataSize - dwBytesLeidos, 0, 2, 1, &bitstream); dwBytesLeidos += iSizeRead; } ASSERT(dwBytesLeidos == dwSoundDataSize); } // Creating DSound Buffer if (bOk && (*pSoundBuffer == NULL)) { char **ptr=ov_comment(pVF,-1)->user_comments; while(*ptr) { GLOGINF(("%s\n",*ptr)); ++ptr; } WAVEFORMATEX WaveFormat; WaveFormat.wFormatTag = WAVE_FORMAT_PCM; WaveFormat.nChannels = vi->channels; WaveFormat.nSamplesPerSec = vi->rate; WaveFormat.nAvgBytesPerSec = vi->rate * vi->channels * 2; // 2 - 16 bits ergo 2 bytes per channel WaveFormat.nBlockAlign = 4; // 2 * BitsPerSample / 8 WaveFormat.wBitsPerSample = 16; WaveFormat.cbSize = 0; //GLOGINF(("\nBitstream is %d channel, %ldHz\n", vi->channels, vi->rate)); //GLOGINF(("\nDecoded length: %ld samples\n", (long)ov_pcm_total(pVF,-1))); //GLOGINF(("Encoded by: %s\n\n",ov_comment(pVF,-1)->vendor)); DSBUFFERDESC DescripcioBuffer; memset(&DescripcioBuffer, 0, sizeof(DSBUFFERDESC)); DescripcioBuffer.dwSize = sizeof(DSBUFFERDESC); DescripcioBuffer.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLVOLUME; DescripcioBuffer.dwBufferBytes = dwSoundDataSize; DescripcioBuffer.lpwfxFormat = &WaveFormat; if (FAILED(m_IDirectSound->CreateSoundBuffer(&DescripcioBuffer, pSoundBuffer, NULL))) { GLOGERR(("No s'ha pogut crear el DSoundBuffer carregant el fitxer %s.", pszFileName)); bOk = false; } } // Copying data to buffer if (bOk) { LPVOID pSoundBufferDataPointer = NULL; LPVOID pSoundBufferDataPointer2 = NULL; DWORD dwWritableBytes = 0; DWORD dwWritableBytes2 = 0; if (FAILED((*pSoundBuffer)->Lock(0, 0, &pSoundBufferDataPointer, &dwWritableBytes, &pSoundBufferDataPointer2, &dwWritableBytes2, DSBLOCK_ENTIREBUFFER))) { GLOGERR(("Couldn't lock DSoundBuffer loading %s.", pszFileName)); bOk = false; } else { memcpy(pSoundBufferDataPointer, &pFileData[TAMANYCAPSALERA], dwSoundDataSize); if (FAILED((*pSoundBuffer)->Unlock(pSoundBufferDataPointer, dwWritableBytes, pSoundBufferDataPointer2, dwWritableBytes2))) { GLOGERR(("Couldn't unlock DSoundBuffer when loading %s ... this shouldn't be happening :-P", pszFileName)); bOk = false; } else { bufSize = dwSoundDataSize; } } } if (pFileData) { DISPOSE_ARRAY (pFileData); } if (pFile) { g_pFileSys->CloseFile(pFile); } if (pVF) { ov_clear(pVF); DISPOSE(pVF); } return bufSize;}
Can anyone give me some advice on this? I would really appreciate.
Thanks a lot in advance.