diff options
-rw-r--r-- | Alc/alc.cpp | 351 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 2 |
2 files changed, 145 insertions, 208 deletions
diff --git a/Alc/alc.cpp b/Alc/alc.cpp index 2a76c846..142ee4d2 100644 --- a/Alc/alc.cpp +++ b/Alc/alc.cpp @@ -1599,10 +1599,15 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) ALCuint oldFreq; int val; + if((!attrList || !attrList[0]) && device->Type == Loopback) + { + WARN("Missing attributes for loopback device\n"); + return ALC_INVALID_VALUE; + } + // Check for attributes - if(device->Type == Loopback) + if(attrList && attrList[0]) { - ALCsizei numMono, numStereo, numSends; ALCenum alayout = AL_NONE; ALCenum ascale = AL_NONE; ALCenum schans = AL_NONE; @@ -1611,120 +1616,124 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) ALCsizei aorder = 0; ALCuint freq = 0; - if(!attrList) + const char *devname{nullptr}; + const bool loopback{device->Type == Loopback}; + if(!loopback) { - WARN("Missing attributes for loopback device\n"); - return ALC_INVALID_VALUE; + devname = device->DeviceName.c_str(); + /* If a context is already running on the device, stop playback so + * the device attributes can be updated. + */ + if((device->Flags&DEVICE_RUNNING)) + V0(device->Backend,stop)(); + device->Flags &= ~DEVICE_RUNNING; } - numMono = device->NumMonoSources; - numStereo = device->NumStereoSources; - numSends = old_sends; + auto numMono = static_cast<ALsizei>(device->NumMonoSources); + auto numStereo = static_cast<ALsizei>(device->NumStereoSources); + auto numSends = ALsizei{old_sends}; -#define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v) +#define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v) while(attrList[attrIdx]) { switch(attrList[attrIdx]) { - case ALC_FORMAT_CHANNELS_SOFT: - schans = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans); - if(!IsValidALCChannels(schans)) - return ALC_INVALID_VALUE; - break; + case ALC_FORMAT_CHANNELS_SOFT: + schans = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, schans); + break; - case ALC_FORMAT_TYPE_SOFT: - stype = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype); - if(!IsValidALCType(stype)) - return ALC_INVALID_VALUE; - break; + case ALC_FORMAT_TYPE_SOFT: + stype = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, stype); + break; - case ALC_FREQUENCY: - freq = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_FREQUENCY, freq); - if(freq < MIN_OUTPUT_RATE) - return ALC_INVALID_VALUE; - break; + case ALC_FREQUENCY: + freq = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_FREQUENCY, freq); + break; - case ALC_AMBISONIC_LAYOUT_SOFT: - alayout = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout); - if(!IsValidAmbiLayout(alayout)) - return ALC_INVALID_VALUE; - break; + case ALC_AMBISONIC_LAYOUT_SOFT: + alayout = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT, alayout); + break; - case ALC_AMBISONIC_SCALING_SOFT: - ascale = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale); - if(!IsValidAmbiScaling(ascale)) - return ALC_INVALID_VALUE; - break; + case ALC_AMBISONIC_SCALING_SOFT: + ascale = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT, ascale); + break; - case 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; - break; + case ALC_AMBISONIC_ORDER_SOFT: + aorder = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT, aorder); + break; - case ALC_MONO_SOURCES: - numMono = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_MONO_SOURCES, numMono); - numMono = maxi(numMono, 0); - break; + case ALC_MONO_SOURCES: + numMono = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_MONO_SOURCES, numMono); + numMono = maxi(numMono, 0); + break; - case ALC_STEREO_SOURCES: - numStereo = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_STEREO_SOURCES, numStereo); - numStereo = maxi(numStereo, 0); - break; + case ALC_STEREO_SOURCES: + numStereo = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_STEREO_SOURCES, numStereo); + numStereo = maxi(numStereo, 0); + break; - case ALC_MAX_AUXILIARY_SENDS: - numSends = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends); - numSends = clampi(numSends, 0, MAX_SENDS); - break; + case ALC_MAX_AUXILIARY_SENDS: + numSends = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends); + numSends = clampi(numSends, 0, MAX_SENDS); + break; - case ALC_HRTF_SOFT: - TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]); - if(attrList[attrIdx + 1] == ALC_FALSE) - hrtf_appreq = Hrtf_Disable; - else if(attrList[attrIdx + 1] == ALC_TRUE) - hrtf_appreq = Hrtf_Enable; - else - hrtf_appreq = Hrtf_Default; - break; + case ALC_HRTF_SOFT: + TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]); + if(attrList[attrIdx + 1] == ALC_FALSE) + hrtf_appreq = Hrtf_Disable; + else if(attrList[attrIdx + 1] == ALC_TRUE) + hrtf_appreq = Hrtf_Enable; + else + hrtf_appreq = Hrtf_Default; + break; - case ALC_HRTF_ID_SOFT: - hrtf_id = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id); - break; + case ALC_HRTF_ID_SOFT: + hrtf_id = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id); + break; - case ALC_OUTPUT_LIMITER_SOFT: - gainLimiter = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter); - break; + case ALC_OUTPUT_LIMITER_SOFT: + gainLimiter = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter); + break; - default: - TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList[attrIdx], - attrList[attrIdx + 1], attrList[attrIdx + 1]); - break; + default: + TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx], + attrList[attrIdx + 1], attrList[attrIdx + 1]); + break; } attrIdx += 2; } #undef TRACE_ATTR - if(!schans || !stype || !freq) + if(loopback) { - 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(!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(!IsValidALCChannels(schans) || !IsValidALCType(stype) || freq < MIN_OUTPUT_RATE) + return ALC_INVALID_VALUE; + if(!IsValidAmbiLayout(alayout) || !IsValidAmbiScaling(ascale)) + return ALC_INVALID_VALUE; + if(aorder < 1 || aorder > MAX_AMBI_ORDER) + return ALC_INVALID_VALUE; } if((device->Flags&DEVICE_RUNNING)) @@ -1733,131 +1742,52 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) UpdateClockBase(device); - device->Frequency = freq; - device->FmtChans = static_cast<enum DevFmtChannels>(schans); - device->FmtType = static_cast<enum DevFmtType>(stype); - if(schans == ALC_BFORMAT3D_SOFT) - { - device->mAmbiOrder = aorder; - device->mAmbiLayout = static_cast<AmbiLayout>(alayout); - device->mAmbiScale = static_cast<AmbiNorm>(ascale); - } - - if(numMono > INT_MAX-numStereo) - numMono = INT_MAX-numStereo; - numMono += numStereo; - if(ConfigValueInt(nullptr, nullptr, "sources", &numMono)) + if(!loopback) { - if(numMono <= 0) - numMono = 256; - } - else - numMono = maxi(numMono, 256); - numStereo = mini(numStereo, numMono); - numMono -= numStereo; - device->SourcesMax = numMono + numStereo; - - device->NumMonoSources = numMono; - device->NumStereoSources = numStereo; + device->NumUpdates = DEFAULT_NUM_UPDATES; + device->UpdateSize = DEFAULT_UPDATE_SIZE; + device->Frequency = DEFAULT_OUTPUT_RATE; - if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends)) - new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS)); - else - new_sends = numSends; - } - else if(attrList && attrList[0]) - { - ALCsizei numMono, numStereo, numSends; - ALCsizei attrIdx = 0; - ALCuint freq; + ConfigValueUInt(devname, nullptr, "frequency", &freq); + if(freq < 1) + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; + else + { + freq = maxi(freq, MIN_OUTPUT_RATE); - /* If a context is already running on the device, stop playback so the - * device attributes can be updated. */ - if((device->Flags&DEVICE_RUNNING)) - V0(device->Backend,stop)(); - device->Flags &= ~DEVICE_RUNNING; + device->NumUpdates = (device->NumUpdates*freq + device->NumUpdates/2) / + device->Frequency; - UpdateClockBase(device); + device->Frequency = freq; + device->Flags |= DEVICE_FREQUENCY_REQUEST; + } - freq = device->Frequency; - numMono = device->NumMonoSources; - numStereo = device->NumStereoSources; - numSends = old_sends; + ConfigValueUInt(devname, nullptr, "periods", &device->NumUpdates); + device->NumUpdates = clampu(device->NumUpdates, 2, 16); -#define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v) - while(attrList[attrIdx]) + ConfigValueUInt(devname, nullptr, "period_size", &device->UpdateSize); + device->UpdateSize = clampu(device->UpdateSize, 64, 8192); + /* 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+3u)&~3u; + } + else { - switch(attrList[attrIdx]) + device->Frequency = freq; + device->FmtChans = static_cast<enum DevFmtChannels>(schans); + device->FmtType = static_cast<enum DevFmtType>(stype); + if(schans == ALC_BFORMAT3D_SOFT) { - case ALC_FREQUENCY: - freq = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_FREQUENCY, freq); - device->Flags |= DEVICE_FREQUENCY_REQUEST; - break; - - case ALC_MONO_SOURCES: - numMono = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_MONO_SOURCES, numMono); - numMono = maxi(numMono, 0); - break; - - case ALC_STEREO_SOURCES: - numStereo = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_STEREO_SOURCES, numStereo); - numStereo = maxi(numStereo, 0); - break; - - case ALC_MAX_AUXILIARY_SENDS: - numSends = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends); - numSends = clampi(numSends, 0, MAX_SENDS); - break; - - case ALC_HRTF_SOFT: - TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]); - if(attrList[attrIdx + 1] == ALC_FALSE) - hrtf_appreq = Hrtf_Disable; - else if(attrList[attrIdx + 1] == ALC_TRUE) - hrtf_appreq = Hrtf_Enable; - else - hrtf_appreq = Hrtf_Default; - break; - - case ALC_HRTF_ID_SOFT: - hrtf_id = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id); - break; - - case ALC_OUTPUT_LIMITER_SOFT: - gainLimiter = attrList[attrIdx + 1]; - TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT, gainLimiter); - break; - - default: - TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx], - attrList[attrIdx + 1], attrList[attrIdx + 1]); - break; + device->mAmbiOrder = aorder; + device->mAmbiLayout = static_cast<AmbiLayout>(alayout); + device->mAmbiScale = static_cast<AmbiNorm>(ascale); } - - attrIdx += 2; } -#undef TRACE_ATTR - - ConfigValueUInt(device->DeviceName.c_str(), nullptr, "frequency", &freq); - freq = maxu(freq, MIN_OUTPUT_RATE); - - device->UpdateSize = (ALuint64)device->UpdateSize * freq / - device->Frequency; - /* 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; - - device->Frequency = freq; if(numMono > INT_MAX-numStereo) numMono = INT_MAX-numStereo; numMono += numStereo; - if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sources", &numMono)) + if(ConfigValueInt(devname, nullptr, "sources", &numMono)) { if(numMono <= 0) numMono = 256; @@ -1871,7 +1801,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) device->NumMonoSources = numMono; device->NumStereoSources = numStereo; - if(ConfigValueInt(device->DeviceName.c_str(), nullptr, "sends", &new_sends)) + if(ConfigValueInt(devname, nullptr, "sends", &new_sends)) new_sends = mini(numSends, clampi(new_sends, 0, MAX_SENDS)); else new_sends = numSends; @@ -3711,9 +3641,9 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) device->FmtChans = DevFmtChannelsDefault; device->FmtType = DevFmtTypeDefault; device->Frequency = DEFAULT_OUTPUT_RATE; + device->UpdateSize = DEFAULT_UPDATE_SIZE; + device->NumUpdates = DEFAULT_NUM_UPDATES; device->LimiterState = ALC_TRUE; - device->NumUpdates = 3; - device->UpdateSize = 1024; device->SourcesMax = 256; device->AuxiliaryEffectSlotMax = 64; @@ -3780,12 +3710,17 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) } } - if(ConfigValueUInt(deviceName, nullptr, "frequency", &device->Frequency)) + ALuint freq{}; + if(ConfigValueUInt(deviceName, nullptr, "frequency", &freq) && freq > 0) { + if(freq < MIN_OUTPUT_RATE) + { + ERR("%uhz request clamped to %uhz minimum\n", freq, MIN_OUTPUT_RATE); + freq = MIN_OUTPUT_RATE; + } + device->NumUpdates = (device->NumUpdates*freq + device->Frequency/2) / device->Frequency; + device->Frequency = freq; device->Flags |= DEVICE_FREQUENCY_REQUEST; - if(device->Frequency < MIN_OUTPUT_RATE) - ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE); - device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE); } ConfigValueUInt(deviceName, nullptr, "periods", &device->NumUpdates); @@ -3794,7 +3729,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) ConfigValueUInt(deviceName, nullptr, "period_size", &device->UpdateSize); device->UpdateSize = clampu(device->UpdateSize, 64, 8192); if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0) - device->UpdateSize = (device->UpdateSize+3)&~3; + device->UpdateSize = (device->UpdateSize+3u)&~3u; ConfigValueUInt(deviceName, nullptr, "sources", &device->SourcesMax); if(device->SourcesMax == 0) device->SourcesMax = 256; diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 9d2e7bfc..b4fc67dd 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -252,6 +252,8 @@ class AmbiUpsampler; struct bs2b; +#define DEFAULT_UPDATE_SIZE (1024) +#define DEFAULT_NUM_UPDATES (3) #define DEFAULT_OUTPUT_RATE (44100) #define MIN_OUTPUT_RATE (8000) |