コード例 #1
0
ファイル: Dsutil.cpp プロジェクト: fenglinnet/ddongddongbae
BOOL DSReloadSoundBuffer(IDirectSoundBuffer *pDSB, LPCTSTR lpName)
{
    BOOL result=FALSE;
    BYTE *pbWaveData;
    DWORD cbWaveSize;
    void *pvBase;

    if (DSGetWaveResource(NULL, lpName, NULL, &pbWaveData, &cbWaveSize))
    {
        if (SUCCEEDED(IDirectSoundBuffer_Restore(pDSB)) &&
            DSFillSoundBuffer(pDSB, pbWaveData, cbWaveSize))
    {
        result = TRUE;
        }
    } else if( DSGetWaveFile(NULL, lpName, NULL, &pbWaveData, &cbWaveSize, &pvBase))
    {
        if (SUCCEEDED(IDirectSoundBuffer_Restore(pDSB)) &&
            DSFillSoundBuffer(pDSB, pbWaveData, cbWaveSize))
    {
        result = TRUE;
        }
        UnmapViewOfFile (pvBase);
    }

    return result;
}
コード例 #2
0
static Uint8 *
DSOUND_GetDeviceBuf(_THIS)
{
    DWORD cursor = 0;
    DWORD junk = 0;
    HRESULT result = DS_OK;
    DWORD rawlen = 0;

    /* Figure out which blocks to fill next */
    this->hidden->locked_buf = NULL;
    result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
                                                   &junk, &cursor);
    if (result == DSERR_BUFFERLOST) {
        IDirectSoundBuffer_Restore(this->hidden->mixbuf);
        result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
                                                       &junk, &cursor);
    }
    if (result != DS_OK) {
        SetDSerror("DirectSound GetCurrentPosition", result);
        return (NULL);
    }
    cursor /= this->hidden->mixlen;
#ifdef DEBUG_SOUND
    /* Detect audio dropouts */
    {
        DWORD spot = cursor;
        if (spot < this->hidden->lastchunk) {
            spot += this->hidden->num_buffers;
        }
        if (spot > this->hidden->lastchunk + 1) {
            fprintf(stderr, "Audio dropout, missed %d fragments\n",
                    (spot - (this->hidden->lastchunk + 1)));
        }
    }
#endif
    this->hidden->lastchunk = cursor;
    cursor = (cursor + 1) % this->hidden->num_buffers;
    cursor *= this->hidden->mixlen;

    /* Lock the audio buffer */
    result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
                                     this->hidden->mixlen,
                                     (LPVOID *) & this->hidden->locked_buf,
                                     &rawlen, NULL, &junk, 0);
    if (result == DSERR_BUFFERLOST) {
        IDirectSoundBuffer_Restore(this->hidden->mixbuf);
        result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
                                         this->hidden->mixlen,
                                         (LPVOID *) & this->
                                         hidden->locked_buf, &rawlen, NULL,
                                         &junk, 0);
    }
    if (result != DS_OK) {
        SetDSerror("DirectSound Lock", result);
        return (NULL);
    }
    return (this->hidden->locked_buf);
}
コード例 #3
0
static void
DSOUND_WaitDevice(_THIS)
{
    DWORD status = 0;
    DWORD cursor = 0;
    DWORD junk = 0;
    HRESULT result = DS_OK;

    /* Semi-busy wait, since we have no way of getting play notification
       on a primary mixing buffer located in hardware (DirectX 5.0)
     */
    result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
                                                   &junk, &cursor);
    if (result != DS_OK) {
        if (result == DSERR_BUFFERLOST) {
            IDirectSoundBuffer_Restore(this->hidden->mixbuf);
        }
#ifdef DEBUG_SOUND
        SetDSerror("DirectSound GetCurrentPosition", result);
#endif
        return;
    }

    while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) {
        /* FIXME: find out how much time is left and sleep that long */
        SDL_Delay(1);

        /* Try to restore a lost sound buffer */
        IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
        if ((status & DSBSTATUS_BUFFERLOST)) {
            IDirectSoundBuffer_Restore(this->hidden->mixbuf);
            IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
            if ((status & DSBSTATUS_BUFFERLOST)) {
                break;
            }
        }
        if (!(status & DSBSTATUS_PLAYING)) {
            result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0,
                                             DSBPLAY_LOOPING);
            if (result == DS_OK) {
                continue;
            }
#ifdef DEBUG_SOUND
            SetDSerror("DirectSound Play", result);
#endif
            return;
        }

        /* Find out where we are playing */
        result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
                                                       &junk, &cursor);
        if (result != DS_OK) {
            SetDSerror("DirectSound GetCurrentPosition", result);
            return;
        }
    }
}
コード例 #4
0
ファイル: SDL_dx5audio.c プロジェクト: bohwaz/ozex
static void DX5_WaitAudio_BusyWait(_THIS)
{
	DWORD status;
	DWORD cursor, junk;
	HRESULT result;

	/* Semi-busy wait, since we have no way of getting play notification
	   on a primary mixing buffer located in hardware (DirectX 5.0)
	*/
	result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &junk);
	if ( result != DS_OK ) {
		if ( result == DSERR_BUFFERLOST ) {
			IDirectSoundBuffer_Restore(mixbuf);
		}
#ifdef DEBUG_SOUND
		SetDSerror("DirectSound GetCurrentPosition", result);
#endif
		return;
	}
	cursor /= mixlen;

	while ( cursor == playing ) {
		/* FIXME: find out how much time is left and sleep that long */
		SDL_Delay(10);

		/* Try to restore a lost sound buffer */
		IDirectSoundBuffer_GetStatus(mixbuf, &status);
		if ( (status&DSBSTATUS_BUFFERLOST) ) {
			IDirectSoundBuffer_Restore(mixbuf);
			IDirectSoundBuffer_GetStatus(mixbuf, &status);
			if ( (status&DSBSTATUS_BUFFERLOST) ) {
				break;
			}
		}
		if ( ! (status&DSBSTATUS_PLAYING) ) {
			result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING);
			if ( result == DS_OK ) {
				continue;
			}
#ifdef DEBUG_SOUND
			SetDSerror("DirectSound Play", result);
#endif
			return;
		}

		/* Find out where we are playing */
		result = IDirectSoundBuffer_GetCurrentPosition(mixbuf,
								&cursor, &junk);
		if ( result != DS_OK ) {
			SetDSerror("DirectSound GetCurrentPosition", result);
			return;
		}
		cursor /= mixlen;
	}
}
コード例 #5
0
ファイル: SDL_dx5audio.c プロジェクト: 3bu1/crossbridge
static Uint8 *DX5_GetAudioBuf(_THIS)
{
	DWORD   cursor, junk;
	HRESULT result;
	DWORD   rawlen;

	/* Figure out which blocks to fill next */
	locked_buf = NULL;
	result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor);
	if ( result == DSERR_BUFFERLOST ) {
		IDirectSoundBuffer_Restore(mixbuf);
		result = IDirectSoundBuffer_GetCurrentPosition(mixbuf,
								&junk, &cursor);
	}
	if ( result != DS_OK ) {
		SetDSerror("DirectSound GetCurrentPosition", result);
		return(NULL);
	}
	cursor /= mixlen;
#ifdef DEBUG_SOUND
	/* Detect audio dropouts */
	{ DWORD spot = cursor;
	  if ( spot < lastchunk ) {
	    spot += NUM_BUFFERS;
	  }
	  if ( spot > lastchunk+1 ) {
	    fprintf(stderr, "Audio dropout, missed %d fragments\n",
	            (spot - (lastchunk+1)));
	  }
	}
#endif
	lastchunk = cursor;
	cursor = (cursor+1)%NUM_BUFFERS;
	cursor *= mixlen;

	/* Lock the audio buffer */
	result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
				(LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0);
	if ( result == DSERR_BUFFERLOST ) {
		IDirectSoundBuffer_Restore(mixbuf);
		result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
				(LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0);
	}
	if ( result != DS_OK ) {
		SetDSerror("DirectSound Lock", result);
		return(NULL);
	}
	return(locked_buf);
}
コード例 #6
0
ファイル: directsound.c プロジェクト: videolan/vlc
static HRESULT Play( vlc_object_t *obj, aout_stream_sys_t *sys,
                     block_t *p_buffer )
{
    HRESULT dsresult;
    dsresult = FillBuffer( obj, sys, p_buffer );
    if( dsresult != DS_OK )
        return dsresult;

    /* start playing the buffer */
    dsresult = IDirectSoundBuffer_Play( sys->p_dsbuffer, 0, 0,
                                        DSBPLAY_LOOPING );
    if( dsresult == DSERR_BUFFERLOST )
    {
        IDirectSoundBuffer_Restore( sys->p_dsbuffer );
        dsresult = IDirectSoundBuffer_Play( sys->p_dsbuffer,
                                            0, 0, DSBPLAY_LOOPING );
    }
    if( dsresult != DS_OK )
        msg_Err( obj, "cannot start playing buffer: (hr=0x%0lx)", dsresult );
    else
    {
        vlc_mutex_lock( &sys->lock );
        sys->b_playing = true;
        vlc_cond_signal(&sys->cond);
        vlc_mutex_unlock( &sys->lock );

    }
    return dsresult;
}
コード例 #7
0
ファイル: dsound.c プロジェクト: ktabata/suika2
/*
 * バッファをリストアする
 */
static BOOL RestoreBuffers(int nBuffer)
{
	DWORD dwStatus;
	HRESULT hRet;

	assert(pDSBuffer[nBuffer] != NULL);
	assert(nBuffer >= 0 && nBuffer < MIXER_STREAMS);

	hRet = IDirectSoundBuffer_GetStatus(pDSBuffer[nBuffer], &dwStatus);
	if(hRet != DS_OK)
		return FALSE;
	if(dwStatus & DSBSTATUS_BUFFERLOST)
    {
		/*
		 * アプリケーションがアクティブになったばかりなので
		 * DirectSoundのコントロールを取得できない可能性がある。
		 * よって、コントロールを取得できるまでスリープする。
		 */
		while(1) {
			Sleep(10);
            hRet = IDirectSoundBuffer_Restore(pDSBuffer[nBuffer]);
            if(hRet != DSERR_BUFFERLOST)
				break;
		}
    }
    return TRUE;
}
コード例 #8
0
ファイル: SDL_dx5audio.c プロジェクト: bohwaz/ozex
static void DX6_WaitAudio_EventWait(_THIS)
{
	DWORD status;
	HRESULT result;

	/* Try to restore a lost sound buffer */
	IDirectSoundBuffer_GetStatus(mixbuf, &status);
	if ( (status&DSBSTATUS_BUFFERLOST) ) {
		IDirectSoundBuffer_Restore(mixbuf);
		IDirectSoundBuffer_GetStatus(mixbuf, &status);
		if ( (status&DSBSTATUS_BUFFERLOST) ) {
			return;
		}
	}
	if ( ! (status&DSBSTATUS_PLAYING) ) {
		result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING);
		if ( result != DS_OK ) {
#ifdef DEBUG_SOUND
			SetDSerror("DirectSound Play", result);
#endif
			return;
		}
	}
	WaitForSingleObject(audio_event, INFINITE);
}
コード例 #9
0
ファイル: sounddx.c プロジェクト: twinaphex/vice-next
static void dx_clear(void)
{
LPVOID  lpvPtr1;
DWORD   dwBytes1;
LPVOID  lpvPtr2;
DWORD   dwBytes2;
HRESULT result;

    result = IDirectSoundBuffer_Lock(buffer, 0, buffer_size,
                                     &lpvPtr1, &dwBytes1, &lpvPtr2,
                                     &dwBytes2, 0);
    if (result == DSERR_BUFFERLOST) {
        IDirectSoundBuffer_Restore(buffer);
    } else {
        if (is16bit) {
            memset(lpvPtr1, 0, dwBytes1);
            if (lpvPtr2) memset(lpvPtr2, 0, dwBytes2);
        } else {
            memset(lpvPtr1, 0x80, dwBytes1);
            if (lpvPtr2) memset(lpvPtr2, 0x80, dwBytes2);
        }
        result = IDirectSoundBuffer_Unlock(buffer, lpvPtr1, dwBytes1,
                                           lpvPtr2, dwBytes2);
    }
}
コード例 #10
0
ファイル: drv_ds.c プロジェクト: OS2World/LIB-SDL-2014
static void DS_Update(void)
{
	LPVOID block;
	DWORD bBytes;

	/* Do first update in DS_Update() to be consistent with other
	   non threaded drivers. */
	if (do_update && pSoundBuffer) {
		do_update = 0;

		if (IDirectSoundBuffer_Lock(pSoundBuffer, 0, fragsize, &block, &bBytes, NULL, NULL, 0)
											== DSERR_BUFFERLOST) {
			IDirectSoundBuffer_Restore (pSoundBuffer);
			IDirectSoundBuffer_Lock (pSoundBuffer, 0, fragsize, &block, &bBytes, NULL, NULL, 0);
		}

		if (Player_Paused_internal()) {
			VC_SilenceBytes ((SBYTE *)block, (ULONG)bBytes);
		} else {
			VC_WriteBytes ((SBYTE *)block, (ULONG)bBytes);
		}

		IDirectSoundBuffer_Unlock (pSoundBuffer, block, bBytes, NULL, 0);

		IDirectSoundBuffer_SetCurrentPosition(pSoundBuffer, 0);
		IDirectSoundBuffer_Play(pSoundBuffer, 0, 0, DSBPLAY_LOOPING);

		threadInUse=1;
		ResumeThread (updateBufferHandle);
	}
}
コード例 #11
0
ファイル: dsound.c プロジェクト: deveck/Deveck.TAM
static BOOL AppWriteDataToBuffer(LPDIRECTSOUNDBUFFER lpDsb,  // The buffer.
				 DWORD dwOffset,	      // Our own write cursor.
				 LPBYTE lpbSoundData,	      // Start of our data.
				 DWORD dwSoundBytes)	      // Size of block to copy.
{ 
    LPVOID  lpvPtr1; 
    DWORD dwBytes1; 
    LPVOID  lpvPtr2; 
    DWORD dwBytes2; 
    HRESULT hr; 
    
    // Obtain memory address of write block. This will be in two parts
    // if the block wraps around.
    
    hr = IDirectSoundBuffer_Lock( lpDsb, dwOffset, dwSoundBytes, &lpvPtr1, 
				  &dwBytes1, &lpvPtr2, &dwBytes2, 0); 
    
    // If the buffer was lost, restore and retry lock. 
    if (DSERR_BUFFERLOST == hr) { 
	IDirectSoundBuffer_Restore(lpDsb); 
	hr = IDirectSoundBuffer_Lock( lpDsb, dwOffset, dwSoundBytes, 
				      &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0); 
    } 
    if SUCCEEDED(hr) { 
	pj_memcpy(lpvPtr1, lpbSoundData, dwBytes1); 
	if (NULL != lpvPtr2) 
	    pj_memcpy(lpvPtr2, lpbSoundData+dwBytes1, dwBytes2); 
	
	hr = IDirectSoundBuffer_Unlock(lpDsb, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2); 
	if SUCCEEDED(hr)
	    return TRUE; 
    } 
    
    return FALSE; 
}
コード例 #12
0
ファイル: i_ds_eax.c プロジェクト: cmbruns/Doomsday-Engine
int I2_IsSourcePlaying(sndsource_t *buf)
{
    DWORD status;
    IDirectSoundBuffer_GetStatus(buf->source, &status);
    // Restore the buffer if it's lost, but that shouldn't really matter since
    // it'll be released when it stops playing.
    if(status & DSBSTATUS_BUFFERLOST) IDirectSoundBuffer_Restore(buf->source);
    return (status & DSBSTATUS_PLAYING) != 0;
}
コード例 #13
0
ファイル: dsound51.cpp プロジェクト: madnessw/thesnow
void DSSoundFeedVoiceData(unsigned char* pSound,long lBytes)
{
	LPVOID lpvPtr1, lpvPtr2;
	unsigned long dwBytes1,dwBytes2;
	unsigned long *lpSS, *lpSD;
	unsigned long dw,cplay,cwrite;
	HRESULT hr;
	unsigned long status;

	IDirectSoundBuffer_GetStatus(lpDSBSECONDARY1,&status);
	if (status & DSBSTATUS_BUFFERLOST)
	{
		if (IDirectSoundBuffer_Restore(lpDSBSECONDARY1) != DS_OK) return;
		IDirectSoundBuffer_Play(lpDSBSECONDARY1,0,0,DSBPLAY_LOOPING);
	}

	IDirectSoundBuffer_GetCurrentPosition(lpDSBSECONDARY1,&cplay,&cwrite);

	if(LastWrite == 0xffffffff) LastWrite=cwrite;

	hr = IDirectSoundBuffer_Lock(lpDSBSECONDARY1,LastWrite,lBytes,
        &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);

	if (hr != DS_OK)
	{
		LastWrite=0xffffffff;
		return;
	}

	lpSS = (unsigned long *)pSound;
	lpSD = (unsigned long *)lpvPtr1;
	dw = dwBytes1 >> 2;

	while(dw)
	{
		*lpSD++=*lpSS++;
		dw--;
	}

	if (lpvPtr2)
	{
		lpSD = (unsigned long *)lpvPtr2;
		dw = dwBytes2 >> 2;

		while(dw)
		{
			*lpSD++ = *lpSS++;
			dw--;
		}
	}

	IDirectSoundBuffer_Unlock(lpDSBSECONDARY1,lpvPtr1,dwBytes1,lpvPtr2,dwBytes2);
	LastWrite += lBytes;
	if(LastWrite >= SOUNDSIZE) LastWrite -= SOUNDSIZE;
	LastPlay = cplay;
}
コード例 #14
0
ファイル: ao_dsound.c プロジェクト: CrimsonVoid/mpv
/**
\brief fill sound buffer
\param data pointer to the sound data to copy
\param len length of the data to copy in bytes
\return number of copyed bytes
*/
static int write_buffer(struct ao *ao, unsigned char *data, int len)
{
    struct priv *p = ao->priv;
    HRESULT res;
    LPVOID lpvPtr1;
    DWORD dwBytes1;
    LPVOID lpvPtr2;
    DWORD dwBytes2;

    p->underrun_check = 0;

    // Lock the buffer
    res = IDirectSoundBuffer_Lock(p->hdsbuf, p->write_offset, len, &lpvPtr1,
                                  &dwBytes1, &lpvPtr2, &dwBytes2, 0);
    // If the buffer was lost, restore and retry lock.
    if (DSERR_BUFFERLOST == res) {
        IDirectSoundBuffer_Restore(p->hdsbuf);
        res = IDirectSoundBuffer_Lock(p->hdsbuf, p->write_offset, len, &lpvPtr1,
                                      &dwBytes1, &lpvPtr2, &dwBytes2, 0);
    }


    if (SUCCEEDED(res)) {
        if (!AF_FORMAT_IS_AC3(ao->format)) {
            memcpy(lpvPtr1, data, dwBytes1);
            if (lpvPtr2 != NULL)
                memcpy(lpvPtr2, (char *)data + dwBytes1, dwBytes2);

            p->write_offset += dwBytes1 + dwBytes2;
            if (p->write_offset >= p->buffer_size)
                p->write_offset = dwBytes2;
        } else {
            // Write to pointers without reordering.
            memcpy(lpvPtr1, data, dwBytes1);
            if (NULL != lpvPtr2)
                memcpy(lpvPtr2, data + dwBytes1, dwBytes2);
            p->write_offset += dwBytes1 + dwBytes2;
            if (p->write_offset >= p->buffer_size)
                p->write_offset = dwBytes2;
        }

        // Release the data back to DirectSound.
        res = IDirectSoundBuffer_Unlock(p->hdsbuf, lpvPtr1, dwBytes1, lpvPtr2,
                                        dwBytes2);
        if (SUCCEEDED(res)) {
            // Success.
            DWORD status;
            IDirectSoundBuffer_GetStatus(p->hdsbuf, &status);
            if (!(status & DSBSTATUS_PLAYING))
                res = IDirectSoundBuffer_Play(p->hdsbuf, 0, 0, DSBPLAY_LOOPING);
            return dwBytes1 + dwBytes2;
        }
    }
    // Lock, Unlock, or Restore failed.
    return 0;
}
コード例 #15
0
ファイル: dsoundaudio.c プロジェクト: 01org/qemu-lite
static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb, dsound *s)
{
    HRESULT hr;

    hr = IDirectSoundBuffer_Restore (dsb);

    if (hr != DS_OK) {
        dsound_logerr (hr, "Could not restore playback buffer\n");
        return -1;
    }
    return 0;
}
コード例 #16
0
ファイル: snd_win.c プロジェクト: kasymovga/DarkPlacesRM
/*
====================
SndSys_LockRenderBuffer

Get the exclusive lock on "snd_renderbuffer"
====================
*/
qboolean SndSys_LockRenderBuffer (void)
{
#ifdef SUPPORTDIRECTX
	int reps;
	HRESULT hresult;
	DWORD	dwStatus;

	if (pDSBuf)
	{
		// if the buffer was lost or stopped, restore it and/or restart it
		if (IDirectSoundBuffer_GetStatus (pDSBuf, &dwStatus) != DS_OK)
			Con_Print("Couldn't get sound buffer status\n");

		if (dwStatus & DSBSTATUS_BUFFERLOST)
		{
			Con_Print("DSound buffer is lost!!\n");
			IDirectSoundBuffer_Restore (pDSBuf);
		}

		if (!(dwStatus & DSBSTATUS_PLAYING))
			IDirectSoundBuffer_Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);

		reps = 0;

		while ((hresult = IDirectSoundBuffer_Lock(pDSBuf, 0, gSndBufSize, (LPVOID*)&dsound_pbuf, &dsound_dwSize, (LPVOID*)&dsound_pbuf2, &dsound_dwSize2, 0)) != DS_OK)
		{
			if (hresult != DSERR_BUFFERLOST)
			{
				Con_Print("S_LockBuffer: DS: Lock Sound Buffer Failed\n");
				S_Shutdown ();
				S_Startup ();
				return false;
			}

			if (++reps > 10000)
			{
				Con_Print("S_LockBuffer: DS: couldn't restore buffer\n");
				S_Shutdown ();
				S_Startup ();
				return false;
			}
		}

		if ((void*)dsound_pbuf != snd_renderbuffer->ring)
			Sys_Error("SndSys_LockRenderBuffer: the ring address has changed!!!\n");
		return true;
	}
#endif

	return wav_init;
}
コード例 #17
0
ファイル: dsutil.c プロジェクト: bowlofstew/ja2
IDirectSoundBuffer *SndObjGetFreeBuffer(SNDOBJ *pSO)
{
    IDirectSoundBuffer *pDSB;

    if (pSO == NULL)
        return NULL;

    if (pDSB = pSO->Buffers[pSO->iCurrent])
    {
        HRESULT hres;
        DWORD dwStatus;

        hres = IDirectSoundBuffer_GetStatus(pDSB, &dwStatus);

        if (FAILED(hres))
            dwStatus = 0;

        if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
        {
            if (pSO->iAlloc > 1)
            {
                if (++pSO->iCurrent >= pSO->iAlloc)
                    pSO->iCurrent = 0;

                pDSB = pSO->Buffers[pSO->iCurrent];
                hres = IDirectSoundBuffer_GetStatus(pDSB, &dwStatus);

                if (SUCCEEDED(hres) && (dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
                {
                    IDirectSoundBuffer_Stop(pDSB);
                    IDirectSoundBuffer_SetCurrentPosition(pDSB, 0);
                }
            }
            else
            {
                pDSB = NULL;
            }
        }

        if (pDSB && (dwStatus & DSBSTATUS_BUFFERLOST))
        {
            if (FAILED(IDirectSoundBuffer_Restore(pDSB)) ||
                !DSFillSoundBuffer(pDSB, pSO->pbWaveData, pSO->cbWaveSize))
            {
                pDSB = NULL;
            }
        }
    }

    return pDSB;
}
コード例 #18
0
ファイル: SDL_dx5audio.c プロジェクト: bohwaz/ozex
static Uint8 *DX5_GetAudioBuf(_THIS)
{
	DWORD   cursor, junk;
	HRESULT result;
	DWORD   rawlen;

	/* Figure out which blocks to fill next */
	locked_buf = NULL;
	result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &junk);
	if ( result == DSERR_BUFFERLOST ) {
		IDirectSoundBuffer_Restore(mixbuf);
		result = IDirectSoundBuffer_GetCurrentPosition(mixbuf,
								&cursor, &junk);
	}
	if ( result != DS_OK ) {
		SetDSerror("DirectSound GetCurrentPosition", result);
		return(NULL);
	}
	cursor /= mixlen;
	playing = cursor;
	cursor = (cursor+1)%NUM_BUFFERS;
	cursor *= mixlen;

	/* Lock the audio buffer */
	result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
				(LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0);
	if ( result == DSERR_BUFFERLOST ) {
		IDirectSoundBuffer_Restore(mixbuf);
		result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
				(LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0);
	}
	if ( result != DS_OK ) {
		SetDSerror("DirectSound Lock", result);
		return(NULL);
	}
	return(locked_buf);
}
コード例 #19
0
ファイル: drv_ds.c プロジェクト: OS2World/LIB-SDL-2014
static DWORD WINAPI updateBufferProc(LPVOID lpParameter)
{
	LPVOID pBlock1 = NULL, pBlock2 = NULL;
	DWORD soundBufferCurrentPosition, blockBytes1, blockBytes2;
	DWORD start;

	while (threadInUse) {
		if (WaitForSingleObject(notifyUpdateHandle,INFINITE)==WAIT_OBJECT_0) {

			if (!threadInUse) break;

			IDirectSoundBuffer_GetCurrentPosition
						(pSoundBuffer,&soundBufferCurrentPosition,NULL);

			if (soundBufferCurrentPosition < fragsize)
				start = fragsize;
			else
				start = 0;

			if (IDirectSoundBuffer_Lock
						(pSoundBuffer,start,fragsize,&pBlock1,&blockBytes1,
						 &pBlock2,&blockBytes2,0)==DSERR_BUFFERLOST) {
				IDirectSoundBuffer_Restore(pSoundBuffer);
				IDirectSoundBuffer_Lock
						(pSoundBuffer,start,fragsize,&pBlock1,&blockBytes1,
						 &pBlock2,&blockBytes2,0);
			}

			MUTEX_LOCK(vars);
			if (Player_Paused_internal()) {
				VC_SilenceBytes((SBYTE*)pBlock1,(ULONG)blockBytes1);
				if (pBlock2)
					VC_SilenceBytes((SBYTE*)pBlock2,(ULONG)blockBytes2);
			} else {
				VC_WriteBytes((SBYTE*)pBlock1,(ULONG)blockBytes1);
				if (pBlock2)
					VC_WriteBytes((SBYTE*)pBlock2,(ULONG)blockBytes2);
			}
			MUTEX_UNLOCK(vars);

			IDirectSoundBuffer_Unlock
						(pSoundBuffer,pBlock1,blockBytes1,pBlock2,blockBytes2);
		}
	}
	return 0;
}
コード例 #20
0
ファイル: sound.c プロジェクト: ficoos/fceu-next
void CheckDStatus(void)
{
  DWORD status;
  status=0;
  IDirectSoundBuffer_GetStatus(ppbufw, &status);

  if(status&DSBSTATUS_BUFFERLOST)
  {
   IDirectSoundBuffer_Restore(ppbufw);
  }

  if(!(status&DSBSTATUS_PLAYING))
  {
   ToWritePos=0;
   IDirectSoundBuffer_SetFormat(ppbufw,&wf);
   IDirectSoundBuffer_Play(ppbufw,0,0,DSBPLAY_LOOPING);
  }
}
コード例 #21
0
ファイル: snd_win.c プロジェクト: luaman/qforge-newtree
void DSOUND_Restore(void)
{
// if the buffer was lost or stopped, restore it and/or restart it
        DWORD       dwStatus;

        if (!pDSBuf) return;

	if (IDirectSoundBuffer_GetStatus (pDSBuf, &dwStatus) != DD_OK)
        	Con_Printf ("Couldn't get sound buffer status\n");

	if (dwStatus & DSBSTATUS_BUFFERLOST)
		IDirectSoundBuffer_Restore (pDSBuf);

	if (!(dwStatus & DSBSTATUS_PLAYING))
		IDirectSoundBuffer_Play (pDSBuf, 0, 0, DSBPLAY_LOOPING);

        return;
}
コード例 #22
0
static void FillBuffer(int32_t bufnum)
{
    HRESULT err;
    LPVOID ptr, ptr2;
    DWORD remaining, remaining2;
    int32_t retries = 1;
    
    //initprintf( "DirectSound FillBuffer: filling %d\n", bufnum);

    do {
        err = IDirectSoundBuffer_Lock(lpdsbsec,
                  notifyPositions[bufnum].dwOffset,
                  notifyPositions[1].dwOffset,
                  &ptr, &remaining,
                  &ptr2, &remaining2,
                  0);
        if (FAILED(err)) {
            if (err == DSERR_BUFFERLOST) {
                err = IDirectSoundBuffer_Restore(lpdsbsec);
                if (FAILED(err)) {
                    return;
                }

                if (retries-- > 0) {
                    continue;
                }
            }
            if (MV_Printf)
                MV_Printf("DirectSound FillBuffer: err %x\n", (uint32_t) err);
            return;
        }
        break;
    } while (1);
    
    if (ptr) {
        FillBufferPortion((char *) ptr, remaining);
    }
    if (ptr2) {
        FillBufferPortion((char *) ptr2, remaining2);
    }
    
    IDirectSoundBuffer_Unlock(lpdsbsec, ptr, remaining, ptr2, remaining2);
}
コード例 #23
0
ファイル: dsound.c プロジェクト: jonakino/RetroArch
static inline bool grab_region(dsound_t *ds, DWORD write_ptr, struct audio_lock *region)
{
   HRESULT res = IDirectSoundBuffer_Lock(ds->dsb, write_ptr, CHUNK_SIZE, &region->chunk1, &region->size1, &region->chunk2, &region->size2, 0);
   if (res == DSERR_BUFFERLOST)
   {
      res = IDirectSoundBuffer_Restore(ds->dsb);
      if (res != DS_OK)
         return false;

      res = IDirectSoundBuffer_Lock(ds->dsb, write_ptr, CHUNK_SIZE, &region->chunk1, &region->size1, &region->chunk2, &region->size2, 0);
      if (res != DS_OK)
         return false;
   }

   const char *err;
   switch (res)
   {
      case DSERR_BUFFERLOST:
         err = "DSERR_BUFFERLOST";
         break;
      case DSERR_INVALIDCALL:
         err = "DSERR_INVALIDCALL";
         break;
      case DSERR_INVALIDPARAM:
         err = "DSERR_INVALIDPARAM";
         break;
      case DSERR_PRIOLEVELNEEDED:
         err = "DSERR_PRIOLEVELNEEDED";
         break;

      default:
         err = NULL;
   }

   if (err)
   {
      RARCH_WARN("[DirectSound error]: %s\n", err);
      return false;
   }

   return true;
}
コード例 #24
0
ファイル: Dsutil.c プロジェクト: ForsakenW/forsaken
BOOL DSReloadSoundBuffer(IDirectSoundBuffer *pDSB, char *lpName)
{
    BOOL result=FALSE;
    BYTE *pbWaveData;
    DWORD cbWaveSize;
    void * Buffer = NULL;

    if (Buffer = DSGetWave( lpName, NULL, &pbWaveData, &cbWaveSize))
    {
        if (SUCCEEDED(IDirectSoundBuffer_Restore(pDSB)) &&
            DSFillSoundBuffer(pDSB, pbWaveData, cbWaveSize))
        {
            result = TRUE;
        }
    }
    if( Buffer != NULL )
        free( Buffer );

    return result;
}
コード例 #25
0
ファイル: dsoundaudio.c プロジェクト: CPFL/gxen
static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb)
{
    HRESULT hr;
    int i;

    for (i = 0; i < conf.restore_retries; ++i) {
        hr = IDirectSoundBuffer_Restore (dsb);

        switch (hr) {
        case DS_OK:
            return 0;

        case DSERR_BUFFERLOST:
            continue;

        default:
            dsound_logerr (hr, "Could not restore playback buffer\n");
            return -1;
        }
    }

    dolog ("%d attempts to restore playback buffer failed\n", i);
    return -1;
}
コード例 #26
0
ファイル: sounddx.c プロジェクト: twinaphex/vice-next
static int dx_write(SWORD *pbuf, size_t nr)
{
    LPVOID lpvPtr1;
    DWORD dwBytes1;
    LPVOID lpvPtr2;
    DWORD dwBytes2;
    HRESULT result;
    DWORD buffer_lock_size; /* buffer_lock_end; */
    unsigned int i, count;

    count = (unsigned int)nr / fragment_size;
    buffer_lock_size = fragment_size * (is16bit ? 2 : 1);

    /* Write one fragment at a time.  FIXME: This could be faster.  */
    for (i = 0; i < count; i++) {
        /* lock buffer for writing */
        do {
            result = IDirectSoundBuffer_Lock(buffer, buffer_offset,
                                             buffer_lock_size,
                                             &lpvPtr1, &dwBytes1, &lpvPtr2,
                                             &dwBytes2, 0);

            if (result == DSERR_BUFFERLOST) {
                IDirectSoundBuffer_Restore(buffer);
                dwBytes1 = dwBytes2 = 0;
            }
        } while (dwBytes1 + dwBytes2 != buffer_lock_size);

        /* put data as-is, or convert to 8 bits first */
        if (is16bit) {
            memcpy(lpvPtr1,pbuf,dwBytes1);
            if (lpvPtr2)
                memcpy(lpvPtr2,(BYTE *)pbuf + dwBytes1, dwBytes2);
            pbuf += fragment_size;
        } else {
            for (i = 0; i < dwBytes1; i++) {
                ((BYTE *)lpvPtr1)[i]=(*(pbuf++) >> 8) + 0x80;
            }
            if (lpvPtr2 != NULL) {
                for (i = 0; i < dwBytes2; i++) {
                    ((BYTE *)lpvPtr2)[i]=(*(pbuf++) >> 8) + 0x80;
                }
            }
        }

        /* done. */
        result = IDirectSoundBuffer_Unlock(buffer, lpvPtr1, dwBytes1,
                                           lpvPtr2, dwBytes2);
        buffer_offset += buffer_lock_size;

        /* loop */
        if (buffer_offset == buffer_size)
            buffer_offset = 0;
    }

    pbuf -= num_of_channels;

    for (i = 0; i < (unsigned int)num_of_channels; i++) {
        last_buffered_sample[i] = *pbuf++;
    }

    return 0;
}
コード例 #27
0
ファイル: sounddx.c プロジェクト: twinaphex/vice-next
static int dx_init(const char *param, int *speed, int *fragsize, int *fragnr,
                   int *channels)
{
HRESULT result;

    DEBUG(("DirectSound driver initialization: speed = %d, fragsize = %d, fragnr = %d, channels = %d\n",
           *speed, *fragsize, *fragnr, *channels));

    if (ds == NULL) {
        result = DirectSoundCreate(NULL, &ds, NULL);
        if (result != DS_OK) {
            ui_error("Cannot initialize DirectSound:\n%s", ds_error(result));
            return -1;
        }

        result = IDirectSound_SetCooperativeLevel(ds, ui_get_main_hwnd(),
                                                  DSSCL_EXCLUSIVE);
        if (result != DS_OK) {
            ui_error("Cannot set cooperative level:\n%s",
                     ds_error(result));
            return -1;
        }
    }

    memset(&capabilities, 0, sizeof(DSCAPS));
    capabilities.dwSize = sizeof(DSCAPS);

    IDirectSound_GetCaps(ds, &capabilities);
    if ((capabilities.dwFlags & DSCAPS_PRIMARY16BIT)
        || (capabilities.dwFlags & DSCAPS_SECONDARY16BIT)) {
        is16bit = 1;
    } else {
        is16bit = 0;
    }
    if (!((capabilities.dwFlags & DSCAPS_PRIMARYSTEREO)
        || (capabilities.dwFlags & DSCAPS_SECONDARYSTEREO))) {
        *channels = 1;
    }
    num_of_channels = *channels;

    DEBUG(("16bit flag: %d",is16bit));
    DEBUG(("Channels: %d",*channels));
    DEBUG(("Capabilities %08x",capabilities.dwFlags));
    DEBUG(("Secondary min Hz: %d",capabilities.dwMinSecondarySampleRate));
    DEBUG(("Secondary max Hz: %d",capabilities.dwMaxSecondarySampleRate));

    memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
    pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
    pcmwf.wf.nChannels = *channels;
    pcmwf.wf.nSamplesPerSec = *speed;
    pcmwf.wBitsPerSample = is16bit ? 16 : 8;
/* Hack to fix if mmsystem header is bad
    ((WORD*)&pcmwf)[7] = 16;
*/
    pcmwf.wf.nBlockAlign = (is16bit ? 2 : 1) * *channels;
    pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;

    memset(&desc, 0, sizeof(DSBUFFERDESC));
    desc.dwSize = sizeof(DSBUFFERDESC);
    desc.dwFlags = DSBCAPS_PRIMARYBUFFER;

    fragment_size = *fragsize; /* frames */
    buffer_size = *fragsize * *fragnr * (is16bit ? 2 : 1) * *channels; /* bytes */
    stream_buffer_size = fragment_size * *fragnr * *channels; /* nr of samples */
    buffer_offset = 0; /* bytes */
    
    result = IDirectSound_CreateSoundBuffer(ds, &desc, &pbuffer, NULL);

    if (result != DS_OK) {
        ui_error("Cannot create Primary DirectSound bufer: %s",
                 ds_error(result));
        return -1;
    }

    memset(&desc, 0, sizeof(DSBUFFERDESC));
    desc.dwSize = sizeof(DSBUFFERDESC);
    desc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2
                   | DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN
                   | DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS ;

    desc.dwBufferBytes = buffer_size;
    desc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;

    result = IDirectSound_CreateSoundBuffer(ds, &desc, &buffer, NULL);
    if (result != DS_OK) {
        ui_error("Cannot create DirectSound buffer:\n%s", ds_error(result));
        return -1;
    }

    memset(&wfex, 0, sizeof(WAVEFORMATEX));
    wfex.wFormatTag = WAVE_FORMAT_PCM;
    wfex.nChannels = *channels;
    wfex.nSamplesPerSec = *speed;
    wfex.wBitsPerSample = is16bit ? 16 : 8;
    wfex.nBlockAlign = (is16bit ? 2 : 1) * *channels;
    wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;

    result=IDirectSoundBuffer_SetFormat(pbuffer, &wfex);
    if (result != DS_OK) {
        ui_error("Cannot set Output format for primary sound buffer:\n%s",
                 ds_error(result));
        return -1;
    }

    dx_clear();
    /* Let's go...  */
    result = IDirectSoundBuffer_Play(buffer, 0, 0, DSBPLAY_LOOPING);
    if (result == DSERR_BUFFERLOST) {
        ui_error("Restoring DirectSound buffer.");
        if ((result = IDirectSoundBuffer_Restore(buffer)) != DS_OK)
            ui_error("Cannot restore buffer:\n%s", ds_error(result));
        result = IDirectSoundBuffer_Play(buffer, 0, 0, DSBPLAY_LOOPING);
    }
    if (result != DS_OK) {
        ui_error("Cannot play DirectSound buffer:\n%s", ds_error(result));
        return -1;
    }

    DEBUG(("DirectSound initialization done succesfully.\n"));

    return 0;
}
コード例 #28
0
static ALuint DSoundPlaybackProc(ALvoid *ptr)
{
    ALCdevice *Device = (ALCdevice*)ptr;
    DSoundPlaybackData *data = (DSoundPlaybackData*)Device->ExtraData;
    DSBCAPS DSBCaps;
    DWORD LastCursor = 0;
    DWORD PlayCursor;
    VOID *WritePtr1, *WritePtr2;
    DWORD WriteCnt1,  WriteCnt2;
    BOOL Playing = FALSE;
    DWORD FrameSize;
    DWORD FragSize;
    DWORD avail;
    HRESULT err;

    SetRTPriority();

    memset(&DSBCaps, 0, sizeof(DSBCaps));
    DSBCaps.dwSize = sizeof(DSBCaps);
    err = IDirectSoundBuffer_GetCaps(data->Buffer, &DSBCaps);
    if(FAILED(err))
    {
        ERR("Failed to get buffer caps: 0x%lx\n", err);
        ALCdevice_Lock(Device);
        aluHandleDisconnect(Device);
        ALCdevice_Unlock(Device);
        return 1;
    }

    FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
    FragSize = Device->UpdateSize * FrameSize;

    IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &LastCursor, NULL);
    while(!data->killNow)
    {
        // Get current play cursor
        IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &PlayCursor, NULL);
        avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;

        if(avail < FragSize)
        {
            if(!Playing)
            {
                err = IDirectSoundBuffer_Play(data->Buffer, 0, 0, DSBPLAY_LOOPING);
                if(FAILED(err))
                {
                    ERR("Failed to play buffer: 0x%lx\n", err);
                    ALCdevice_Lock(Device);
                    aluHandleDisconnect(Device);
                    ALCdevice_Unlock(Device);
                    return 1;
                }
                Playing = TRUE;
            }

            avail = WaitForSingleObjectEx(data->NotifyEvent, 2000, FALSE);
            if(avail != WAIT_OBJECT_0)
                ERR("WaitForSingleObjectEx error: 0x%lx\n", avail);
            continue;
        }
        avail -= avail%FragSize;

        // Lock output buffer
        WriteCnt1 = 0;
        WriteCnt2 = 0;
        err = IDirectSoundBuffer_Lock(data->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);

        // If the buffer is lost, restore it and lock
        if(err == DSERR_BUFFERLOST)
        {
            WARN("Buffer lost, restoring...\n");
            err = IDirectSoundBuffer_Restore(data->Buffer);
            if(SUCCEEDED(err))
            {
                Playing = FALSE;
                LastCursor = 0;
                err = IDirectSoundBuffer_Lock(data->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
            }
        }

        // Successfully locked the output buffer
        if(SUCCEEDED(err))
        {
            // If we have an active context, mix data directly into output buffer otherwise fill with silence
            aluMixData(Device, WritePtr1, WriteCnt1/FrameSize);
            aluMixData(Device, WritePtr2, WriteCnt2/FrameSize);

            // Unlock output buffer only when successfully locked
            IDirectSoundBuffer_Unlock(data->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
        }
        else
        {
            ERR("Buffer lock error: %#lx\n", err);
            ALCdevice_Lock(Device);
            aluHandleDisconnect(Device);
            ALCdevice_Unlock(Device);
            return 1;
        }

        // Update old write cursor location
        LastCursor += WriteCnt1+WriteCnt2;
        LastCursor %= DSBCaps.dwBufferBytes;
    }

    return 0;
}
コード例 #29
0
ファイル: ghetto.c プロジェクト: bsutherland/trisynth
static DWORD WINAPI bufferLoop(void *param)
{
  HANDLE handles[2] = { g_dsound.tickev, g_dsound.exitev };

  while (WaitForMultipleObjects(2, handles, FALSE, BUFFERLEN/3000) != WAIT_OBJECT_0 + 1) // while not exit
  {
    EnterCriticalSection(&g_dsound.crsec);

    void *buf1, *buf2;
    DWORD len1, len2;

    // fetch current buffer pos
    DWORD curpos;
    int nwrite = 0;
    for (;;)
    {
      HRESULT hr = IDirectSoundBuffer_GetCurrentPosition(g_dsound.sbuf, &curpos, NULL);
      if (hr == S_OK)
      {
        // find out how many bytes to write
        curpos &= ~31u;
        if (curpos == g_dsound.lastpos)
          goto done; // still the same

        nwrite = curpos - g_dsound.lastpos;
        if (nwrite < 0) {
          nwrite += BUFFERLEN;
          printf("positivizing nwrite\n");
        }
        printf("nwrite = %i\n", nwrite);

        hr = IDirectSoundBuffer_Lock(g_dsound.sbuf, g_dsound.lastpos, nwrite, &buf1, &len1, &buf2, &len2, 0);
      }

      if (hr == S_OK)
        break;
      else if (hr == DSERR_BUFFERLOST) {
        printf("buffer lost!\n");
        IDirectSoundBuffer_Restore(g_dsound.sbuf);
      } else {
        printf("something else went wrong\n");
        goto done;
      }
    }

    // we got the lock
    printf("got lock\n");
    g_dsound.lastpos = curpos;
    g_dsound.bufcnt += nwrite;

    // render to mix buffer
    g_dsound.callback(g_dsound.mixbuffer, nwrite / 2);

    // float->int, clamp
    //if (buf1)
    //  clamp(buf1, g_dsound.mixbuffer, len1/2);
    //if (buf2)
    //  clamp(buf2, g_dsound.mixbuffer + len1/2, len2/2);

    if (buf1) {
      printf("buf1: %d\n", len1);
      memcpy(buf1, g_dsound.mixbuffer, len1);
    }
    if (buf2) {
      printf("buf2: %d\n", len2);
      memcpy(buf2, g_dsound.mixbuffer + len1/2, len2);
    }

    HRESULT hr = IDirectSoundBuffer_Unlock(g_dsound.sbuf, buf1, len1, buf2, len2);
    if (!hr) {
      printf("unlock result: %i\n", hr);
    }

  done:
    LeaveCriticalSection(&g_dsound.crsec);
  }

  return 0;
}
コード例 #30
0
ファイル: mcicda.c プロジェクト: MichaelMcDonnell/wine
static DWORD CALLBACK MCICDA_playLoop(void *ptr)
{
    WINE_MCICDAUDIO *wmcda = (WINE_MCICDAUDIO*)ptr;
    DWORD lastPos, curPos, endPos, br;
    void *cdData;
    DWORD lockLen, fragLen;
    DSBCAPS caps;
    RAW_READ_INFO rdInfo;
    HRESULT hr = DS_OK;

    memset(&caps, 0, sizeof(caps));
    caps.dwSize = sizeof(caps);
    hr = IDirectSoundBuffer_GetCaps(wmcda->dsBuf, &caps);

    fragLen = caps.dwBufferBytes/CDDA_FRAG_COUNT;
    curPos = lastPos = 0;
    endPos = ~0u;
    while (SUCCEEDED(hr) && endPos != lastPos &&
           WaitForSingleObject(wmcda->stopEvent, 0) != WAIT_OBJECT_0) {
        hr = IDirectSoundBuffer_GetCurrentPosition(wmcda->dsBuf, &curPos, NULL);
        if ((curPos-lastPos+caps.dwBufferBytes)%caps.dwBufferBytes < fragLen) {
            Sleep(1);
            continue;
        }

        EnterCriticalSection(&wmcda->cs);
        rdInfo.DiskOffset.QuadPart = wmcda->start<<11;
        rdInfo.SectorCount = min(fragLen/RAW_SECTOR_SIZE, wmcda->end-wmcda->start);
        rdInfo.TrackMode = CDDA;

        hr = IDirectSoundBuffer_Lock(wmcda->dsBuf, lastPos, fragLen, &cdData, &lockLen, NULL, NULL, 0);
        if (hr == DSERR_BUFFERLOST) {
            if(FAILED(IDirectSoundBuffer_Restore(wmcda->dsBuf)) ||
               FAILED(IDirectSoundBuffer_Play(wmcda->dsBuf, 0, 0, DSBPLAY_LOOPING))) {
                LeaveCriticalSection(&wmcda->cs);
                break;
            }
            hr = IDirectSoundBuffer_Lock(wmcda->dsBuf, lastPos, fragLen, &cdData, &lockLen, NULL, NULL, 0);
        }

        if (SUCCEEDED(hr)) {
            if (rdInfo.SectorCount > 0) {
                if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_RAW_READ, &rdInfo, sizeof(rdInfo), cdData, lockLen, &br, NULL))
                    WARN("CD read failed at sector %d: 0x%x\n", wmcda->start, GetLastError());
            }
            if (rdInfo.SectorCount*RAW_SECTOR_SIZE < lockLen) {
                if(endPos == ~0u) endPos = lastPos;
                memset((BYTE*)cdData + rdInfo.SectorCount*RAW_SECTOR_SIZE, 0,
                       lockLen - rdInfo.SectorCount*RAW_SECTOR_SIZE);
            }
            hr = IDirectSoundBuffer_Unlock(wmcda->dsBuf, cdData, lockLen, NULL, 0);
        }

        lastPos += fragLen;
        lastPos %= caps.dwBufferBytes;
        wmcda->start += rdInfo.SectorCount;

        LeaveCriticalSection(&wmcda->cs);
    }
    IDirectSoundBuffer_Stop(wmcda->dsBuf);
    SetEvent(wmcda->stopEvent);

    /* A design bug in native: the independent CD player called by the
     * MCI has no means to signal end of playing, therefore the MCI
     * notification is left hanging.  MCI_NOTIFY_SUPERSEDED will be
     * signaled by the next command that has MCI_NOTIFY set (or
     * MCI_NOTIFY_ABORTED for MCI_PLAY). */

    return 0;
}