diff options
-rw-r--r-- | Alc/ALc.c | 24 | ||||
-rw-r--r-- | Alc/ALu.c | 8 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 7 |
3 files changed, 39 insertions, 0 deletions
@@ -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; @@ -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 diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index b6a9f0ae..63c996e5 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -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" |