diff options
-rw-r--r-- | Alc/ALc.c | 287 | ||||
-rw-r--r-- | Alc/ALu.c | 31 | ||||
-rw-r--r-- | Alc/bformatdec.c | 28 | ||||
-rw-r--r-- | Alc/bformatdec.h | 1 | ||||
-rw-r--r-- | Alc/panning.c | 18 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 40 | ||||
-rw-r--r-- | OpenAL32/Include/alSource.h | 8 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 54 | ||||
-rw-r--r-- | utils/alsoft-config/mainwindow.ui | 24 |
9 files changed, 360 insertions, 131 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 ************************************************/ @@ -1224,9 +1224,8 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro } } -static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean force) +static void CalcSourceParams(ALvoice *voice, ALsource *source, ALCcontext *context, ALboolean force) { - ALsource *source = voice->Source; const ALbufferlistitem *BufferListItem; struct ALsourceProps *props; @@ -1278,11 +1277,8 @@ static void UpdateContextSources(ALCcontext *ctx, ALeffectslot *slot) voice_end = voice + ctx->VoiceCount; for(;voice != voice_end;++voice) { - if(!(source=(*voice)->Source)) continue; - if(!IsPlayingOrPaused(source)) - (*voice)->Source = NULL; - else - CalcSourceParams(*voice, ctx, force); + if((source=(*voice)->Source) != NULL) + CalcSourceParams(*voice, source, ctx, force); } } IncrementRef(&ctx->UpdateCount); @@ -1332,24 +1328,24 @@ static void Write_##T(const ALfloatBUFFERSIZE *InBuffer, ALvoid *OutBuffer, \ T *restrict out = (T*)OutBuffer + j; \ const ALfloat gain = distcomp[j].Gain; \ const ALsizei base = distcomp[j].Length; \ + ALfloat *restrict distbuf = ASSUME_ALIGNED(distcomp[j].Buffer, 16); \ if(base > 0 || gain != 1.0f) \ { \ if(SamplesToDo >= base) \ { \ for(i = 0;i < base;i++) \ - out[i*numchans] = func(distcomp[j].Buffer[i]*gain); \ + out[i*numchans] = func(distbuf[i]*gain); \ for(;i < SamplesToDo;i++) \ out[i*numchans] = func(in[i-base]*gain); \ - memcpy(distcomp[j].Buffer, &in[SamplesToDo-base], \ - base*sizeof(ALfloat)); \ + memcpy(distbuf, &in[SamplesToDo-base], base*sizeof(ALfloat)); \ } \ else \ { \ for(i = 0;i < SamplesToDo;i++) \ - out[i*numchans] = func(distcomp[j].Buffer[i]*gain); \ - memmove(distcomp[j].Buffer, distcomp[j].Buffer+SamplesToDo, \ + out[i*numchans] = func(distbuf[i]*gain); \ + memmove(distbuf, distbuf+SamplesToDo, \ (base-SamplesToDo)*sizeof(ALfloat)); \ - memcpy(distcomp[j].Buffer+base-SamplesToDo, in, \ + memcpy(distbuf+base-SamplesToDo, in, \ SamplesToDo*sizeof(ALfloat)); \ } \ } \ @@ -1423,13 +1419,15 @@ void aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) voice_end = voice + ctx->VoiceCount; for(;voice != voice_end;++voice) { - ALboolean IsVoiceInit = ((*voice)->Step > 0); source = (*voice)->Source; - if(IsVoiceInit && source && - ATOMIC_LOAD(&source->state, almemory_order_relaxed) == AL_PLAYING) + if(source && ATOMIC_LOAD(&(*voice)->Playing, almemory_order_relaxed) && + (*voice)->Step > 0) { if(!MixSource(*voice, source, device, SamplesToDo)) + { (*voice)->Source = NULL; + ATOMIC_STORE(&(*voice)->Playing, false, almemory_order_release); + } } } @@ -1596,6 +1594,7 @@ void aluHandleDisconnect(ALCdevice *device) { ALsource *source = (*voice)->Source; (*voice)->Source = NULL; + ATOMIC_STORE(&(*voice)->Playing, false, almemory_order_release); if(source) { diff --git a/Alc/bformatdec.c b/Alc/bformatdec.c index a0aa4e44..92a2aecf 100644 --- a/Alc/bformatdec.c +++ b/Alc/bformatdec.c @@ -6,6 +6,7 @@ #include "mixer_defs.h" #include "alu.h" +#include "bool.h" #include "threads.h" #include "almalloc.h" @@ -181,7 +182,6 @@ typedef struct BFormatDec { ALsizei NumChannels; ALboolean DualBand; - ALboolean Periphonic; } BFormatDec; BFormatDec *bformatdec_alloc() @@ -204,29 +204,13 @@ void bformatdec_free(BFormatDec *dec) } } -int bformatdec_getOrder(const struct BFormatDec *dec) -{ - if(dec->Periphonic) - { - if(dec->NumChannels > 9) return 3; - if(dec->NumChannels > 4) return 2; - if(dec->NumChannels > 1) return 1; - } - else - { - if(dec->NumChannels > 5) return 3; - if(dec->NumChannels > 3) return 2; - if(dec->NumChannels > 1) return 1; - } - return 0; -} - void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount, ALuint srate, const ALsizei chanmap[MAX_OUTPUT_CHANNELS]) { static const ALsizei map2DTo3D[MAX_AMBI2D_COEFFS] = { 0, 1, 3, 4, 8, 9, 15 }; const ALfloat *coeff_scale = UnitScale; + bool periphonic; ALfloat ratio; ALsizei i; @@ -256,7 +240,7 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount bandsplit_init(&dec->UpSampler[i].XOver, ratio); if((conf->ChanMask&AMBI_PERIPHONIC_MASK)) { - dec->Periphonic = AL_TRUE; + periphonic = true; dec->UpSampler[0].Gains[FB_HighFreq] = (dec->NumChannels > 9) ? W_SCALE3D_THIRD : (dec->NumChannels > 4) ? W_SCALE3D_SECOND : 1.0f; @@ -270,7 +254,7 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount } else { - dec->Periphonic = AL_FALSE; + periphonic = false; dec->UpSampler[0].Gains[FB_HighFreq] = (dec->NumChannels > 5) ? W_SCALE2D_THIRD : (dec->NumChannels > 3) ? W_SCALE2D_SECOND : 1.0f; @@ -295,7 +279,7 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount ALfloat gain; ALsizei j, k; - if(!dec->Periphonic) + if(!periphonic) { for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++) { @@ -339,7 +323,7 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount ALfloat gain; ALsizei j, k; - if(!dec->Periphonic) + if(!periphonic) { for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++) { diff --git a/Alc/bformatdec.h b/Alc/bformatdec.h index 889d59f4..162f2652 100644 --- a/Alc/bformatdec.h +++ b/Alc/bformatdec.h @@ -28,7 +28,6 @@ struct AmbiUpsampler; struct BFormatDec *bformatdec_alloc(); void bformatdec_free(struct BFormatDec *dec); -int bformatdec_getOrder(const struct BFormatDec *dec); void bformatdec_reset(struct BFormatDec *dec, const struct AmbDecConf *conf, ALsizei chancount, ALuint srate, const ALsizei chanmap[MAX_OUTPUT_CHANNELS]); /* Decodes the ambisonic input to the given output channels. */ diff --git a/Alc/panning.c b/Alc/panning.c index 77f8e31b..c4d3e43f 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -616,6 +616,7 @@ static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const AL { const char *devname = al_string_get_cstr(device->DeviceName); ALfloat maxdist = 0.0f; + ALsizei total = 0; ALsizei i; for(i = 0;i < conf->NumSpeakers;i++) @@ -649,6 +650,21 @@ static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const AL al_string_get_cstr(conf->Speakers[i].Name), device->ChannelDelay[chan].Length, device->ChannelDelay[chan].Gain ); + + /* Round up to the next 4th sample, so each channel buffer starts + * 16-byte aligned. + */ + total += RoundUp(device->ChannelDelay[chan].Length, 4); + } + } + + if(total > 0) + { + device->ChannelDelay[0].Buffer = al_calloc(16, total * sizeof(ALfloat)); + for(i = 1;i < MAX_OUTPUT_CHANNELS;i++) + { + size_t len = RoundUp(device->ChannelDelay[i-1].Length, 4); + device->ChannelDelay[i].Buffer = device->ChannelDelay[i-1].Buffer + len; } } } @@ -775,7 +791,7 @@ static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALsiz ); bformatdec_reset(device->AmbiDecoder, conf, count, device->Frequency, speakermap); - if(bformatdec_getOrder(device->AmbiDecoder) < 2) + if(!(conf->ChanMask > 0xf)) { device->FOAOut.Ambi = device->Dry.Ambi; device->FOAOut.CoeffCount = device->Dry.CoeffCount; diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 23572a90..cc30dcef 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -29,6 +29,29 @@ #include "almalloc.h" #include "threads.h" +#ifndef ALC_SOFT_loopback2 +#define ALC_SOFT_loopback2 1 +#define ALC_AMBISONIC_LAYOUT_SOFT 0x1997 +#define ALC_AMBISONIC_SCALING_SOFT 0x1998 +#define ALC_AMBISONIC_ORDER_SOFT 0x1999 + +#define ALC_BFORMAT3D_SOFT 0x1508 + +/* Ambisonic layouts */ +#define ALC_ACN_SOFT 0x1600 +#define ALC_FUMA_SOFT 0x1601 + +/* Ambisonic scalings (normalization) */ +#define ALC_N3D_SOFT 0x1700 +#define ALC_SN3D_SOFT 0x1701 +/*#define ALC_FUMA_SOFT*/ + +typedef ALCboolean (ALC_APIENTRY*LPALCISAMBISONICFORMATSUPPORTEDSOFT)(ALCdevice *device, ALCenum layout, ALCenum scaling, ALsizei order); +#ifdef AL_ALEXT_PROTOTYPES +ALC_API ALCboolean ALC_APIENTRY alcIsAmbisonicFormatSupportedSOFT(ALCdevice *device, ALCenum layout, ALCenum scaling, ALsizei order); +#endif +#endif + #ifndef ALC_SOFT_device_clock #define ALC_SOFT_device_clock 1 typedef int64_t ALCint64SOFT; @@ -408,9 +431,6 @@ typedef struct { ALCboolean alc_ca_init(BackendFuncs *func_list); void alc_ca_deinit(void); void alc_ca_probe(enum DevProbe type); -ALCboolean alc_opensl_init(BackendFuncs *func_list); -void alc_opensl_deinit(void); -void alc_opensl_probe(enum DevProbe type); ALCboolean alc_qsa_init(BackendFuncs *func_list); void alc_qsa_deinit(void); void alc_qsa_probe(enum DevProbe type); @@ -511,16 +531,16 @@ inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType ty } enum AmbiLayout { - AmbiLayout_FuMa, /* FuMa channel order */ - AmbiLayout_ACN, /* ACN channel order */ + AmbiLayout_FuMa = ALC_FUMA_SOFT, /* FuMa channel order */ + AmbiLayout_ACN = ALC_ACN_SOFT, /* ACN channel order */ AmbiLayout_Default = AmbiLayout_ACN }; enum AmbiNorm { - AmbiNorm_FuMa, /* FuMa normalization */ - AmbiNorm_SN3D, /* SN3D normalization */ - AmbiNorm_N3D, /* N3D normalization */ + AmbiNorm_FuMa = ALC_FUMA_SOFT, /* FuMa normalization */ + AmbiNorm_SN3D = ALC_SN3D_SOFT, /* SN3D normalization */ + AmbiNorm_N3D = ALC_N3D_SOFT, /* N3D normalization */ AmbiNorm_Default = AmbiNorm_SN3D }; @@ -611,12 +631,12 @@ TYPEDEF_VECTOR(HrtfEntry, vector_HrtfEntry) /* Maximum delay in samples for speaker distance compensation. */ -#define MAX_DELAY_LENGTH 128 +#define MAX_DELAY_LENGTH 1024 typedef struct DistanceComp { ALfloat Gain; ALsizei Length; /* Valid range is [0...MAX_DELAY_LENGTH). */ - alignas(16) ALfloat Buffer[MAX_DELAY_LENGTH]; + ALfloat *Buffer; } DistanceComp; /* Size for temporary storage of buffer data, in ALfloats. Larger values need diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index f8a32f71..fc1756e5 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -1,13 +1,14 @@ #ifndef _AL_SOURCE_H_ #define _AL_SOURCE_H_ -#define MAX_SENDS 16 -#define DEFAULT_SENDS 2 - +#include "bool.h" #include "alMain.h" #include "alu.h" #include "hrtf.h" +#define MAX_SENDS 16 +#define DEFAULT_SENDS 2 + #ifdef __cplusplus extern "C" { #endif @@ -80,6 +81,7 @@ typedef struct ALvoice { struct ALsourceProps *Props; struct ALsource *Source; + ATOMIC(bool) Playing; /* Current buffer queue item being played. */ ATOMIC(ALbufferlistitem*) current_buffer; diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 40aa855c..14329bc2 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -1637,8 +1637,11 @@ AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) FreeThunkEntry(Source->id); ALCdevice_Lock(device); - voice = GetSourceVoice(Source, context); - if(voice) voice->Source = NULL; + if((voice=GetSourceVoice(Source, context)) != NULL) + { + voice->Source = NULL; + ATOMIC_STORE(&voice->Playing, false, almemory_order_release); + } ALCdevice_Unlock(device); DeinitSource(Source, device->NumAuxSends); @@ -2963,6 +2966,8 @@ void UpdateAllSourceProps(ALCcontext *context) */ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) { + ALCdevice *device = Context->Device; + ALuint refcount; ALvoice *voice; WriteLock(&Source->queue_lock); @@ -2994,11 +2999,12 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) { case AL_PLAYING: assert(voice != NULL); - /* A source that's already playing is restarted. */ + /* A source that's already playing is restarted from the beginning. */ ATOMIC_STORE(&voice->current_buffer, BufferList, almemory_order_relaxed); ATOMIC_STORE(&voice->position, 0, almemory_order_relaxed); ATOMIC_STORE(&voice->position_fraction, 0, almemory_order_release); - /* fall-through */ + goto done; + case AL_PAUSED: assert(voice != NULL); /* A source that's paused simply resumes. Make sure it uses the @@ -3006,12 +3012,16 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) * it stopped at. */ voice->Moving = AL_FALSE; + ATOMIC_STORE(&voice->Playing, true, almemory_order_release); goto done; default: break; } + Source->NeedsUpdate = AL_FALSE; + UpdateSourceProps(Source, device->NumAuxSends); + /* Make sure this source isn't already active, and if not, look for an * unused voice to put it in. */ @@ -3021,22 +3031,20 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) if(Context->Voices[i]->Source == NULL) { voice = Context->Voices[i]; - voice->Source = Source; break; } } if(voice == NULL) - { voice = Context->Voices[Context->VoiceCount++]; - voice->Source = Source; - } + ATOMIC_STORE(&voice->Playing, false, almemory_order_release); + ATOMIC_THREAD_FENCE(almemory_order_acquire); /* A source that's not playing or paused has any offset applied when it * starts playing. */ ATOMIC_STORE(&voice->current_buffer, BufferList, almemory_order_relaxed); ATOMIC_STORE(&voice->position, 0, almemory_order_relaxed); - ATOMIC_STORE(&voice->position_fraction, 0, almemory_order_release); + ATOMIC_STORE(&voice->position_fraction, 0, almemory_order_relaxed); if(Source->OffsetType != AL_NONE) ApplyOffset(Source, voice); @@ -3061,19 +3069,30 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) } } - Source->NeedsUpdate = AL_FALSE; - UpdateSourceProps(Source, device->NumAuxSends); + voice->Source = Source; + ATOMIC_STORE(&voice->Playing, true, almemory_order_release); } else if(state == AL_PAUSED) { ALenum playing = AL_PLAYING; + if((voice=GetSourceVoice(Source, Context)) != NULL) + { + ATOMIC_STORE(&voice->Playing, false, almemory_order_release); + while(((refcount=ATOMIC_LOAD(&device->MixCount, almemory_order_acquire))&1)) + althrd_yield(); + } ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALenum, &Source->state, &playing, AL_PAUSED); } else if(state == AL_STOPPED) { do_stop: - voice = GetSourceVoice(Source, Context); - if(voice) voice->Source = NULL; + if((voice=GetSourceVoice(Source, Context)) != NULL) + { + voice->Source = NULL; + ATOMIC_STORE(&voice->Playing, false, almemory_order_release); + while(((refcount=ATOMIC_LOAD(&device->MixCount, almemory_order_acquire))&1)) + althrd_yield(); + } if(ATOMIC_LOAD(&Source->state, almemory_order_acquire) != AL_INITIAL) ATOMIC_STORE(&Source->state, AL_STOPPED, almemory_order_relaxed); Source->OffsetType = AL_NONE; @@ -3081,8 +3100,13 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) } else if(state == AL_INITIAL) { - voice = GetSourceVoice(Source, Context); - if(voice) voice->Source = NULL; + if((voice=GetSourceVoice(Source, Context)) != NULL) + { + voice->Source = NULL; + ATOMIC_STORE(&voice->Playing, false, almemory_order_release); + while(((refcount=ATOMIC_LOAD(&device->MixCount, almemory_order_acquire))&1)) + althrd_yield(); + } if(ATOMIC_LOAD(&Source->state, almemory_order_acquire) != AL_INITIAL) ATOMIC_STORE(&Source->state, AL_INITIAL, almemory_order_relaxed); Source->OffsetType = AL_NONE; diff --git a/utils/alsoft-config/mainwindow.ui b/utils/alsoft-config/mainwindow.ui index 18392430..806b0ce0 100644 --- a/utils/alsoft-config/mainwindow.ui +++ b/utils/alsoft-config/mainwindow.ui @@ -635,9 +635,9 @@ configuration file.</string> <widget class="QLineEdit" name="decoderQuadLineEdit"> <property name="geometry"> <rect> - <x>150</x> + <x>120</x> <y>30</y> - <width>281</width> + <width>311</width> <height>21</height> </rect> </property> @@ -647,7 +647,7 @@ configuration file.</string> <rect> <x>20</x> <y>30</y> - <width>121</width> + <width>91</width> <height>21</height> </rect> </property> @@ -674,9 +674,9 @@ configuration file.</string> <widget class="QLineEdit" name="decoder51LineEdit"> <property name="geometry"> <rect> - <x>150</x> + <x>120</x> <y>60</y> - <width>281</width> + <width>311</width> <height>21</height> </rect> </property> @@ -699,7 +699,7 @@ configuration file.</string> <rect> <x>20</x> <y>60</y> - <width>121</width> + <width>91</width> <height>21</height> </rect> </property> @@ -715,7 +715,7 @@ configuration file.</string> <rect> <x>20</x> <y>90</y> - <width>121</width> + <width>91</width> <height>21</height> </rect> </property> @@ -729,9 +729,9 @@ configuration file.</string> <widget class="QLineEdit" name="decoder61LineEdit"> <property name="geometry"> <rect> - <x>150</x> + <x>120</x> <y>90</y> - <width>281</width> + <width>311</width> <height>21</height> </rect> </property> @@ -765,9 +765,9 @@ configuration file.</string> <widget class="QLineEdit" name="decoder71LineEdit"> <property name="geometry"> <rect> - <x>150</x> + <x>120</x> <y>120</y> - <width>281</width> + <width>311</width> <height>21</height> </rect> </property> @@ -777,7 +777,7 @@ configuration file.</string> <rect> <x>20</x> <y>120</y> - <width>121</width> + <width>91</width> <height>21</height> </rect> </property> |