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
This commit is contained in:
Chris Robinson 2010-08-02 20:04:52 -07:00
parent ee61f7a55c
commit ae41ad5d1e
2 changed files with 42 additions and 25 deletions

View File

@ -30,6 +30,8 @@ typedef struct {
ALvoid *buffer; ALvoid *buffer;
ALuint size; ALuint size;
ALuint startTime;
volatile int killNow; volatile int killNow;
ALvoid *thread; ALvoid *thread;
} null_data; } null_data;
@ -41,30 +43,34 @@ static ALuint NullProc(ALvoid *ptr)
{ {
ALCdevice *Device = (ALCdevice*)ptr; ALCdevice *Device = (ALCdevice*)ptr;
null_data *data = (null_data*)Device->ExtraData; null_data *data = (null_data*)Device->ExtraData;
ALuint frameSize; ALuint now, start;
ALuint now, last; ALuint64 avail, done;
ALuint avail; const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 /
Device->Frequency / 2;
frameSize = aluFrameSizeFromFormat(Device->Format); done = 0;
start = data->startTime;
last = timeGetTime()<<8;
while(!data->killNow && Device->Connected) while(!data->killNow && Device->Connected)
{ {
now = timeGetTime()<<8; now = timeGetTime();
avail = (ALuint64)(now-last) * Device->Frequency / (1000<<8); avail = (ALuint64)(now-start) * Device->Frequency / 1000;
if(avail < Device->UpdateSize) if(avail < done)
{ {
Sleep(1); AL_PRINT("Timer wrapped\n");
aluHandleDisconnect(Device);
break;
}
if(avail-done < Device->UpdateSize)
{
Sleep(restTime);
continue; continue;
} }
while(avail >= Device->UpdateSize) while(avail-done >= Device->UpdateSize)
{ {
aluMixData(Device, data->buffer, Device->UpdateSize); aluMixData(Device, data->buffer, Device->UpdateSize);
done += Device->UpdateSize;
avail -= Device->UpdateSize;
last += (ALuint64)Device->UpdateSize * (1000<<8) / Device->Frequency;
} }
} }
@ -111,6 +117,7 @@ static ALCboolean null_reset_playback(ALCdevice *device)
device->TimeRes = (ALuint64)device->UpdateSize * 1000000000 / device->TimeRes = (ALuint64)device->UpdateSize * 1000000000 /
device->Frequency; device->Frequency;
data->startTime = timeGetTime();
data->thread = StartThread(NullProc, device); data->thread = StartThread(NullProc, device);
if(data->thread == NULL) if(data->thread == NULL)
{ {

View File

@ -35,6 +35,8 @@ typedef struct {
ALvoid *buffer; ALvoid *buffer;
ALuint size; ALuint size;
ALuint startTime;
volatile int killNow; volatile int killNow;
ALvoid *thread; ALvoid *thread;
} wave_data; } wave_data;
@ -68,32 +70,42 @@ static ALuint WaveProc(ALvoid *ptr)
ALCdevice *pDevice = (ALCdevice*)ptr; ALCdevice *pDevice = (ALCdevice*)ptr;
wave_data *data = (wave_data*)pDevice->ExtraData; wave_data *data = (wave_data*)pDevice->ExtraData;
ALuint frameSize; ALuint frameSize;
ALuint now, last; ALuint now, start;
ALuint64 avail, done;
size_t fs; size_t fs;
ALuint avail;
union { union {
short s; short s;
char b[sizeof(short)]; char b[sizeof(short)];
} uSB; } uSB;
const ALuint restTime = (ALuint64)pDevice->UpdateSize * 1000 /
pDevice->Frequency / 2;
uSB.s = 1; uSB.s = 1;
frameSize = aluFrameSizeFromFormat(pDevice->Format); frameSize = aluFrameSizeFromFormat(pDevice->Format);
last = timeGetTime()<<8; done = 0;
start = data->startTime;
while(!data->killNow && pDevice->Connected) while(!data->killNow && pDevice->Connected)
{ {
now = timeGetTime()<<8; now = timeGetTime();
avail = (ALuint64)(now-last) * pDevice->Frequency / (1000<<8); avail = (ALuint64)(now-start) * pDevice->Frequency / 1000;
if(avail < pDevice->UpdateSize) if(avail < done)
{ {
Sleep(1); AL_PRINT("Timer wrapped\n");
aluHandleDisconnect(pDevice);
break;
}
if(avail-done < pDevice->UpdateSize)
{
Sleep(restTime);
continue; continue;
} }
while(avail >= pDevice->UpdateSize) while(avail-done >= pDevice->UpdateSize)
{ {
aluMixData(pDevice, data->buffer, pDevice->UpdateSize); aluMixData(pDevice, data->buffer, pDevice->UpdateSize);
done += pDevice->UpdateSize;
if(uSB.b[0] != 1) if(uSB.b[0] != 1)
{ {
@ -125,9 +137,6 @@ static ALuint WaveProc(ALvoid *ptr)
aluHandleDisconnect(pDevice); aluHandleDisconnect(pDevice);
break; 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; device->Frequency;
SetDefaultWFXChannelOrder(device); SetDefaultWFXChannelOrder(device);
data->startTime = timeGetTime();
data->thread = StartThread(WaveProc, device); data->thread = StartThread(WaveProc, device);
if(data->thread == NULL) if(data->thread == NULL)
{ {