Keep track of a device clock time, based on the number of samples processed

This commit is contained in:
Chris Robinson 2014-02-01 16:37:11 -08:00
parent 9e2a8843a8
commit 69f3a7da6d
3 changed files with 39 additions and 0 deletions

View File

@ -1577,6 +1577,18 @@ static void alcSetError(ALCdevice *device, ALCenum errorCode)
}
/* UpdateClockBase
*
* Updates the device's base clock time with however many samples have been
* done. This is used so frequency changes on the device don't cause the time
* to jump forward or back.
*/
static inline void UpdateClockBase(ALCdevice *device)
{
device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
device->SamplesDone = 0;
}
/* UpdateDeviceParams
*
* Updates device parameters according to the attribute list (caller is
@ -1683,6 +1695,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
V0(device->Backend,stop)();
device->Flags &= ~DEVICE_RUNNING;
if(freq != device->Frequency)
UpdateClockBase(device);
device->Frequency = freq;
device->FmtChans = schans;
device->FmtType = stype;
@ -1749,6 +1763,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
device->UpdateSize = (device->UpdateSize+3)&~3;
if(freq != device->Frequency)
UpdateClockBase(device);
device->Frequency = freq;
device->NumMonoSources = numMono;
device->NumStereoSources = numStereo;
@ -1758,6 +1774,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
if((device->Flags&DEVICE_RUNNING))
return ALC_NO_ERROR;
UpdateClockBase(device);
oldFreq = device->Frequency;
oldChans = device->FmtChans;
oldType = device->FmtType;
@ -2935,6 +2953,9 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
device->ContextList = NULL;
device->ClockBase = 0;
device->SamplesDone = 0;
device->MaxNoOfSources = 256;
device->AuxiliaryEffectSlotMax = 4;
device->NumAuxSends = MAX_SENDS;
@ -3402,6 +3423,9 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN
device->ContextList = NULL;
device->ClockBase = 0;
device->SamplesDone = 0;
device->MaxNoOfSources = 256;
device->AuxiliaryEffectSlotMax = 4;
device->NumAuxSends = MAX_SENDS;

View File

@ -1126,6 +1126,14 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
for(i = 0;i < SamplesToDo;i++)
(*slot)->WetBuffer[0][i] = 0.0f;
}
/* Increment the clock time. Every second's worth of samples is
* converted and added to clock base so that large sample counts don't
* overflow during conversion. This also guarantees an exact, stable
* conversion. */
device->SamplesDone += SamplesToDo;
device->ClockBase += (device->SamplesDone/device->Frequency) * DEVICE_CLOCK_RES;
device->SamplesDone %= device->Frequency;
ALCdevice_Unlock(device);
/* Click-removal. Could do better; this only really handles immediate

View File

@ -623,6 +623,9 @@ struct ALCdevice_struct
ALfloat SpeakerAngle[MaxChannels];
ALuint NumChan;
ALuint64 ClockBase;
ALuint SamplesDone;
/* Temp storage used for mixing. +1 for the predictive sample. */
ALIGN(16) ALfloat SampleData1[BUFFERSIZE+1];
ALIGN(16) ALfloat SampleData2[BUFFERSIZE+1];
@ -669,6 +672,10 @@ struct ALCdevice_struct
#define INVALID_OFFSET (~0u)
/* Nanosecond resolution for the device clock time. */
#define DEVICE_CLOCK_RES U64(1000000000)
/* Must be less than 15 characters (16 including terminating null) for
* compatibility with pthread_setname_np limitations. */
#define MIXER_THREAD_NAME "alsoft-mixer"