Archived

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

frozentax

Sound doesn't play smoothly

Recommended Posts

Hello, I'm streaming an OGG vorbis file via DirectSound using the code provided in the tutorial. I'm decoding 4096 or less bytes of PCM data at a time, and writing to the DirectSound buffer. However the sound doesn't play smoothly and there is a crackling or subtle static sound the whole time while playing. Code is as follows:
    
void main()
{
	HANDLE hThread = NULL;

	if(!InitDSound(GetConsoleHwnd();))
		cout << "Couldn't init DSound.\n";

	if(!SetupStreamBuffer())
		cout << "Couldn't set stream.\n";

	hThread = (HANDLE)_beginthread(Messages, 0, NULL );

	getch();

}

BOOL InitDSound(HWND hwnd)
{
   // Create DirectSound

 
    if FAILED(DirectSoundCreate(NULL, &lpds, NULL)) 
        return FALSE;
 
    // Set co-op level

 
    if FAILED(IDirectSound_SetCooperativeLevel(lpds, hwnd,
DSSCL_PRIORITY))
        return FALSE;

	// Obtain primary buffer

 
    ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC));
    dsbdesc.dwSize = sizeof(DSBUFFERDESC);
    dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
    if FAILED(lpds->CreateSoundBuffer(&dsbdesc, &lpdsbPrimary, NULL))
        return FALSE;

	// Set primary buffer format

 
    WAVEFORMATEX wfx;
    memset(&wfx, 0, sizeof(WAVEFORMATEX)); 
    wfx.wFormatTag = WAVE_FORMAT_PCM; 
    wfx.nChannels = 2; 
    wfx.nSamplesPerSec = 44100; 
    wfx.wBitsPerSample = 16; 
    wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
    wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
 
    lpdsbPrimary->SetFormat(&wfx); 
 
    return TRUE;
}  // InitDSound()


BOOL SetupStreamBuffer()
{
    // Close any open file and release interfaces


	f = fopen("C:/a5/work/media/8_256.ogg", "rb");
	int eof=0;
		
	if(ov_open(f, &vf, NULL, 0))	
			return FALSE;

	if(!(vi = ov_info(&vf, -1)))
		return FALSE;

	pwfx = new WAVEFORMATEX;

	pwfx->wFormatTag      = WAVE_FORMAT_PCM; 
    pwfx->nChannels       = vi->channels; 
    pwfx->nSamplesPerSec  = vi->rate; 
    pwfx->wBitsPerSample  = vi->channels*8; 
    pwfx->nBlockAlign     = pwfx->wBitsPerSample / 8 * pwfx->nChannels;
    pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;

	memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); 
    dsbdesc.dwSize = sizeof(DSBUFFERDESC); 
    dsbdesc.dwFlags = 
            DSBCAPS_GETCURRENTPOSITION2   // Always a good idea

            | DSBCAPS_GLOBALFOCUS         // Allows background playing

            | DSBCAPS_CTRLPOSITIONNOTIFY; // Needed for notification


 // Set buffer size

	dsbdesc.dwBufferBytes = 4096;
	dsbdesc.lpwfxFormat = pwfx;
 
    if FAILED(IDirectSound_CreateSoundBuffer(lpds, &dsbdesc, &lpdsb,
NULL))
    {
        fclose(f);
        return FALSE; 
    }

	for (int i = 0; i < NUMEVENTS; i++)
    {
        rghEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (NULL == rghEvent[i]) return FALSE;
    }

	rgdsbpn[0].dwOffset = 0;
    rgdsbpn[0].hEventNotify = rghEvent[0];
    rgdsbpn[1].dwOffset = (dsbdesc.dwBufferBytes/2);
    rgdsbpn[1].hEventNotify = rghEvent[1];

	if FAILED(IDirectSoundBuffer_QueryInterface(lpdsb,
IID_IDirectSoundNotify, (VOID **)&lpdsNotify))
        return FALSE; 
 
    if FAILED(IDirectSoundNotify_SetNotificationPositions(lpdsNotify,
NUMEVENTS, rgdsbpn))
    {
        IDirectSoundNotify_Release(lpdsNotify);
        return FALSE;
    }

	IDirectSoundBuffer_Play(lpdsb, 0, 0, TRUE);

    return TRUE;
} // end of SetupStreamBuffer()


BOOL StreamToBuffer(DWORD dwPos)
{
    LONG            lNumToWrite;
    DWORD           dwStartOfs;
    VOID            *lpvPtr1, *lpvPtr2;
    DWORD           dwBytes1, dwBytes2;
    static DWORD    dwStopNextTime = 0xFFFF;
 
    if (dwStopNextTime == dwPos)   // All data has been played

    {
        lpdsb->Stop();
        dwStopNextTime = 0xFFFF;
        return TRUE;
    }
 
    if (dwStopNextTime != 0xFFFF)  // No more to stream, but keep

                                 // playing to end of data

        return TRUE;

	if (dwPos == 0)
        dwStartOfs = rgdsbpn[NUMEVENTS - 1].dwOffset;
    else
        dwStartOfs = rgdsbpn[dwPos-1].dwOffset;

	lNumToWrite = (LONG) rgdsbpn[dwPos].dwOffset - dwStartOfs;
    if (lNumToWrite < 0) lNumToWrite += dsbdesc.dwBufferBytes;

	IDirectSoundBuffer_Lock(lpdsb,
                     dwStartOfs,       // Offset of lock start

                     lNumToWrite,      // Number of bytes to lock

                     &lpvPtr1,         // Address of lock start

                     &dwBytes1,        // Count of bytes locked

                     &lpvPtr2,         // Address of wrap around

                     &dwBytes2,        // Count of wrap around bytes

                     0);  


	cbBytesRead = ov_read(&vf,pcmout,4096,0,2,1,¤t_section);

	memcpy( lpvPtr1, pcmout, cbBytesRead);


	if (cbBytesRead ==0)        // Reached end of file

    {
		fclose(f);
        FillMemory((PBYTE)lpvPtr1 + cbBytesRead,
                dwBytes1 - cbBytesRead, 
                (dsbdesc.lpwfxFormat->wBitsPerSample==8) ? 128 : 0);
        dwStopNextTime = dwPos;
    }

	IDirectSoundBuffer_Unlock(lpdsb, lpvPtr1, cbBytesRead, lpvPtr2, dwBytes2);
    
    return TRUE;
} // end StreamToBuffer()



void Messages( void *dummy)
{
	BOOL Done = FALSE;
while (!Done)
{
    DWORD dwEvt = MsgWaitForMultipleObjects(
            NUMEVENTS,      // How many possible events

            rghEvent,       // Location of handles

            FALSE,          // Wait for all?

            INFINITE,       // How long to wait

            QS_ALLINPUT);   // Any message is an event

 
    // WAIT_OBJECT_0 == 0 but is properly treated as an arbitrary

    // index value assigned to the first event, therefore we subtract

    // it from dwEvt to get the zero-based index of the event.

 
    dwEvt -= WAIT_OBJECT_0;
 
    // If the event was set by the buffer, there's input

    // to process. 

 
    if (dwEvt < NUMEVENTS) 
        StreamToBuffer(dwEvt); // copy data to output stream

 
    // If it's the last event, it's a message 

 
    else if (dwEvt == NUMEVENTS) 
    {         
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
        {
            if (msg.message == WM_QUIT) 
                Done = TRUE;
            else
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }  // end message processing

} // while (!Done)

}

    
This is likely a problem in StreamToBuffer, but is it possible that the initial value of dsbdesc.dwBufferBytes is incorrect? Any help would be greatly appreciated! Thanks, -Anthony Edited by - frozentax on December 19, 2001 4:19:12 PM

Share this post


Link to post
Share on other sites
If the sound is crackeling does it mean that a buffer is being overwritten? I would increase the size of dsbdesc.dwBufferBytes to the suggested "pwfx->nAvgBytesPerSec * 2" but I can only decode so many bytes from the OGG file at a time - not nearly as much as "pwfx->nAvgBytesPerSec * 2", so this creates long pauses between small audio samples.

Share this post


Link to post
Share on other sites