From ae41ad5d1ed2c9b41cf5bbb7aa78848a043ee1f8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 2 Aug 2010 20:04:52 -0700 Subject: Use a better method to time the Null and Wave Writer backends This better compensates for precision loss when converting milliseconds to the sample rate --- Alc/wave.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'Alc/wave.c') diff --git a/Alc/wave.c b/Alc/wave.c index 1b6a41d1..5f1f399b 100644 --- a/Alc/wave.c +++ b/Alc/wave.c @@ -35,6 +35,8 @@ typedef struct { ALvoid *buffer; ALuint size; + ALuint startTime; + volatile int killNow; ALvoid *thread; } wave_data; @@ -68,32 +70,42 @@ static ALuint WaveProc(ALvoid *ptr) ALCdevice *pDevice = (ALCdevice*)ptr; wave_data *data = (wave_data*)pDevice->ExtraData; ALuint frameSize; - ALuint now, last; + ALuint now, start; + ALuint64 avail, done; size_t fs; - ALuint avail; union { short s; char b[sizeof(short)]; } uSB; + const ALuint restTime = (ALuint64)pDevice->UpdateSize * 1000 / + pDevice->Frequency / 2; uSB.s = 1; frameSize = aluFrameSizeFromFormat(pDevice->Format); - last = timeGetTime()<<8; + done = 0; + start = data->startTime; while(!data->killNow && pDevice->Connected) { - now = timeGetTime()<<8; + now = timeGetTime(); - avail = (ALuint64)(now-last) * pDevice->Frequency / (1000<<8); - if(avail < pDevice->UpdateSize) + avail = (ALuint64)(now-start) * pDevice->Frequency / 1000; + if(avail < done) + { + AL_PRINT("Timer wrapped\n"); + aluHandleDisconnect(pDevice); + break; + } + if(avail-done < pDevice->UpdateSize) { - Sleep(1); + Sleep(restTime); continue; } - while(avail >= pDevice->UpdateSize) + while(avail-done >= pDevice->UpdateSize) { aluMixData(pDevice, data->buffer, pDevice->UpdateSize); + done += pDevice->UpdateSize; if(uSB.b[0] != 1) { @@ -125,9 +137,6 @@ static ALuint WaveProc(ALvoid *ptr) aluHandleDisconnect(pDevice); break; } - - avail -= pDevice->UpdateSize; - last += (ALuint64)pDevice->UpdateSize * (1000<<8) / pDevice->Frequency; } } @@ -277,6 +286,7 @@ static ALCboolean wave_reset_playback(ALCdevice *device) device->Frequency; SetDefaultWFXChannelOrder(device); + data->startTime = timeGetTime(); data->thread = StartThread(WaveProc, device); if(data->thread == NULL) { -- cgit v1.2.3