diff options
Diffstat (limited to 'Alc/ALc.c')
-rw-r--r-- | Alc/ALc.c | 287 |
1 files changed, 236 insertions, 51 deletions
@@ -157,6 +157,8 @@ static const ALCfunction alcFunctions[] = { DECL(alcIsRenderFormatSupportedSOFT), DECL(alcRenderSamplesSOFT), + DECL(alcIsAmbisonicFormatSupportedSOFT), + DECL(alcDevicePauseSOFT), DECL(alcDeviceResumeSOFT), @@ -335,6 +337,7 @@ static const ALCenums enumeration[] = { DECL(ALC_5POINT1_SOFT), DECL(ALC_6POINT1_SOFT), DECL(ALC_7POINT1_SOFT), + DECL(ALC_BFORMAT3D_SOFT), DECL(ALC_BYTE_SOFT), DECL(ALC_UNSIGNED_BYTE_SOFT), @@ -357,6 +360,14 @@ static const ALCenums enumeration[] = { DECL(ALC_HRTF_SPECIFIER_SOFT), DECL(ALC_HRTF_ID_SOFT), + DECL(ALC_AMBISONIC_LAYOUT_SOFT), + DECL(ALC_AMBISONIC_SCALING_SOFT), + DECL(ALC_AMBISONIC_ORDER_SOFT), + DECL(ALC_ACN_SOFT), + DECL(ALC_FUMA_SOFT), + DECL(ALC_N3D_SOFT), + DECL(ALC_SN3D_SOFT), + DECL(ALC_NO_ERROR), DECL(ALC_INVALID_DEVICE), DECL(ALC_INVALID_CONTEXT), @@ -1478,11 +1489,34 @@ static ALCboolean IsValidALCChannels(ALCenum channels) case ALC_5POINT1_SOFT: case ALC_6POINT1_SOFT: case ALC_7POINT1_SOFT: + case ALC_BFORMAT3D_SOFT: return ALC_TRUE; } return ALC_FALSE; } +static ALCboolean IsValidAmbiLayout(ALCenum layout) +{ + switch(layout) + { + case ALC_ACN_SOFT: + case ALC_FUMA_SOFT: + return ALC_TRUE; + } + return ALC_FALSE; +} + +static ALCboolean IsValidAmbiScaling(ALCenum scaling) +{ + switch(scaling) + { + case ALC_N3D_SOFT: + case ALC_SN3D_SOFT: + case ALC_FUMA_SOFT: + return ALC_TRUE; + } + return ALC_FALSE; +} /************************************************ * Miscellaneous ALC helpers @@ -1746,12 +1780,15 @@ static void alcSetError(ALCdevice *device, ALCenum errorCode) * * 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. + * to jump forward or back. Must not be called while the device is running/ + * mixing. */ static inline void UpdateClockBase(ALCdevice *device) { + IncrementRef(&device->MixCount); device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency; device->SamplesDone = 0; + IncrementRef(&device->MixCount); } /* UpdateDeviceParams @@ -1773,22 +1810,19 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) ALCuint oldFreq; FPUCtl oldMode; size_t size; + ALCsizei i; // Check for attributes if(device->Type == Loopback) { - enum { - GotFreq = 1<<0, - GotChans = 1<<1, - GotType = 1<<2, - GotAll = GotFreq|GotChans|GotType - }; - ALCuint freq, numMono, numStereo; - enum DevFmtChannels schans; - enum DevFmtType stype; - ALCuint attrIdx = 0; - ALCint gotFmt = 0; - ALCsizei numSends; + ALCsizei numMono, numStereo, numSends; + ALCenum alayout = AL_NONE; + ALCenum ascale = AL_NONE; + ALCenum schans = AL_NONE; + ALCenum stype = AL_NONE; + ALCsizei attrIdx = 0; + ALCsizei aorder = 0; + ALCuint freq = 0; if(!attrList) { @@ -1798,9 +1832,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) numMono = device->NumMonoSources; numStereo = device->NumStereoSources; - schans = device->FmtChans; - stype = device->FmtType; - freq = device->Frequency; numSends = old_sends; #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v) @@ -1808,22 +1839,18 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) { if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT) { - ALCint val = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, val); - if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val)) + schans = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans); + if(!IsValidALCChannels(schans)) return ALC_INVALID_VALUE; - schans = val; - gotFmt |= GotChans; } if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT) { - ALCint val = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, val); - if(!IsValidALCType(val) || !BytesFromDevFmt(val)) + stype = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype); + if(!IsValidALCType(stype)) return ALC_INVALID_VALUE; - stype = val; - gotFmt |= GotType; } if(attrList[attrIdx] == ALC_FREQUENCY) @@ -1832,16 +1859,38 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) TRACE_ATTR(ALC_FREQUENCY, freq); if(freq < MIN_OUTPUT_RATE) return ALC_INVALID_VALUE; - gotFmt |= GotFreq; + } + + if(attrList[attrIdx] == ALC_AMBISONIC_LAYOUT_SOFT) + { + alayout = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout); + if(!IsValidAmbiLayout(alayout)) + return ALC_INVALID_VALUE; + } + + if(attrList[attrIdx] == ALC_AMBISONIC_SCALING_SOFT) + { + ascale = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale); + if(!IsValidAmbiScaling(ascale)) + return ALC_INVALID_VALUE; + } + + if(attrList[attrIdx] == ALC_AMBISONIC_ORDER_SOFT) + { + aorder = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder); + if(aorder < 1 || aorder > MAX_AMBI_ORDER) + return ALC_INVALID_VALUE; } if(attrList[attrIdx] == ALC_STEREO_SOURCES) { numStereo = attrList[attrIdx + 1]; TRACE_ATTR(ALC_STEREO_SOURCES, numStereo); - if(numStereo > device->SourcesMax) - numStereo = device->SourcesMax; + numStereo = clampi(numStereo, 0, device->SourcesMax); numMono = device->SourcesMax - numStereo; } @@ -1849,14 +1898,16 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) { numSends = attrList[attrIdx + 1]; TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends); + numSends = clampi(numSends, 0, MAX_SENDS); } if(attrList[attrIdx] == ALC_HRTF_SOFT) { - TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]); - if(attrList[attrIdx + 1] == ALC_FALSE) + ALCint val = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_HRTF_SOFT, val); + if(val == ALC_FALSE) hrtf_appreq = Hrtf_Disable; - else if(attrList[attrIdx + 1] == ALC_TRUE) + else if(val == ALC_TRUE) hrtf_appreq = Hrtf_Enable; else hrtf_appreq = Hrtf_Default; @@ -1872,11 +1923,16 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) } #undef TRACE_ATTR - if(gotFmt != GotAll) + if(!schans || !stype || !freq) { WARN("Missing format for loopback device\n"); return ALC_INVALID_VALUE; } + if(schans == ALC_BFORMAT3D_SOFT && (!alayout || !ascale || !aorder)) + { + WARN("Missing ambisonic info for loopback device\n"); + return ALC_INVALID_VALUE; + } if((device->Flags&DEVICE_RUNNING)) V0(device->Backend,stop)(); @@ -1884,22 +1940,29 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) UpdateClockBase(device); + if(schans == ALC_BFORMAT3D_SOFT) + { + device->FmtChans = DevFmtAmbi1 + aorder; + device->AmbiLayout = alayout; + device->AmbiScale = ascale; + } + else + device->FmtChans = schans; device->Frequency = freq; - device->FmtChans = schans; device->FmtType = stype; device->NumMonoSources = numMono; device->NumStereoSources = numStereo; if(ConfigValueInt(NULL, NULL, "sends", &new_sends)) - new_sends = clampi(numSends, 0, clampi(new_sends, 0, MAX_SENDS)); + new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS)); else - new_sends = clampi(numSends, 0, MAX_SENDS); + new_sends = numSends; } else if(attrList && attrList[0]) { - ALCuint freq, numMono, numStereo; - ALCuint attrIdx = 0; - ALCsizei numSends; + ALCsizei numMono, numStereo, numSends; + ALCsizei attrIdx = 0; + ALCuint freq; /* If a context is already running on the device, stop playback so the * device attributes can be updated. */ @@ -1928,9 +1991,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) { numStereo = attrList[attrIdx + 1]; TRACE_ATTR(ALC_STEREO_SOURCES, numStereo); - if(numStereo > device->SourcesMax) - numStereo = device->SourcesMax; + numStereo = clampi(numStereo, 0, device->SourcesMax); numMono = device->SourcesMax - numStereo; } @@ -1938,6 +2000,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) { numSends = attrList[attrIdx + 1]; TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends); + numSends = clampi(numSends, 0, MAX_SENDS); } if(attrList[attrIdx] == ALC_HRTF_SOFT) @@ -1975,9 +2038,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) device->NumStereoSources = numStereo; if(ConfigValueInt(al_string_get_cstr(device->DeviceName), NULL, "sends", &new_sends)) - new_sends = clampi(numSends, 0, clampi(new_sends, 0, MAX_SENDS)); + new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS)); else - new_sends = clampi(numSends, 0, MAX_SENDS); + new_sends = numSends; } if((device->Flags&DEVICE_RUNNING)) @@ -1989,6 +2052,13 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) al_free(device->Bs2b); device->Bs2b = NULL; + al_free(device->ChannelDelay[0].Buffer); + for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) + { + device->ChannelDelay[i].Length = 0; + device->ChannelDelay[i].Buffer = NULL; + } + al_free(device->Dry.Buffer); device->Dry.Buffer = NULL; device->Dry.NumChannels = 0; @@ -2270,6 +2340,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) */ static ALCvoid FreeDevice(ALCdevice *device) { + ALsizei i; + TRACE("%p\n", device); V0(device->Backend,close)(); @@ -2323,6 +2395,14 @@ static ALCvoid FreeDevice(ALCdevice *device) ambiup_free(device->AmbiUp); device->AmbiUp = NULL; + al_free(device->ChannelDelay[0].Buffer); + for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) + { + device->ChannelDelay[i].Gain = 1.0f; + device->ChannelDelay[i].Length = 0; + device->ChannelDelay[i].Buffer = NULL; + } + AL_STRING_DEINIT(device->DeviceName); al_free(device->Dry.Buffer); @@ -2883,6 +2963,14 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para } +static inline ALCsizei NumAttrsForDevice(ALCdevice *device) +{ + if(device->Type == Loopback && device->FmtChans >= DevFmtAmbi1 && + device->FmtChans <= DevFmtAmbi3) + return 23; + return 17; +} + static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) { ALCsizei i; @@ -2914,6 +3002,9 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC case ALC_CAPTURE_SAMPLES: case ALC_FORMAT_CHANNELS_SOFT: case ALC_FORMAT_TYPE_SOFT: + case ALC_AMBISONIC_LAYOUT_SOFT: + case ALC_AMBISONIC_SCALING_SOFT: + case ALC_AMBISONIC_ORDER_SOFT: alcSetError(NULL, ALC_INVALID_DEVICE); return 0; @@ -2965,11 +3056,11 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC return 1; case ALC_ATTRIBUTES_SIZE: - values[0] = 17; + values[0] = NumAttrsForDevice(device); return 1; case ALC_ALL_ATTRIBUTES: - if(size < 17) + if(size < NumAttrsForDevice(device)) { alcSetError(device, ALC_INVALID_VALUE); return 0; @@ -2990,8 +3081,25 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC } else { - values[i++] = ALC_FORMAT_CHANNELS_SOFT; - values[i++] = device->FmtChans; + if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) + { + values[i++] = ALC_FORMAT_CHANNELS_SOFT; + values[i++] = ALC_BFORMAT3D_SOFT; + + values[i++] = ALC_AMBISONIC_LAYOUT_SOFT; + values[i++] = device->AmbiLayout; + + values[i++] = ALC_AMBISONIC_SCALING_SOFT; + values[i++] = device->AmbiScale; + + values[i++] = ALC_AMBISONIC_ORDER_SOFT; + values[i++] = device->FmtChans-DevFmtAmbi1+1; + } + else + { + values[i++] = ALC_FORMAT_CHANNELS_SOFT; + values[i++] = device->FmtChans; + } values[i++] = ALC_FORMAT_TYPE_SOFT; values[i++] = device->FmtType; @@ -3046,7 +3154,10 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC alcSetError(device, ALC_INVALID_DEVICE); return 0; } - values[0] = device->FmtChans; + if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) + values[0] = ALC_BFORMAT3D_SOFT; + else + values[0] = device->FmtChans; return 1; case ALC_FORMAT_TYPE_SOFT: @@ -3058,6 +3169,36 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC values[0] = device->FmtType; return 1; + case ALC_AMBISONIC_LAYOUT_SOFT: + if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 && + device->FmtChans <= DevFmtAmbi3)) + { + alcSetError(device, ALC_INVALID_DEVICE); + return 0; + } + values[0] = device->AmbiLayout; + return 1; + + case ALC_AMBISONIC_SCALING_SOFT: + if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 && + device->FmtChans <= DevFmtAmbi3)) + { + alcSetError(device, ALC_INVALID_DEVICE); + return 0; + } + values[0] = device->AmbiScale; + return 1; + + case ALC_AMBISONIC_ORDER_SOFT: + if(device->Type != Loopback || !(device->FmtChans >= DevFmtAmbi1 && + device->FmtChans <= DevFmtAmbi3)) + { + alcSetError(device, ALC_INVALID_DEVICE); + return 0; + } + values[0] = device->FmtChans - DevFmtAmbi1 + 1; + return 1; + case ALC_MONO_SOURCES: values[0] = device->NumMonoSources; return 1; @@ -3567,6 +3708,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) const ALCchar *fmt; ALCdevice *device; ALCenum err; + ALCsizei i; DO_INITCONFIG(); @@ -3628,6 +3770,13 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) InitUIntMap(&device->EffectMap, ~0); InitUIntMap(&device->FilterMap, ~0); + for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) + { + device->ChannelDelay[i].Gain = 1.0f; + device->ChannelDelay[i].Length = 0; + device->ChannelDelay[i].Buffer = NULL; + } + //Set output format device->FmtChans = DevFmtChannelsDefault; device->FmtType = DevFmtTypeDefault; @@ -3871,6 +4020,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, { ALCdevice *device = NULL; ALCenum err; + ALCsizei i; DO_INITCONFIG(); @@ -3916,6 +4066,13 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, InitUIntMap(&device->EffectMap, ~0); InitUIntMap(&device->FilterMap, ~0); + for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) + { + device->ChannelDelay[i].Gain = 1.0f; + device->ChannelDelay[i].Length = 0; + device->ChannelDelay[i].Buffer = NULL; + } + if(!CaptureBackend.getFactory) device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs, ALCbackend_Capture); @@ -4078,6 +4235,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN { ALCbackendFactory *factory; ALCdevice *device; + ALCsizei i; DO_INITCONFIG(); @@ -4128,6 +4286,13 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN InitUIntMap(&device->EffectMap, ~0); InitUIntMap(&device->FilterMap, ~0); + for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) + { + device->ChannelDelay[i].Gain = 1.0f; + device->ChannelDelay[i].Length = 0; + device->ChannelDelay[i].Buffer = NULL; + } + factory = ALCloopbackFactory_getFactory(); device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback); if(!device->Backend) @@ -4191,9 +4356,7 @@ ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device alcSetError(device, ALC_INVALID_VALUE); else { - if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 && - IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 && - freq >= MIN_OUTPUT_RATE) + if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE) ret = ALC_TRUE; } if(device) ALCdevice_DecRef(device); @@ -4223,6 +4386,28 @@ FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, AL /************************************************ + * ALC loopback2 functions + ************************************************/ + +ALC_API ALCboolean ALC_APIENTRY alcIsAmbisonicFormatSupportedSOFT(ALCdevice *device, ALCenum layout, ALCenum scaling, ALsizei order) +{ + ALCboolean ret = ALC_FALSE; + + if(!VerifyDevice(&device) || device->Type != Loopback) + alcSetError(device, ALC_INVALID_DEVICE); + else if(order <= 0) + alcSetError(device, ALC_INVALID_VALUE); + else + { + if(IsValidAmbiLayout(layout) && IsValidAmbiScaling(scaling) && order <= MAX_AMBI_ORDER) + ret = ALC_TRUE; + } + if(device) ALCdevice_DecRef(device); + + return ret; +} + +/************************************************ * ALC DSP pause/resume functions ************************************************/ |