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; }
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); }
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; } } }
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; } }
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); }
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; }
/* * バッファをリストアする */ 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; }
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); }
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); } }
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); } }
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; }
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; }
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; }
/** \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; }
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; }
/* ==================== 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; }
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; }
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); }
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; }
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); } }
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; }
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); }
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, ®ion->chunk1, ®ion->size1, ®ion->chunk2, ®ion->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, ®ion->chunk1, ®ion->size1, ®ion->chunk2, ®ion->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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }