aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/ALc.c
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/ALc.c')
-rw-r--r--Alc/ALc.c363
1 files changed, 251 insertions, 112 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index fea0320d..805be2fa 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -153,6 +153,8 @@ static const ALCfunction alcFunctions[] = {
DECL(alcDevicePauseSOFT),
DECL(alcDeviceResumeSOFT),
+ DECL(alcGetInteger64vSOFT),
+
DECL(alEnable),
DECL(alDisable),
DECL(alIsEnabled),
@@ -744,8 +746,8 @@ static const ALCchar alcNoDeviceExtList[] =
static const ALCchar alcExtensionList[] =
"ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
"ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
- "ALC_EXT_thread_local_context ALC_SOFTX_HRTF ALC_SOFT_loopback "
- "ALC_SOFTX_midi_interface ALC_SOFTX_pause_device";
+ "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
+ "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFTX_pause_device";
static const ALCint alcMajorVersion = 1;
static const ALCint alcMinorVersion = 1;
@@ -1577,6 +1579,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 +1697,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;
@@ -1745,10 +1761,12 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
device->UpdateSize = (ALuint64)device->UpdateSize * freq /
device->Frequency;
- /* SSE does best with the update size being a multiple of 4 */
- if((CPUCapFlags&CPU_CAP_SSE))
+ /* SSE and Neon do best with the update size being a multiple of 4 */
+ 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 +1776,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;
@@ -1861,6 +1881,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
{
if((CPUCapFlags&CPU_CAP_SSE))
WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
+ if((CPUCapFlags&CPU_CAP_NEON))
+ WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
}
SetMixerFPUMode(&oldMode);
@@ -2415,19 +2437,14 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para
}
-/* alcGetIntegerv
- *
- * Returns information about the device and the version of OpenAL
- */
-ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
+static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
{
- device = VerifyDevice(device);
+ ALCsizei i;
- if(size == 0 || data == NULL)
+ if(size <= 0 || values == NULL)
{
alcSetError(device, ALC_INVALID_VALUE);
- if(device) ALCdevice_DecRef(device);
- return;
+ return 0;
}
if(!device)
@@ -2435,11 +2452,11 @@ ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsi
switch(param)
{
case ALC_MAJOR_VERSION:
- *data = alcMajorVersion;
- break;
+ values[0] = alcMajorVersion;
+ return 1;
case ALC_MINOR_VERSION:
- *data = alcMinorVersion;
- break;
+ values[0] = alcMinorVersion;
+ return 1;
case ALC_ATTRIBUTES_SIZE:
case ALC_ALL_ATTRIBUTES:
@@ -2452,153 +2469,269 @@ ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsi
case ALC_FORMAT_CHANNELS_SOFT:
case ALC_FORMAT_TYPE_SOFT:
alcSetError(NULL, ALC_INVALID_DEVICE);
- break;
+ return 0;
default:
alcSetError(NULL, ALC_INVALID_ENUM);
- break;
+ return 0;
}
+ return 0;
}
- else if(device->Type == Capture)
+
+ if(device->Type == Capture)
{
switch(param)
{
case ALC_CAPTURE_SAMPLES:
ALCdevice_Lock(device);
- *data = V0(device->Backend,availableSamples)();
+ values[0] = V0(device->Backend,availableSamples)();
ALCdevice_Unlock(device);
- break;
+ return 1;
case ALC_CONNECTED:
- *data = device->Connected;
- break;
+ values[0] = device->Connected;
+ return 1;
default:
alcSetError(device, ALC_INVALID_ENUM);
- break;
+ return 0;
}
+ return 0;
}
- else /* render device */
+
+ /* render device */
+ switch(param)
{
- switch(param)
- {
- case ALC_MAJOR_VERSION:
- *data = alcMajorVersion;
- break;
+ case ALC_MAJOR_VERSION:
+ values[0] = alcMajorVersion;
+ return 1;
- case ALC_MINOR_VERSION:
- *data = alcMinorVersion;
- break;
+ case ALC_MINOR_VERSION:
+ values[0] = alcMinorVersion;
+ return 1;
- case ALC_EFX_MAJOR_VERSION:
- *data = alcEFXMajorVersion;
- break;
+ case ALC_EFX_MAJOR_VERSION:
+ values[0] = alcEFXMajorVersion;
+ return 1;
- case ALC_EFX_MINOR_VERSION:
- *data = alcEFXMinorVersion;
- break;
+ case ALC_EFX_MINOR_VERSION:
+ values[0] = alcEFXMinorVersion;
+ return 1;
+ case ALC_ATTRIBUTES_SIZE:
+ values[0] = 15;
+ return 1;
+
+ case ALC_ALL_ATTRIBUTES:
+ if(size < 15)
+ {
+ alcSetError(device, ALC_INVALID_VALUE);
+ return 0;
+ }
+
+ i = 0;
+ values[i++] = ALC_FREQUENCY;
+ values[i++] = device->Frequency;
+
+ if(device->Type != Loopback)
+ {
+ values[i++] = ALC_REFRESH;
+ values[i++] = device->Frequency / device->UpdateSize;
+
+ values[i++] = ALC_SYNC;
+ values[i++] = ALC_FALSE;
+ }
+ else
+ {
+ values[i++] = ALC_FORMAT_CHANNELS_SOFT;
+ values[i++] = device->FmtChans;
+
+ values[i++] = ALC_FORMAT_TYPE_SOFT;
+ values[i++] = device->FmtType;
+ }
+
+ values[i++] = ALC_MONO_SOURCES;
+ values[i++] = device->NumMonoSources;
+
+ values[i++] = ALC_STEREO_SOURCES;
+ values[i++] = device->NumStereoSources;
+
+ values[i++] = ALC_MAX_AUXILIARY_SENDS;
+ values[i++] = device->NumAuxSends;
+
+ values[i++] = ALC_HRTF_SOFT;
+ values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
+
+ values[i++] = 0;
+ return i;
+
+ case ALC_FREQUENCY:
+ values[0] = device->Frequency;
+ return 1;
+
+ case ALC_REFRESH:
+ if(device->Type == Loopback)
+ {
+ alcSetError(device, ALC_INVALID_DEVICE);
+ return 0;
+ }
+ values[0] = device->Frequency / device->UpdateSize;
+ return 1;
+
+ case ALC_SYNC:
+ if(device->Type == Loopback)
+ {
+ alcSetError(device, ALC_INVALID_DEVICE);
+ return 0;
+ }
+ values[0] = ALC_FALSE;
+ return 1;
+
+ case ALC_FORMAT_CHANNELS_SOFT:
+ if(device->Type != Loopback)
+ {
+ alcSetError(device, ALC_INVALID_DEVICE);
+ return 0;
+ }
+ values[0] = device->FmtChans;
+ return 1;
+
+ case ALC_FORMAT_TYPE_SOFT:
+ if(device->Type != Loopback)
+ {
+ alcSetError(device, ALC_INVALID_DEVICE);
+ return 0;
+ }
+ values[0] = device->FmtType;
+ return 1;
+
+ case ALC_MONO_SOURCES:
+ values[0] = device->NumMonoSources;
+ return 1;
+
+ case ALC_STEREO_SOURCES:
+ values[0] = device->NumStereoSources;
+ return 1;
+
+ case ALC_MAX_AUXILIARY_SENDS:
+ values[0] = device->NumAuxSends;
+ return 1;
+
+ case ALC_CONNECTED:
+ values[0] = device->Connected;
+ return 1;
+
+ case ALC_HRTF_SOFT:
+ values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
+ return 1;
+
+ default:
+ alcSetError(device, ALC_INVALID_ENUM);
+ return 0;
+ }
+ return 0;
+}
+
+/* alcGetIntegerv
+ *
+ * Returns information about the device and the version of OpenAL
+ */
+ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
+{
+ device = VerifyDevice(device);
+ if(size <= 0 || values == NULL)
+ alcSetError(device, ALC_INVALID_VALUE);
+ else
+ GetIntegerv(device, param, size, values);
+ if(device) ALCdevice_DecRef(device);
+}
+
+ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
+{
+ ALCint *ivals;
+ ALsizei i;
+
+ device = VerifyDevice(device);
+ if(size <= 0 || values == NULL)
+ alcSetError(device, ALC_INVALID_VALUE);
+ else if(!device || device->Type == Capture)
+ {
+ ivals = malloc(size * sizeof(ALCint));
+ size = GetIntegerv(device, pname, size, ivals);
+ for(i = 0;i < size;i++)
+ values[i] = ivals[i];
+ free(ivals);
+ }
+ else /* render device */
+ {
+ switch(pname)
+ {
case ALC_ATTRIBUTES_SIZE:
- *data = 15;
+ *values = 17;
break;
case ALC_ALL_ATTRIBUTES:
- if(size < 15)
+ if(size < 17)
alcSetError(device, ALC_INVALID_VALUE);
else
{
int i = 0;
- data[i++] = ALC_FREQUENCY;
- data[i++] = device->Frequency;
+ V0(device->Backend,lock)();
+ values[i++] = ALC_FREQUENCY;
+ values[i++] = device->Frequency;
if(device->Type != Loopback)
{
- data[i++] = ALC_REFRESH;
- data[i++] = device->Frequency / device->UpdateSize;
+ values[i++] = ALC_REFRESH;
+ values[i++] = device->Frequency / device->UpdateSize;
- data[i++] = ALC_SYNC;
- data[i++] = ALC_FALSE;
+ values[i++] = ALC_SYNC;
+ values[i++] = ALC_FALSE;
}
else
{
- data[i++] = ALC_FORMAT_CHANNELS_SOFT;
- data[i++] = device->FmtChans;
+ values[i++] = ALC_FORMAT_CHANNELS_SOFT;
+ values[i++] = device->FmtChans;
- data[i++] = ALC_FORMAT_TYPE_SOFT;
- data[i++] = device->FmtType;
+ values[i++] = ALC_FORMAT_TYPE_SOFT;
+ values[i++] = device->FmtType;
}
- data[i++] = ALC_MONO_SOURCES;
- data[i++] = device->NumMonoSources;
-
- data[i++] = ALC_STEREO_SOURCES;
- data[i++] = device->NumStereoSources;
+ values[i++] = ALC_MONO_SOURCES;
+ values[i++] = device->NumMonoSources;
- data[i++] = ALC_MAX_AUXILIARY_SENDS;
- data[i++] = device->NumAuxSends;
+ values[i++] = ALC_STEREO_SOURCES;
+ values[i++] = device->NumStereoSources;
- data[i++] = ALC_HRTF_SOFT;
- data[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
+ values[i++] = ALC_MAX_AUXILIARY_SENDS;
+ values[i++] = device->NumAuxSends;
- data[i++] = 0;
- }
- break;
+ values[i++] = ALC_HRTF_SOFT;
+ values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
- case ALC_FREQUENCY:
- *data = device->Frequency;
- break;
+ values[i++] = ALC_DEVICE_CLOCK_SOFT;
+ values[i++] = device->ClockBase +
+ (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
- case ALC_REFRESH:
- if(device->Type == Loopback)
- alcSetError(device, ALC_INVALID_DEVICE);
- else
- *data = device->Frequency / device->UpdateSize;
- break;
-
- case ALC_SYNC:
- if(device->Type == Loopback)
- alcSetError(device, ALC_INVALID_DEVICE);
- else
- *data = ALC_FALSE;
- break;
-
- case ALC_FORMAT_CHANNELS_SOFT:
- if(device->Type != Loopback)
- alcSetError(device, ALC_INVALID_DEVICE);
- else
- *data = device->FmtChans;
- break;
-
- case ALC_FORMAT_TYPE_SOFT:
- if(device->Type != Loopback)
- alcSetError(device, ALC_INVALID_DEVICE);
- else
- *data = device->FmtType;
- break;
-
- case ALC_MONO_SOURCES:
- *data = device->NumMonoSources;
- break;
-
- case ALC_STEREO_SOURCES:
- *data = device->NumStereoSources;
- break;
-
- case ALC_MAX_AUXILIARY_SENDS:
- *data = device->NumAuxSends;
- break;
-
- case ALC_CONNECTED:
- *data = device->Connected;
+ values[i++] = 0;
+ V0(device->Backend,unlock)();
+ }
break;
- case ALC_HRTF_SOFT:
- *data = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
+ case ALC_DEVICE_CLOCK_SOFT:
+ V0(device->Backend,lock)();
+ *values = device->ClockBase +
+ (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
+ V0(device->Backend,unlock)();
break;
default:
- alcSetError(device, ALC_INVALID_ENUM);
+ ivals = malloc(size * sizeof(ALCint));
+ size = GetIntegerv(device, pname, size, ivals);
+ for(i = 0;i < size;i++)
+ values[i] = ivals[i];
+ free(ivals);
break;
}
}
@@ -2933,6 +3066,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;
@@ -3400,6 +3536,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;