aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c24
-rw-r--r--Alc/ALu.c8
-rw-r--r--OpenAL32/Include/alMain.h7
3 files changed, 39 insertions, 0 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 7d8f14cd..ad8b4286 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -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;
diff --git a/Alc/ALu.c b/Alc/ALu.c
index bf09450f..bf3d8174 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -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"