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 (pSoundBuffer->lpVtbl->Lock (pSoundBuffer, 0, fragsize, &block, &bBytes, NULL, NULL, 0) == DSERR_BUFFERLOST) { pSoundBuffer->lpVtbl->Restore (pSoundBuffer); pSoundBuffer->lpVtbl->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); } pSoundBuffer->lpVtbl->Unlock (pSoundBuffer, block, bBytes, NULL, 0); pSoundBuffer->lpVtbl->SetCurrentPosition(pSoundBuffer, 0); pSoundBuffer->lpVtbl->Play(pSoundBuffer, 0, 0, DSBPLAY_LOOPING); threadInUse=1; ResumeThread (updateBufferHandle); } }
static void XAudio2_Update(void) { if (do_update && pSourceVoice) { do_update = 0; while (1) { XAUDIO2_VOICE_STATE state; XAUDIO2_BUFFER audio_buf; #if !defined(DRV_XAUDIO28) IXAudio2SourceVoice_GetState(pSourceVoice, &state); #else IXAudio2SourceVoice_GetState(pSourceVoice, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED); #endif if (state.BuffersQueued > 0) break; current_buf %= XAUDIO2_NUM_BUFFERS; if (Player_Paused_internal()) VC_SilenceBytes((SBYTE *) buffers[current_buf], (ULONG) XAUDIO2_BUFFER_SIZE); else VC_WriteBytes((SBYTE *) buffers[current_buf], (ULONG) XAUDIO2_BUFFER_SIZE); memset(&audio_buf, 0, sizeof(XAUDIO2_BUFFER)); audio_buf.AudioBytes = XAUDIO2_BUFFER_SIZE; audio_buf.pAudioData = buffers[current_buf]; IXAudio2SourceVoice_SubmitSourceBuffer(pSourceVoice, &audio_buf, NULL); current_buf++; current_buf %= XAUDIO2_NUM_BUFFERS; } IXAudio2SourceVoice_Start(pSourceVoice, 0, 0); threadInUse = 1; ResumeThread(UpdateBufferHandle); } }
static DWORD WINAPI UpdateBufferProc(LPVOID lpParameter) { while (threadInUse) { while (1) { XAUDIO2_VOICE_STATE state; XAUDIO2_BUFFER audio_buf; #if !defined(DRV_XAUDIO28) IXAudio2SourceVoice_GetState(pSourceVoice, &state); #else IXAudio2SourceVoice_GetState(pSourceVoice, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED); #endif if (state.BuffersQueued >= XAUDIO2_NUM_BUFFERS - 1) break; MUTEX_LOCK(vars); if (Player_Paused_internal()) VC_SilenceBytes((SBYTE *) buffers[current_buf], (ULONG) XAUDIO2_BUFFER_SIZE); else VC_WriteBytes((SBYTE *) buffers[current_buf], (ULONG) XAUDIO2_BUFFER_SIZE); MUTEX_UNLOCK(vars); memset(&audio_buf, 0, sizeof(XAUDIO2_BUFFER)); audio_buf.AudioBytes = XAUDIO2_BUFFER_SIZE; audio_buf.pAudioData = buffers[current_buf]; IXAudio2SourceVoice_SubmitSourceBuffer(pSourceVoice, &audio_buf, NULL); current_buf++; current_buf %= XAUDIO2_NUM_BUFFERS; } WaitForSingleObject(hBufferEvent, INFINITE); } return 0; }
static void WSS_Callback(void) { unsigned int dma_size, dma_pos; ULONG (*mixer)(SBYTE *buf, ULONG todo); wss_query_dma(&dma_size, &dma_pos); /* There isn't much sense in filling less than 256 bytes */ dma_pos &= ~255; /* If nothing to mix, quit */ if (buff_tail == dma_pos) return; if (Player_Paused_internal()) mixer = VC_SilenceBytes; else mixer = VC_WriteBytes; /* If DMA pointer still didn't wrapped around ... */ if (dma_pos > buff_tail) { buff_tail += mixer (wss.dma_buff->linear + buff_tail, dma_pos - buff_tail); /* If we arrived right to the DMA buffer end, jump to the beginning */ if (buff_tail >= dma_size) buff_tail = 0; } else { /* If wrapped around, fill first to the end of buffer */ mixer (wss.dma_buff->linear + buff_tail, dma_size - buff_tail); /* Now fill from buffer beginning to current DMA pointer */ buff_tail = mixer (wss.dma_buff->linear, dma_pos); } }
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; pSoundBuffer->lpVtbl->GetCurrentPosition (pSoundBuffer,&soundBufferCurrentPosition,NULL); if (soundBufferCurrentPosition < fragsize) start = fragsize; else start = 0; if (pSoundBuffer->lpVtbl->Lock (pSoundBuffer,start,fragsize,&pBlock1,&blockBytes1, &pBlock2,&blockBytes2,0)==DSERR_BUFFERLOST) { pSoundBuffer->lpVtbl->Restore(pSoundBuffer); pSoundBuffer->lpVtbl->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); pSoundBuffer->lpVtbl->Unlock (pSoundBuffer,pBlock1,blockBytes1,pBlock2,blockBytes2); } } return 0; }
/* ARGSUSED */ void OS2_UpdateBufferThread(void *dummy) { /* Run at timecritical priority */ DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM - 1, 0); while (!FinishPlayback) { ULONG count; static ULONG NextBuffer = 0; /* next fragment to be filled */ /* wait for play enable */ DosWaitEventSem(Play, SEM_INDEFINITE_WAIT); /* wait for timer event */ DosWaitEventSem(Update, SEM_INDEFINITE_WAIT); /* reset timer semaphore */ DosResetEventSem(Update, &count); /* fill all free buffers */ while (PlayList[NextBuffer].ulOperand3 >= PlayList[NextBuffer].ulOperand2) { MUTEX_LOCK(vars); if (Player_Paused_internal()) PlayList[NextBuffer].ulOperand2 = VC_SilenceBytes((SBYTE *)PlayList[NextBuffer].ulOperand1, BufferSize); else PlayList[NextBuffer].ulOperand2 = VC_WriteBytes((SBYTE *)PlayList[NextBuffer].ulOperand1, BufferSize); MUTEX_UNLOCK(vars); /* Reset play offset, although it seems MMOS2 does it automagically */ PlayList[NextBuffer].ulOperand3 = 0; NextBuffer = (NextBuffer + 1) % FRAGMENTS; } } /* Tell main thread we're done */ ThreadID = 0; }
/* Buffer update thread (created and called by DART) This is a high-priority thread used to compute and update the audio stream, automatically created by the DART subsystem. We compute the next audio buffer and feed it to the waveaudio device. */ static LONG APIENTRY Dart_UpdateBuffers(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags) { /* sanity check */ if (!pBuffer) return TRUE; /* if we have finished a buffer, we're ready to play a new one */ if ((ulFlags == MIX_WRITE_COMPLETE) || ((ulFlags == (MIX_WRITE_COMPLETE | MIX_STREAM_ERROR)) && (ulStatus == ERROR_DEVICE_UNDERRUN))) { /* refill this audio buffer and feed it again */ MUTEX_LOCK(vars); if (Player_Paused_internal()) pBuffer->ulBufferLength = VC_SilenceBytes(pBuffer->pBuffer, BufferSize); else pBuffer->ulBufferLength = VC_WriteBytes(pBuffer->pBuffer, BufferSize); MUTEX_UNLOCK(vars); MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle, pBuffer, 1); } return TRUE; }