From 75f3e34951f165a523825472dc22bfc557277a00 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 24 Apr 2023 11:05:21 -0700 Subject: Try to detect headphones with CoreAudio --- alc/backends/coreaudio.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'alc') diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index 8b0e75fd..86f58637 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -388,6 +388,24 @@ void CoreAudioPlayback::open(const char *name) if(!devname.empty()) mDevice->DeviceName = std::move(devname); else mDevice->DeviceName = "Unknown Device Name"; } + + if(audioDevice != kAudioDeviceUnknown) + { + UInt32 type{}; + err = GetDevProperty(audioDevice, kAudioDevicePropertyTransportType, false, + kAudioObjectPropertyElementMaster, sizeof(type), &type); + if(err != noErr) + ERR("Failed to get audio device type: %u\n", err); + else + { + static constexpr UInt32 HeadphoneType{('h'<<24u) | ('d'<<16u) | ('p'<<8u) | 'n'}; + TRACE("Got device type '%c%c%c%c'\n", static_cast((type>>24)&0xff), + static_cast((type>>16)&0xff), static_cast((type>>8)&0xff), + static_cast(type&0xff)); + mDevice->Flags.set(DirectEar, (type == HeadphoneType)); + } + } + #else mDevice->DeviceName = name; #endif -- cgit v1.2.3 From aefc514ef6d1ab94ec595f5042dcbb3107f77dc9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 25 Apr 2023 00:46:41 -0700 Subject: Check the correct device property to detect headphones --- alc/backends/coreaudio.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'alc') diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index 86f58637..6a8003d2 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -41,6 +41,7 @@ #include #include +#include namespace { @@ -392,17 +393,16 @@ void CoreAudioPlayback::open(const char *name) if(audioDevice != kAudioDeviceUnknown) { UInt32 type{}; - err = GetDevProperty(audioDevice, kAudioDevicePropertyTransportType, false, + err = GetDevProperty(audioDevice, kAudioDevicePropertyDataSource, false, kAudioObjectPropertyElementMaster, sizeof(type), &type); if(err != noErr) ERR("Failed to get audio device type: %u\n", err); else { - static constexpr UInt32 HeadphoneType{('h'<<24u) | ('d'<<16u) | ('p'<<8u) | 'n'}; TRACE("Got device type '%c%c%c%c'\n", static_cast((type>>24)&0xff), static_cast((type>>16)&0xff), static_cast((type>>8)&0xff), static_cast(type&0xff)); - mDevice->Flags.set(DirectEar, (type == HeadphoneType)); + mDevice->Flags.set(DirectEar, (type == kIOAudioOutputPortSubTypeHeadphones)); } } -- cgit v1.2.3 From e3d5c9f69cba4db2b5d4c0512a1132a83d3ce5d4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 26 Apr 2023 17:33:41 -0700 Subject: Print CoreAudio errors as FourCC codes when possible --- alc/backends/coreaudio.cpp | 101 ++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 43 deletions(-) (limited to 'alc') diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index 6a8003d2..d11bcf6f 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -55,6 +55,27 @@ namespace { constexpr auto OutputElement = 0; constexpr auto InputElement = 1; +struct FourCCPrinter { + char mString[sizeof(UInt32) + 1]{}; + + constexpr FourCCPrinter(UInt32 code) noexcept + { + for(size_t i{0};i < sizeof(UInt32);++i) + { + const auto ch = static_cast(code & 0xff); + /* If this breaks early it'll leave the first byte null, to get + * read as a 0-length string. + */ + if(ch <= 0x1f || ch >= 0x7f) + break; + mString[sizeof(UInt32)-1-i] = ch; + code >>= 8; + } + } + + constexpr const char *c_str() const noexcept { return mString; } +}; + #if CAN_ENUMERATE struct DeviceEntry { AudioDeviceID mId; @@ -148,7 +169,8 @@ UInt32 GetDeviceChannelCount(AudioDeviceID devId, bool isCapture) &propSize); if(err) { - ERR("kAudioDevicePropertyStreamConfiguration size query failed: %u\n", err); + ERR("kAudioDevicePropertyStreamConfiguration size query failed: '%s' (%u)\n", + FourCCPrinter{err}.c_str(), err); return 0; } @@ -159,7 +181,8 @@ UInt32 GetDeviceChannelCount(AudioDeviceID devId, bool isCapture) buflist); if(err) { - ERR("kAudioDevicePropertyStreamConfiguration query failed: %u\n", err); + ERR("kAudioDevicePropertyStreamConfiguration query failed: '%s' (%u)\n", + FourCCPrinter{err}.c_str(), err); return 0; } @@ -183,7 +206,7 @@ void EnumerateDevices(std::vector &list, bool isCapture) auto devIds = std::vector(propSize/sizeof(AudioDeviceID), kAudioDeviceUnknown); if(auto err = GetHwProperty(kAudioHardwarePropertyDevices, propSize, devIds.data())) { - ERR("Failed to get device list: %u\n", err); + ERR("Failed to get device list: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); return; } @@ -261,13 +284,6 @@ struct CoreAudioPlayback final : public BackendBase { OSStatus MixerProc(AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) noexcept; - static OSStatus MixerProcC(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, - AudioBufferList *ioData) noexcept - { - return static_cast(inRefCon)->MixerProc(ioActionFlags, inTimeStamp, - inBusNumber, inNumberFrames, ioData); - } void open(const char *name) override; bool reset() override; @@ -352,7 +368,7 @@ void CoreAudioPlayback::open(const char *name) OSStatus err{AudioComponentInstanceNew(comp, &audioUnit)}; if(err != noErr) throw al::backend_exception{al::backend_error::NoDevice, - "Could not create component instance: %u", err}; + "Could not create component instance: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; #if CAN_ENUMERATE if(audioDevice != kAudioDeviceUnknown) @@ -363,7 +379,7 @@ void CoreAudioPlayback::open(const char *name) err = AudioUnitInitialize(audioUnit); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not initialize audio unit: %u", err}; + "Could not initialize audio unit: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; /* WARNING: I don't know if "valid" audio unit values are guaranteed to be * non-0. If not, this logic is broken. @@ -399,9 +415,7 @@ void CoreAudioPlayback::open(const char *name) ERR("Failed to get audio device type: %u\n", err); else { - TRACE("Got device type '%c%c%c%c'\n", static_cast((type>>24)&0xff), - static_cast((type>>16)&0xff), static_cast((type>>8)&0xff), - static_cast(type&0xff)); + TRACE("Got device type '%s'\n", FourCCPrinter{type}.c_str()); mDevice->Flags.set(DirectEar, (type == kIOAudioOutputPortSubTypeHeadphones)); } } @@ -415,7 +429,7 @@ bool CoreAudioPlayback::reset() { OSStatus err{AudioUnitUninitialize(mAudioUnit)}; if(err != noErr) - ERR("-- AudioUnitUninitialize failed.\n"); + ERR("AudioUnitUninitialize failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); /* retrieve default output unit's properties (output side) */ AudioStreamBasicDescription streamFormat{}; @@ -424,7 +438,8 @@ bool CoreAudioPlayback::reset() OutputElement, &streamFormat, &size); if(err != noErr || size != sizeof(streamFormat)) { - ERR("AudioUnitGetProperty failed\n"); + ERR("AudioUnitGetProperty(StreamFormat) failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), + err); return false; } @@ -491,7 +506,8 @@ bool CoreAudioPlayback::reset() OutputElement, &streamFormat, sizeof(streamFormat)); if(err != noErr) { - ERR("AudioUnitSetProperty failed\n"); + ERR("AudioUnitSetProperty(StreamFormat) failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), + err); return false; } @@ -500,14 +516,16 @@ bool CoreAudioPlayback::reset() /* setup callback */ mFrameSize = mDevice->frameSizeFromFmt(); AURenderCallbackStruct input{}; - input.inputProc = CoreAudioPlayback::MixerProcC; + input.inputProc = [](void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) noexcept + { return static_cast(inRefCon)->MixerProc(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData); }; input.inputProcRefCon = this; err = AudioUnitSetProperty(mAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, OutputElement, &input, sizeof(AURenderCallbackStruct)); if(err != noErr) { - ERR("AudioUnitSetProperty failed\n"); + ERR("AudioUnitSetProperty(SetRenderCallback) failed: '%s' (%u)\n", + FourCCPrinter{err}.c_str(), err); return false; } @@ -515,7 +533,7 @@ bool CoreAudioPlayback::reset() err = AudioUnitInitialize(mAudioUnit); if(err != noErr) { - ERR("AudioUnitInitialize failed\n"); + ERR("AudioUnitInitialize failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); return false; } @@ -527,14 +545,14 @@ void CoreAudioPlayback::start() const OSStatus err{AudioOutputUnitStart(mAudioUnit)}; if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "AudioOutputUnitStart failed: %d", err}; + "AudioOutputUnitStart failed: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; } void CoreAudioPlayback::stop() { OSStatus err{AudioOutputUnitStop(mAudioUnit)}; if(err != noErr) - ERR("AudioOutputUnitStop failed\n"); + ERR("AudioOutputUnitStop failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); } @@ -545,13 +563,6 @@ struct CoreAudioCapture final : public BackendBase { OSStatus RecordProc(AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) noexcept; - static OSStatus RecordProcC(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, - const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, - AudioBufferList *ioData) noexcept - { - return static_cast(inRefCon)->RecordProc(ioActionFlags, inTimeStamp, - inBusNumber, inNumberFrames, ioData); - } void open(const char *name) override; void start() override; @@ -599,7 +610,7 @@ OSStatus CoreAudioCapture::RecordProc(AudioUnitRenderActionFlags *ioActionFlags, inNumberFrames, &audiobuf.list)}; if(err != noErr) { - ERR("AudioUnitRender capture error: %d\n", err); + ERR("AudioUnitRender capture error: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); return err; } @@ -658,7 +669,7 @@ void CoreAudioCapture::open(const char *name) OSStatus err{AudioComponentInstanceNew(comp, &mAudioUnit)}; if(err != noErr) throw al::backend_exception{al::backend_error::NoDevice, - "Could not create component instance: %u", err}; + "Could not create component instance: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; // Turn off AudioUnit output UInt32 enableIO{0}; @@ -666,7 +677,8 @@ void CoreAudioCapture::open(const char *name) kAudioUnitScope_Output, OutputElement, &enableIO, sizeof(enableIO)); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not disable audio unit output property: %u", err}; + "Could not disable audio unit output property: '%s' (%u)", FourCCPrinter{err}.c_str(), + err}; // Turn on AudioUnit input enableIO = 1; @@ -674,7 +686,8 @@ void CoreAudioCapture::open(const char *name) kAudioUnitScope_Input, InputElement, &enableIO, sizeof(enableIO)); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not enable audio unit input property: %u", err}; + "Could not enable audio unit input property: '%s' (%u)", FourCCPrinter{err}.c_str(), + err}; #if CAN_ENUMERATE if(audioDevice != kAudioDeviceUnknown) @@ -684,14 +697,15 @@ void CoreAudioCapture::open(const char *name) // set capture callback AURenderCallbackStruct input{}; - input.inputProc = CoreAudioCapture::RecordProcC; + input.inputProc = [](void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) noexcept + { return static_cast(inRefCon)->RecordProc(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData); }; input.inputProcRefCon = this; err = AudioUnitSetProperty(mAudioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, InputElement, &input, sizeof(AURenderCallbackStruct)); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not set capture callback: %u", err}; + "Could not set capture callback: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; // Disable buffer allocation for capture UInt32 flag{0}; @@ -699,13 +713,14 @@ void CoreAudioCapture::open(const char *name) kAudioUnitScope_Output, InputElement, &flag, sizeof(flag)); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not disable buffer allocation property: %u", err}; + "Could not disable buffer allocation property: '%s' (%u)", FourCCPrinter{err}.c_str(), + err}; // Initialize the device err = AudioUnitInitialize(mAudioUnit); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not initialize audio unit: %u", err}; + "Could not initialize audio unit: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; // Get the hardware format AudioStreamBasicDescription hardwareFormat{}; @@ -714,7 +729,7 @@ void CoreAudioCapture::open(const char *name) InputElement, &hardwareFormat, &propertySize); if(err != noErr || propertySize != sizeof(hardwareFormat)) throw al::backend_exception{al::backend_error::DeviceError, - "Could not get input format: %u", err}; + "Could not get input format: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; // Set up the requested format description AudioStreamBasicDescription requestedFormat{}; @@ -795,7 +810,7 @@ void CoreAudioCapture::open(const char *name) InputElement, &outputFormat, sizeof(outputFormat)); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not set input format: %u", err}; + "Could not set input format: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; /* Calculate the minimum AudioUnit output format frame count for the pre- * conversion ring buffer. Ensure at least 100ms for the total buffer. @@ -814,7 +829,7 @@ void CoreAudioCapture::open(const char *name) kAudioUnitScope_Global, OutputElement, &outputFrameCount, &propertySize); if(err != noErr || propertySize != sizeof(outputFrameCount)) throw al::backend_exception{al::backend_error::DeviceError, - "Could not get input frame count: %u", err}; + "Could not get input frame count: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; mCaptureData.resize(outputFrameCount * mFrameSize); @@ -852,14 +867,14 @@ void CoreAudioCapture::start() OSStatus err{AudioOutputUnitStart(mAudioUnit)}; if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "AudioOutputUnitStart failed: %d", err}; + "AudioOutputUnitStart failed: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; } void CoreAudioCapture::stop() { OSStatus err{AudioOutputUnitStop(mAudioUnit)}; if(err != noErr) - ERR("AudioOutputUnitStop failed\n"); + ERR("AudioOutputUnitStop failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); } void CoreAudioCapture::captureSamples(al::byte *buffer, uint samples) -- cgit v1.2.3 From ac143e1236319ea087388ff48a178930c0dbaf47 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 26 Apr 2023 17:40:18 -0700 Subject: Handle signed int values holding FourCC codes --- alc/backends/coreaudio.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'alc') diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index d11bcf6f..ae220d7a 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -72,6 +72,7 @@ struct FourCCPrinter { code >>= 8; } } + constexpr FourCCPrinter(int code) noexcept : FourCCPrinter{static_cast(code)} { } constexpr const char *c_str() const noexcept { return mString; } }; -- cgit v1.2.3 From 102789d4487a8dbbb13a131dde3d21a612e86adb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 28 Apr 2023 22:28:32 -0700 Subject: Unset sLocalContext when releasing it --- alc/context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/context.cpp b/alc/context.cpp index e02c549b..008c2bf4 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -93,7 +93,7 @@ std::atomic ALCcontext::sGlobalContext{nullptr}; thread_local ALCcontext *ALCcontext::sLocalContext{nullptr}; ALCcontext::ThreadCtx::~ThreadCtx() { - if(ALCcontext *ctx{ALCcontext::sLocalContext}) + if(ALCcontext *ctx{std::exchange(ALCcontext::sLocalContext, nullptr)}) { const bool result{ctx->releaseIfNoDelete()}; ERR("Context %p current for thread being destroyed%s!\n", voidp{ctx}, -- cgit v1.2.3 From a35211e2c1dc53e47c4a300366d22a27fb046a8c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 29 Apr 2023 19:18:06 -0700 Subject: Start a debug API extension --- al/error.cpp | 11 ++++++-- al/state.cpp | 38 +++++++++++++++++++++++++--- alc/alc.cpp | 4 +++ alc/context.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- alc/context.h | 41 ++++++++++++++++++++++++++++++ alc/inprogext.h | 31 +++++++++++++++++++++++ 6 files changed, 196 insertions(+), 7 deletions(-) (limited to 'alc') diff --git a/al/error.cpp b/al/error.cpp index afa7019a..70081a2e 100644 --- a/al/error.cpp +++ b/al/error.cpp @@ -61,8 +61,13 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...) va_end(args2); va_end(args); - if(msglen >= 0) msg = message.data(); - else msg = ""; + if(msglen >= 0) + msg = message.data(); + else + { + msg = ""; + msglen = static_cast(strlen(msg)); + } WARN("Error generated on context %p, code 0x%04x, \"%s\"\n", decltype(std::declval()){this}, errorCode, msg); @@ -79,6 +84,8 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...) ALenum curerr{AL_NO_ERROR}; mLastError.compare_exchange_strong(curerr, errorCode); + + debugMessage(DebugSource::API, DebugType::Error, 0, DebugSeverity::High, msglen, msg); } AL_API ALenum AL_APIENTRY alGetError(void) diff --git a/al/state.cpp b/al/state.cpp index 86d81b13..fc9acb25 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -170,6 +170,10 @@ START_API_FUNC } break; + case AL_DEBUG_OUTPUT_SOFT: + context->mDebugEnabled = true; + break; + case AL_STOP_SOURCES_ON_DISCONNECT_SOFT: context->setError(AL_INVALID_OPERATION, "Re-enabling AL_STOP_SOURCES_ON_DISCONNECT_SOFT not yet supported"); break; @@ -196,6 +200,10 @@ START_API_FUNC } break; + case AL_DEBUG_OUTPUT_SOFT: + context->mDebugEnabled = false; + break; + case AL_STOP_SOURCES_ON_DISCONNECT_SOFT: context->mStopVoicesOnDisconnect = false; break; @@ -220,6 +228,10 @@ START_API_FUNC value = context->mSourceDistanceModel ? AL_TRUE : AL_FALSE; break; + case AL_DEBUG_OUTPUT_SOFT: + value = context->mDebugEnabled ? AL_TRUE : AL_FALSE; + break; + case AL_STOP_SOURCES_ON_DISCONNECT_SOFT: value = context->mStopVoicesOnDisconnect ? AL_TRUE : AL_FALSE; break; @@ -546,6 +558,14 @@ START_API_FUNC value = context->mEventParam; break; + case AL_DEBUG_CALLBACK_FUNCTION_SOFT: + value = reinterpret_cast(context->mDebugCb); + break; + + case AL_DEBUG_CALLBACK_USER_PARAM_SOFT: + value = context->mDebugParam; + break; + default: context->setError(AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname); } @@ -726,10 +746,12 @@ START_API_FUNC { switch(pname) { - case AL_EVENT_CALLBACK_FUNCTION_SOFT: - case AL_EVENT_CALLBACK_USER_PARAM_SOFT: - values[0] = alGetPointerSOFT(pname); - return; + case AL_EVENT_CALLBACK_FUNCTION_SOFT: + case AL_EVENT_CALLBACK_USER_PARAM_SOFT: + case AL_DEBUG_CALLBACK_FUNCTION_SOFT: + case AL_DEBUG_CALLBACK_USER_PARAM_SOFT: + values[0] = alGetPointerSOFT(pname); + return; } } @@ -825,6 +847,14 @@ START_API_FUNC ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; + if(context->mDebugEnabled.load(std::memory_order_relaxed)) + { + static constexpr char deprecatedMessage[] = "alDopplerVelocity is deprecated in AL 1.1"; + context->sendDebugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + DebugSeverity::Medium, static_cast(std::strlen(deprecatedMessage)), + deprecatedMessage); + } + if(!(value >= 0.0f && std::isfinite(value))) context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value); else diff --git a/alc/alc.cpp b/alc/alc.cpp index af8ff55d..0ed0ae58 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -459,6 +459,8 @@ const struct { DECL(alBufferSubDataSOFT), DECL(alBufferDataStatic), + + DECL(alDebugMessageCallbackSOFT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), @@ -915,6 +917,8 @@ constexpr struct { DECL(AL_FORMAT_UHJ4CHN_MULAW_SOFT), DECL(AL_FORMAT_UHJ4CHN_ALAW_SOFT), + DECL(AL_DEBUG_OUTPUT_SOFT), + DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), #ifdef ALSOFT_EAX diff --git a/alc/context.cpp b/alc/context.cpp index 008c2bf4..e2a2e2d2 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -113,7 +113,7 @@ void ALCcontext::setThreadContext(ALCcontext *context) noexcept #endif ALCcontext::ALCcontext(al::intrusive_ptr device) - : ContextBase{device.get()}, mALDevice{std::move(device)} + : ContextBase{device.get()}, mALDevice{std::move(device)} { } @@ -295,6 +295,82 @@ void ALCcontext::applyAllUpdates() mHoldUpdates.store(false, std::memory_order_release); } +void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, + DebugSeverity severity, ALsizei length, const char *message) +{ + std::lock_guard _{mDebugCbLock}; + if(!mDebugEnabled.load()) + return; + + if(mDebugCb) + mDebugCb(al::to_underlying(source), al::to_underlying(type), id, + al::to_underlying(severity), length, message, mDebugParam); + else + { + /* TODO: Store in a log. */ + } +} + +FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + std::lock_guard _{context->mDebugCbLock}; + context->mDebugCb = callback; + context->mDebugParam = userParam; +} + +FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type, ALuint id, + ALenum severity, ALsizei length, const ALchar *message) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + if(!message) + return context->setError(AL_INVALID_VALUE, "Null message pointer"); + + DebugSource dsource{}; + switch(source) + { + case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: dsource = DebugSource::ThirdParty; break; + case AL_DEBUG_SOURCE_APPLICATION_SOFT: dsource = DebugSource::Application; break; + case AL_DEBUG_SOURCE_API_SOFT: + case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: + case AL_DEBUG_SOURCE_OTHER_SOFT: + return context->setError(AL_INVALID_ENUM, "Debug source enum 0x%04x not allowed", source); + default: + return context->setError(AL_INVALID_ENUM, "Invalid debug source enum 0x%04x", source); + } + + DebugType dtype{}; + switch(type) + { + case AL_DEBUG_TYPE_ERROR_SOFT: dtype = DebugType::Error; break; + case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: dtype = DebugType::DeprecatedBehavior; break; + case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: dtype = DebugType::UndefinedBehavior; break; + case AL_DEBUG_TYPE_PORTABILITY_SOFT: dtype = DebugType::Portability; break; + case AL_DEBUG_TYPE_PERFORMANCE_SOFT: dtype = DebugType::Performance; break; + case AL_DEBUG_TYPE_MARKER_SOFT: dtype = DebugType::Marker; break; + case AL_DEBUG_TYPE_OTHER_SOFT: dtype = DebugType::Other; break; + default: + return context->setError(AL_INVALID_ENUM, "Invalid debug type 0x%04x", type); + } + + DebugSeverity dseverity{}; + switch(severity) + { + case AL_DEBUG_SEVERITY_HIGH_SOFT: dseverity = DebugSeverity::High; break; + case AL_DEBUG_SEVERITY_MEDIUM_SOFT: dseverity = DebugSeverity::Medium; break; + case AL_DEBUG_SEVERITY_LOW_SOFT: dseverity = DebugSeverity::Low; break; + case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: dseverity = DebugSeverity::Notification; break; + default: + return context->setError(AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity); + } + + context->debugMessage(dsource, dtype, id, dseverity, length, message); +} + #ifdef ALSOFT_EAX namespace { diff --git a/alc/context.h b/alc/context.h index e8efdbf1..697ecfe9 100644 --- a/alc/context.h +++ b/alc/context.h @@ -34,6 +34,30 @@ struct ALsource; using uint = unsigned int; +enum class DebugSource : ALenum { + API = AL_DEBUG_SOURCE_API_SOFT, + System = AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT, + ThirdParty = AL_DEBUG_SOURCE_THIRD_PARTY_SOFT, + Application = AL_DEBUG_SOURCE_APPLICATION_SOFT, + Other = AL_DEBUG_SOURCE_OTHER_SOFT, +}; +enum class DebugType : ALenum { + Error = AL_DEBUG_TYPE_ERROR_SOFT, + DeprecatedBehavior = AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT, + UndefinedBehavior = AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT, + Portability = AL_DEBUG_TYPE_PORTABILITY_SOFT, + Performance = AL_DEBUG_TYPE_PERFORMANCE_SOFT, + Marker = AL_DEBUG_TYPE_MARKER_SOFT, + Other = AL_DEBUG_TYPE_OTHER_SOFT, +}; +enum class DebugSeverity : ALenum { + High = AL_DEBUG_SEVERITY_HIGH_SOFT, + Medium = AL_DEBUG_SEVERITY_MEDIUM_SOFT, + Low = AL_DEBUG_SEVERITY_LOW_SOFT, + Notification = AL_DEBUG_SEVERITY_NOTIFICATION_SOFT, +}; + + struct SourceSubList { uint64_t FreeMask{~0_u64}; ALsource *Sources{nullptr}; /* 64 */ @@ -76,6 +100,8 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { std::atomic mLastError{AL_NO_ERROR}; + std::atomic mDebugEnabled{false}; + DistanceModel mDistanceModel{DistanceModel::Default}; bool mSourceDistanceModel{false}; @@ -88,6 +114,10 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { ALEVENTPROCSOFT mEventCb{}; void *mEventParam{nullptr}; + std::mutex mDebugCbLock; + ALDEBUGPROCSOFT mDebugCb{}; + void *mDebugParam{nullptr}; + ALlistener mListener{}; al::vector mSourceList; @@ -149,6 +179,17 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { #endif void setError(ALenum errorCode, const char *msg, ...); + void sendDebugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, + ALsizei length, const char *message); + + void debugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, + ALsizei length, const char *message) + { + if(!mDebugEnabled.load(std::memory_order_relaxed)) LIKELY + return; + sendDebugMessage(source, type, id, severity, length, message); + } + /* Process-wide current context */ static std::atomic sGlobalContextLock; static std::atomic sGlobalContext; diff --git a/alc/inprogext.h b/alc/inprogext.h index ccb9a4be..53dc9f0c 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -54,6 +54,37 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_STOP_SOURCES_ON_DISCONNECT_SOFT 0x19AB #endif +#ifndef AL_SOFT_debug +#define AL_SOFT_debug +#define AL_DEBUG_OUTPUT_SOFT 0x19B2 +#define AL_DEBUG_CALLBACK_FUNCTION_SOFT 0x19B3 +#define AL_DEBUG_CALLBACK_USER_PARAM_SOFT 0x19B4 +#define AL_DEBUG_SOURCE_API_SOFT 0x19B5 +#define AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT 0x19B6 +#define AL_DEBUG_SOURCE_THIRD_PARTY_SOFT 0x19B7 +#define AL_DEBUG_SOURCE_APPLICATION_SOFT 0x19B8 +#define AL_DEBUG_SOURCE_OTHER_SOFT 0x19B9 +#define AL_DEBUG_TYPE_ERROR_SOFT 0x19BA +#define AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT 0x19BB +#define AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT 0x19BC +#define AL_DEBUG_TYPE_PORTABILITY_SOFT 0x19BD +#define AL_DEBUG_TYPE_PERFORMANCE_SOFT 0x19BE +#define AL_DEBUG_TYPE_MARKER_SOFT 0x19BF +#define AL_DEBUG_TYPE_OTHER_SOFT 0x19C0 +#define AL_DEBUG_SEVERITY_HIGH_SOFT 0x19C1 +#define AL_DEBUG_SEVERITY_MEDIUM_SOFT 0x19C2 +#define AL_DEBUG_SEVERITY_LOW_SOFT 0x19C3 +#define AL_DEBUG_SEVERITY_NOTIFICATION_SOFT 0x19C4 + +typedef void (AL_APIENTRY*ALDEBUGPROCSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam); +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKSOFT)(ALDEBUGPROCSOFT callback, void *userParam); +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); +#ifdef AL_ALEXT_PROTOTYPES +void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept; +void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; +#endif +#endif + /* Non-standard export. Not part of any extension. */ AL_API const ALchar* AL_APIENTRY alsoft_get_version(void); -- cgit v1.2.3 From 55cc9470f9cf39618db65a1fd7eacb535af3a523 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 29 Apr 2023 20:26:57 -0700 Subject: Add a missing include --- alc/context.h | 1 + 1 file changed, 1 insertion(+) (limited to 'alc') diff --git a/alc/context.h b/alc/context.h index 697ecfe9..0dd9efb0 100644 --- a/alc/context.h +++ b/alc/context.h @@ -16,6 +16,7 @@ #include "alnumeric.h" #include "atomic.h" #include "core/context.h" +#include "inprogext.h" #include "intrusive_ptr.h" #include "vector.h" -- cgit v1.2.3 From e57da7c825607f2756227f4d4273146e8f79bce0 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 29 Apr 2023 22:15:07 -0700 Subject: Provide some more debug messages --- al/state.cpp | 31 ++++++++++++++++++++++++------- alc/alc.cpp | 30 ++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 15 deletions(-) (limited to 'alc') diff --git a/al/state.cpp b/al/state.cpp index 516797aa..777492ef 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -261,6 +261,10 @@ START_API_FUNC break; case AL_DOPPLER_VELOCITY: + context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + DebugSeverity::Medium, -1, + "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; " + "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f"); if(context->mDopplerVelocity != 0.0f) value = AL_TRUE; break; @@ -317,6 +321,10 @@ START_API_FUNC break; case AL_DOPPLER_VELOCITY: + context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + DebugSeverity::Medium, -1, + "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; " + "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f"); value = context->mDopplerVelocity; break; @@ -368,6 +376,10 @@ START_API_FUNC break; case AL_DOPPLER_VELOCITY: + context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + DebugSeverity::Medium, -1, + "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; " + "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f"); value = context->mDopplerVelocity; break; @@ -419,6 +431,10 @@ START_API_FUNC break; case AL_DOPPLER_VELOCITY: + context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + DebugSeverity::Medium, -1, + "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; " + "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f"); value = static_cast(context->mDopplerVelocity); break; @@ -505,6 +521,10 @@ START_API_FUNC break; case AL_DOPPLER_VELOCITY: + context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + DebugSeverity::Medium, -1, + "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; " + "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f"); value = static_cast(context->mDopplerVelocity); break; @@ -848,13 +868,10 @@ START_API_FUNC ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - if(context->mDebugEnabled.load(std::memory_order_relaxed)) - { - static constexpr char deprecatedMessage[] = "alDopplerVelocity is deprecated in AL 1.1"; - context->sendDebugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, - DebugSeverity::Medium, static_cast(std::strlen(deprecatedMessage)), - deprecatedMessage); - } + context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + DebugSeverity::Medium, -1, + "alDopplerVelocity is deprecated in AL 1.1, use alSpeedOfSound; " + "alDopplerVelocity(x) -> alSpeedOfSound(343.3f * x)"); if(!(value >= 0.0f && std::isfinite(value))) context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value); diff --git a/alc/alc.cpp b/alc/alc.cpp index 0ed0ae58..33531afb 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2584,13 +2584,20 @@ END_API_FUNC ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context) START_API_FUNC { - if(!SuspendDefers) - return; - ContextRef ctx{VerifyContext(context)}; if(!ctx) + { alcSetError(nullptr, ALC_INVALID_CONTEXT); - else + return; + } + + ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, -1, + "alcSuspendContext behavior is not portable -- some implementations suspend all " + "rendering, some only defer property changes, and some are completely no-op; consider " + "using alcDevicePauseSOFT to suspend all rendering, or alDeferUpdatesSOFT to only defer " + "property changes"); + + if(SuspendDefers) { std::lock_guard _{ctx->mPropLock}; ctx->deferUpdates(); @@ -2601,13 +2608,20 @@ END_API_FUNC ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context) START_API_FUNC { - if(!SuspendDefers) - return; - ContextRef ctx{VerifyContext(context)}; if(!ctx) + { alcSetError(nullptr, ALC_INVALID_CONTEXT); - else + return; + } + + ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, -1, + "alcProcessContext behavior is not portable -- some implementations resume rendering, " + "some apply deferred property changes, and some are completely no-op; consider using " + "alcDeviceResumeSOFT to resume rendering, or alProcessUpdatesSOFT to apply deferred " + "property changes"); + + if(SuspendDefers) { std::lock_guard _{ctx->mPropLock}; ctx->processUpdates(); -- cgit v1.2.3 From d7e22a8ada669910882ae34e0b57da6712629e72 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Apr 2023 03:13:37 -0700 Subject: Implement non-ID based debug message filtering --- alc/alc.cpp | 21 ++++++++ alc/context.cpp | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- alc/context.h | 9 ++++ alc/inprogext.h | 3 ++ 4 files changed, 179 insertions(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index 33531afb..b6dc111d 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -461,6 +461,8 @@ const struct { DECL(alBufferDataStatic), DECL(alDebugMessageCallbackSOFT), + DECL(alDebugMessageInsertSOFT), + DECL(alDebugMessageControlSOFT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), @@ -917,7 +919,26 @@ constexpr struct { DECL(AL_FORMAT_UHJ4CHN_MULAW_SOFT), DECL(AL_FORMAT_UHJ4CHN_ALAW_SOFT), + DECL(AL_DONT_CARE_SOFT), DECL(AL_DEBUG_OUTPUT_SOFT), + DECL(AL_DEBUG_CALLBACK_FUNCTION_SOFT), + DECL(AL_DEBUG_CALLBACK_USER_PARAM_SOFT), + DECL(AL_DEBUG_SOURCE_API_SOFT), + DECL(AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT), + DECL(AL_DEBUG_SOURCE_THIRD_PARTY_SOFT), + DECL(AL_DEBUG_SOURCE_APPLICATION_SOFT), + DECL(AL_DEBUG_SOURCE_OTHER_SOFT), + DECL(AL_DEBUG_TYPE_ERROR_SOFT), + DECL(AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT), + DECL(AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT), + DECL(AL_DEBUG_TYPE_PORTABILITY_SOFT), + DECL(AL_DEBUG_TYPE_PERFORMANCE_SOFT), + DECL(AL_DEBUG_TYPE_MARKER_SOFT), + DECL(AL_DEBUG_TYPE_OTHER_SOFT), + DECL(AL_DEBUG_SEVERITY_HIGH_SOFT), + DECL(AL_DEBUG_SEVERITY_MEDIUM_SOFT), + DECL(AL_DEBUG_SEVERITY_LOW_SOFT), + DECL(AL_DEBUG_SEVERITY_NOTIFICATION_SOFT), DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), diff --git a/alc/context.cpp b/alc/context.cpp index e2a2e2d2..3f7b456d 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -4,11 +4,13 @@ #include "context.h" #include +#include #include #include #include #include #include +#include #include "AL/efx.h" @@ -19,6 +21,7 @@ #include "al/listener.h" #include "albit.h" #include "alc/alu.h" +#include "alspan.h" #include "core/async_event.h" #include "core/device.h" #include "core/effectslot.h" @@ -27,6 +30,7 @@ #include "core/voice_change.h" #include "device.h" #include "ringbuffer.h" +#include "threads.h" #include "vecmat.h" #ifdef ALSOFT_EAX @@ -295,11 +299,45 @@ void ALCcontext::applyAllUpdates() mHoldUpdates.store(false, std::memory_order_release); } + void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message) { + static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); + std::lock_guard _{mDebugCbLock}; - if(!mDebugEnabled.load()) + if(!mDebugEnabled.load()) UNLIKELY + return; + + uint filter{0}; + switch(source) + { + case DebugSource::API: filter |= 1<<(DebugSourceBase+0); break; + case DebugSource::System: filter |= 1<<(DebugSourceBase+1); break; + case DebugSource::ThirdParty: filter |= 1<<(DebugSourceBase+2); break; + case DebugSource::Application: filter |= 1<<(DebugSourceBase+3); break; + case DebugSource::Other: filter |= 1<<(DebugSourceBase+4); break; + } + switch(type) + { + case DebugType::Error: filter |= 1<<(DebugTypeBase+0); break; + case DebugType::DeprecatedBehavior: filter |= 1<<(DebugTypeBase+1); break; + case DebugType::UndefinedBehavior: filter |= 1<<(DebugTypeBase+2); break; + case DebugType::Portability: filter |= 1<<(DebugTypeBase+3); break; + case DebugType::Performance: filter |= 1<<(DebugTypeBase+4); break; + case DebugType::Marker: filter |= 1<<(DebugTypeBase+5); break; + case DebugType::Other: filter |= 1<<(DebugTypeBase+6); break; + } + switch(severity) + { + case DebugSeverity::High: filter |= 1<<(DebugSeverityBase+0); break; + case DebugSeverity::Medium: filter |= 1<<(DebugSeverityBase+1); break; + case DebugSeverity::Low: filter |= 1<<(DebugSeverityBase+2); break; + case DebugSeverity::Notification: filter |= 1<<(DebugSeverityBase+3); break; + } + + auto iter = std::lower_bound(mDebugFilters.cbegin(), mDebugFilters.cend(), filter); + if(iter != mDebugFilters.cend() && *iter == filter) return; if(mDebugCb) @@ -371,6 +409,113 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type context->debugMessage(dsource, dtype, id, dseverity, length, message); } + +namespace { + +template +constexpr auto make_array(std::integer_sequence) +{ return std::array{Vals...}; } + +template> +constexpr auto make_array() +{ return make_array(Indices{}); } + +} // namespace + +FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, + ALsizei count, const ALuint *ids, ALboolean enable) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + if(count > 0) + { + if(!ids) + return context->setError(AL_INVALID_VALUE, "IDs is null with non-0 count"); + if(source == AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug source cannot be AL_DONT_CARE_SOFT with IDs"); + if(type == AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug type cannot be AL_DONT_CARE_SOFT with IDs"); + if(severity != AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug severity must be AL_DONT_CARE_SOFT with IDs"); + + return context->setError(AL_INVALID_VALUE, "Debug ID filtering not supported"); + return; + } + + if(enable != AL_TRUE && enable != AL_FALSE) + return context->setError(AL_INVALID_VALUE, "Invalid debug enable %d", enable); + + static constexpr size_t ElemCount{DebugSourceCount + DebugTypeCount + DebugSeverityCount}; + static constexpr auto Values = make_array(); + + al::span srcIndices{al::as_span(Values).subspan()}; + switch(source) + { + case AL_DEBUG_SOURCE_API_SOFT: srcIndices = srcIndices.subspan(0, 1); break; + case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: srcIndices = srcIndices.subspan(1, 1); break; + case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: srcIndices = srcIndices.subspan(2, 1); break; + case AL_DEBUG_SOURCE_APPLICATION_SOFT: srcIndices = srcIndices.subspan(3, 1); break; + case AL_DEBUG_SOURCE_OTHER_SOFT: srcIndices = srcIndices.subspan(4, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug source 0x%04x", source); + } + + al::span typeIndices{al::as_span(Values).subspan()}; + switch(type) + { + case AL_DEBUG_TYPE_ERROR_SOFT: typeIndices = typeIndices.subspan(0, 1); break; + case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(1, 1); break; + case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(2, 1); break; + case AL_DEBUG_TYPE_PORTABILITY_SOFT: typeIndices = typeIndices.subspan(3, 1); break; + case AL_DEBUG_TYPE_PERFORMANCE_SOFT: typeIndices = typeIndices.subspan(4, 1); break; + case AL_DEBUG_TYPE_MARKER_SOFT: typeIndices = typeIndices.subspan(5, 1); break; + case AL_DEBUG_TYPE_OTHER_SOFT: typeIndices = typeIndices.subspan(6, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug type 0x%04x", type); + } + + al::span svrIndices{al::as_span(Values).subspan()}; + switch(severity) + { + case AL_DEBUG_SEVERITY_HIGH_SOFT: svrIndices = svrIndices.subspan(0, 1); break; + case AL_DEBUG_SEVERITY_MEDIUM_SOFT: svrIndices = svrIndices.subspan(1, 1); break; + case AL_DEBUG_SEVERITY_LOW_SOFT: svrIndices = svrIndices.subspan(2, 1); break; + case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: svrIndices = svrIndices.subspan(3, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug severity 0x%04x", severity); + } + + std::lock_guard _{context->mDebugCbLock}; + auto apply_filter = [enable,&context](const uint filter) + { + auto iter = std::lower_bound(context->mDebugFilters.cbegin(), + context->mDebugFilters.cend(), filter); + if(enable && (iter == context->mDebugFilters.cend() || *iter != filter)) + context->mDebugFilters.insert(iter, filter); + else if(!enable && iter != context->mDebugFilters.cend() && *iter == filter) + context->mDebugFilters.erase(iter); + }; + auto apply_severity = [apply_filter,svrIndices](const uint filter) + { + std::for_each(svrIndices.cbegin(), svrIndices.cend(), + [apply_filter,filter](const uint idx){ apply_filter(filter | (1<, ContextBase { std::mutex mDebugCbLock; ALDEBUGPROCSOFT mDebugCb{}; void *mDebugParam{nullptr}; + std::vector mDebugFilters; ALlistener mListener{}; diff --git a/alc/inprogext.h b/alc/inprogext.h index 53dc9f0c..a4e2c353 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -56,6 +56,7 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #ifndef AL_SOFT_debug #define AL_SOFT_debug +#define AL_DONT_CARE_SOFT 0x0002 #define AL_DEBUG_OUTPUT_SOFT 0x19B2 #define AL_DEBUG_CALLBACK_FUNCTION_SOFT 0x19B3 #define AL_DEBUG_CALLBACK_USER_PARAM_SOFT 0x19B4 @@ -79,9 +80,11 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * typedef void (AL_APIENTRY*ALDEBUGPROCSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam); typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKSOFT)(ALDEBUGPROCSOFT callback, void *userParam); typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLSOFT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable); #ifdef AL_ALEXT_PROTOTYPES void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept; void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; +void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept; #endif #endif -- cgit v1.2.3 From 755429798a1dbe658d2a4d342927c9b9272629ee Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Apr 2023 03:24:20 -0700 Subject: Move debug functions to their own source --- CMakeLists.txt | 2 + al/debug.cpp | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ al/debug.h | 4 ++ alc/context.cpp | 166 -------------------------------------------------- 4 files changed, 192 insertions(+), 166 deletions(-) create mode 100644 al/debug.cpp create mode 100644 al/debug.h (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index 55644b04..eec2d58f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -742,6 +742,8 @@ set(OPENAL_OBJS al/auxeffectslot.h al/buffer.cpp al/buffer.h + al/debug.cpp + al/debug.h al/effect.cpp al/effect.h al/effects/autowah.cpp diff --git a/al/debug.cpp b/al/debug.cpp new file mode 100644 index 00000000..975443c7 --- /dev/null +++ b/al/debug.cpp @@ -0,0 +1,186 @@ +#include "config.h" + +#include "debug.h" + +#include +#include +#include +#include +#include + +#include "AL/al.h" + +#include "alc/context.h" +#include "alc/inprogext.h" +#include "alspan.h" +#include "opthelpers.h" +#include "threads.h" + + +namespace { + +template +constexpr auto make_array(std::integer_sequence) +{ return std::array{Vals...}; } + +template> +constexpr auto make_array() +{ return make_array(Indices{}); } + +} // namespace + + +FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + std::lock_guard _{context->mDebugCbLock}; + context->mDebugCb = callback; + context->mDebugParam = userParam; +} + +FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type, ALuint id, + ALenum severity, ALsizei length, const ALchar *message) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + if(!message) + return context->setError(AL_INVALID_VALUE, "Null message pointer"); + + DebugSource dsource{}; + switch(source) + { + case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: dsource = DebugSource::ThirdParty; break; + case AL_DEBUG_SOURCE_APPLICATION_SOFT: dsource = DebugSource::Application; break; + case AL_DEBUG_SOURCE_API_SOFT: + case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: + case AL_DEBUG_SOURCE_OTHER_SOFT: + return context->setError(AL_INVALID_ENUM, "Debug source enum 0x%04x not allowed", source); + default: + return context->setError(AL_INVALID_ENUM, "Invalid debug source enum 0x%04x", source); + } + + DebugType dtype{}; + switch(type) + { + case AL_DEBUG_TYPE_ERROR_SOFT: dtype = DebugType::Error; break; + case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: dtype = DebugType::DeprecatedBehavior; break; + case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: dtype = DebugType::UndefinedBehavior; break; + case AL_DEBUG_TYPE_PORTABILITY_SOFT: dtype = DebugType::Portability; break; + case AL_DEBUG_TYPE_PERFORMANCE_SOFT: dtype = DebugType::Performance; break; + case AL_DEBUG_TYPE_MARKER_SOFT: dtype = DebugType::Marker; break; + case AL_DEBUG_TYPE_OTHER_SOFT: dtype = DebugType::Other; break; + default: + return context->setError(AL_INVALID_ENUM, "Invalid debug type 0x%04x", type); + } + + DebugSeverity dseverity{}; + switch(severity) + { + case AL_DEBUG_SEVERITY_HIGH_SOFT: dseverity = DebugSeverity::High; break; + case AL_DEBUG_SEVERITY_MEDIUM_SOFT: dseverity = DebugSeverity::Medium; break; + case AL_DEBUG_SEVERITY_LOW_SOFT: dseverity = DebugSeverity::Low; break; + case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: dseverity = DebugSeverity::Notification; break; + default: + return context->setError(AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity); + } + + context->debugMessage(dsource, dtype, id, dseverity, length, message); +} + + +FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, + ALsizei count, const ALuint *ids, ALboolean enable) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + if(count > 0) + { + if(!ids) + return context->setError(AL_INVALID_VALUE, "IDs is null with non-0 count"); + if(source == AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug source cannot be AL_DONT_CARE_SOFT with IDs"); + if(type == AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug type cannot be AL_DONT_CARE_SOFT with IDs"); + if(severity != AL_DONT_CARE_SOFT) + return context->setError(AL_INVALID_VALUE, + "Debug severity must be AL_DONT_CARE_SOFT with IDs"); + + return context->setError(AL_INVALID_VALUE, "Debug ID filtering not supported"); + return; + } + + if(enable != AL_TRUE && enable != AL_FALSE) + return context->setError(AL_INVALID_VALUE, "Invalid debug enable %d", enable); + + static constexpr size_t ElemCount{DebugSourceCount + DebugTypeCount + DebugSeverityCount}; + static constexpr auto Values = make_array(); + + al::span srcIndices{al::as_span(Values).subspan()}; + switch(source) + { + case AL_DEBUG_SOURCE_API_SOFT: srcIndices = srcIndices.subspan(0, 1); break; + case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: srcIndices = srcIndices.subspan(1, 1); break; + case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: srcIndices = srcIndices.subspan(2, 1); break; + case AL_DEBUG_SOURCE_APPLICATION_SOFT: srcIndices = srcIndices.subspan(3, 1); break; + case AL_DEBUG_SOURCE_OTHER_SOFT: srcIndices = srcIndices.subspan(4, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug source 0x%04x", source); + } + + al::span typeIndices{al::as_span(Values).subspan()}; + switch(type) + { + case AL_DEBUG_TYPE_ERROR_SOFT: typeIndices = typeIndices.subspan(0, 1); break; + case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(1, 1); break; + case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(2, 1); break; + case AL_DEBUG_TYPE_PORTABILITY_SOFT: typeIndices = typeIndices.subspan(3, 1); break; + case AL_DEBUG_TYPE_PERFORMANCE_SOFT: typeIndices = typeIndices.subspan(4, 1); break; + case AL_DEBUG_TYPE_MARKER_SOFT: typeIndices = typeIndices.subspan(5, 1); break; + case AL_DEBUG_TYPE_OTHER_SOFT: typeIndices = typeIndices.subspan(6, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug type 0x%04x", type); + } + + al::span svrIndices{al::as_span(Values).subspan()}; + switch(severity) + { + case AL_DEBUG_SEVERITY_HIGH_SOFT: svrIndices = svrIndices.subspan(0, 1); break; + case AL_DEBUG_SEVERITY_MEDIUM_SOFT: svrIndices = svrIndices.subspan(1, 1); break; + case AL_DEBUG_SEVERITY_LOW_SOFT: svrIndices = svrIndices.subspan(2, 1); break; + case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: svrIndices = svrIndices.subspan(3, 1); break; + case AL_DONT_CARE_SOFT: break; + default: + return context->setError(AL_INVALID_VALUE, "Invalid debug severity 0x%04x", severity); + } + + std::lock_guard _{context->mDebugCbLock}; + auto apply_filter = [enable,&context](const uint filter) + { + auto iter = std::lower_bound(context->mDebugFilters.cbegin(), + context->mDebugFilters.cend(), filter); + if(enable && (iter == context->mDebugFilters.cend() || *iter != filter)) + context->mDebugFilters.insert(iter, filter); + else if(!enable && iter != context->mDebugFilters.cend() && *iter == filter) + context->mDebugFilters.erase(iter); + }; + auto apply_severity = [apply_filter,svrIndices](const uint filter) + { + std::for_each(svrIndices.cbegin(), svrIndices.cend(), + [apply_filter,filter](const uint idx){ apply_filter(filter | (1< _{context->mDebugCbLock}; - context->mDebugCb = callback; - context->mDebugParam = userParam; -} - -FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type, ALuint id, - ALenum severity, ALsizei length, const ALchar *message) noexcept -{ - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; - - if(!message) - return context->setError(AL_INVALID_VALUE, "Null message pointer"); - - DebugSource dsource{}; - switch(source) - { - case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: dsource = DebugSource::ThirdParty; break; - case AL_DEBUG_SOURCE_APPLICATION_SOFT: dsource = DebugSource::Application; break; - case AL_DEBUG_SOURCE_API_SOFT: - case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: - case AL_DEBUG_SOURCE_OTHER_SOFT: - return context->setError(AL_INVALID_ENUM, "Debug source enum 0x%04x not allowed", source); - default: - return context->setError(AL_INVALID_ENUM, "Invalid debug source enum 0x%04x", source); - } - - DebugType dtype{}; - switch(type) - { - case AL_DEBUG_TYPE_ERROR_SOFT: dtype = DebugType::Error; break; - case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: dtype = DebugType::DeprecatedBehavior; break; - case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: dtype = DebugType::UndefinedBehavior; break; - case AL_DEBUG_TYPE_PORTABILITY_SOFT: dtype = DebugType::Portability; break; - case AL_DEBUG_TYPE_PERFORMANCE_SOFT: dtype = DebugType::Performance; break; - case AL_DEBUG_TYPE_MARKER_SOFT: dtype = DebugType::Marker; break; - case AL_DEBUG_TYPE_OTHER_SOFT: dtype = DebugType::Other; break; - default: - return context->setError(AL_INVALID_ENUM, "Invalid debug type 0x%04x", type); - } - - DebugSeverity dseverity{}; - switch(severity) - { - case AL_DEBUG_SEVERITY_HIGH_SOFT: dseverity = DebugSeverity::High; break; - case AL_DEBUG_SEVERITY_MEDIUM_SOFT: dseverity = DebugSeverity::Medium; break; - case AL_DEBUG_SEVERITY_LOW_SOFT: dseverity = DebugSeverity::Low; break; - case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: dseverity = DebugSeverity::Notification; break; - default: - return context->setError(AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity); - } - - context->debugMessage(dsource, dtype, id, dseverity, length, message); -} - - -namespace { - -template -constexpr auto make_array(std::integer_sequence) -{ return std::array{Vals...}; } - -template> -constexpr auto make_array() -{ return make_array(Indices{}); } - -} // namespace - -FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, - ALsizei count, const ALuint *ids, ALboolean enable) noexcept -{ - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; - - if(count > 0) - { - if(!ids) - return context->setError(AL_INVALID_VALUE, "IDs is null with non-0 count"); - if(source == AL_DONT_CARE_SOFT) - return context->setError(AL_INVALID_VALUE, - "Debug source cannot be AL_DONT_CARE_SOFT with IDs"); - if(type == AL_DONT_CARE_SOFT) - return context->setError(AL_INVALID_VALUE, - "Debug type cannot be AL_DONT_CARE_SOFT with IDs"); - if(severity != AL_DONT_CARE_SOFT) - return context->setError(AL_INVALID_VALUE, - "Debug severity must be AL_DONT_CARE_SOFT with IDs"); - - return context->setError(AL_INVALID_VALUE, "Debug ID filtering not supported"); - return; - } - - if(enable != AL_TRUE && enable != AL_FALSE) - return context->setError(AL_INVALID_VALUE, "Invalid debug enable %d", enable); - - static constexpr size_t ElemCount{DebugSourceCount + DebugTypeCount + DebugSeverityCount}; - static constexpr auto Values = make_array(); - - al::span srcIndices{al::as_span(Values).subspan()}; - switch(source) - { - case AL_DEBUG_SOURCE_API_SOFT: srcIndices = srcIndices.subspan(0, 1); break; - case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: srcIndices = srcIndices.subspan(1, 1); break; - case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: srcIndices = srcIndices.subspan(2, 1); break; - case AL_DEBUG_SOURCE_APPLICATION_SOFT: srcIndices = srcIndices.subspan(3, 1); break; - case AL_DEBUG_SOURCE_OTHER_SOFT: srcIndices = srcIndices.subspan(4, 1); break; - case AL_DONT_CARE_SOFT: break; - default: - return context->setError(AL_INVALID_VALUE, "Invalid debug source 0x%04x", source); - } - - al::span typeIndices{al::as_span(Values).subspan()}; - switch(type) - { - case AL_DEBUG_TYPE_ERROR_SOFT: typeIndices = typeIndices.subspan(0, 1); break; - case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(1, 1); break; - case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(2, 1); break; - case AL_DEBUG_TYPE_PORTABILITY_SOFT: typeIndices = typeIndices.subspan(3, 1); break; - case AL_DEBUG_TYPE_PERFORMANCE_SOFT: typeIndices = typeIndices.subspan(4, 1); break; - case AL_DEBUG_TYPE_MARKER_SOFT: typeIndices = typeIndices.subspan(5, 1); break; - case AL_DEBUG_TYPE_OTHER_SOFT: typeIndices = typeIndices.subspan(6, 1); break; - case AL_DONT_CARE_SOFT: break; - default: - return context->setError(AL_INVALID_VALUE, "Invalid debug type 0x%04x", type); - } - - al::span svrIndices{al::as_span(Values).subspan()}; - switch(severity) - { - case AL_DEBUG_SEVERITY_HIGH_SOFT: svrIndices = svrIndices.subspan(0, 1); break; - case AL_DEBUG_SEVERITY_MEDIUM_SOFT: svrIndices = svrIndices.subspan(1, 1); break; - case AL_DEBUG_SEVERITY_LOW_SOFT: svrIndices = svrIndices.subspan(2, 1); break; - case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: svrIndices = svrIndices.subspan(3, 1); break; - case AL_DONT_CARE_SOFT: break; - default: - return context->setError(AL_INVALID_VALUE, "Invalid debug severity 0x%04x", severity); - } - - std::lock_guard _{context->mDebugCbLock}; - auto apply_filter = [enable,&context](const uint filter) - { - auto iter = std::lower_bound(context->mDebugFilters.cbegin(), - context->mDebugFilters.cend(), filter); - if(enable && (iter == context->mDebugFilters.cend() || *iter != filter)) - context->mDebugFilters.insert(iter, filter); - else if(!enable && iter != context->mDebugFilters.cend() && *iter == filter) - context->mDebugFilters.erase(iter); - }; - auto apply_severity = [apply_filter,svrIndices](const uint filter) - { - std::for_each(svrIndices.cbegin(), svrIndices.cend(), - [apply_filter,filter](const uint idx){ apply_filter(filter | (1< Date: Sun, 30 Apr 2023 03:53:16 -0700 Subject: Separate the internal debug enums from the API values --- al/debug.cpp | 129 +++++++++++++++++++++++++++++--------------------------- alc/context.cpp | 67 +++++++++++++++++------------ alc/context.h | 54 ++++++++++++------------ 3 files changed, 133 insertions(+), 117 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index 975443c7..5d01fda9 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -12,6 +12,7 @@ #include "alc/context.h" #include "alc/inprogext.h" +#include "aloptional.h" #include "alspan.h" #include "opthelpers.h" #include "threads.h" @@ -27,6 +28,47 @@ template GetDebugSource(ALenum source) noexcept +{ + switch(source) + { + case AL_DEBUG_SOURCE_API_SOFT: return DebugSource::API; + case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: return DebugSource::System; + case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: return DebugSource::ThirdParty; + case AL_DEBUG_SOURCE_APPLICATION_SOFT: return DebugSource::Application; + case AL_DEBUG_SOURCE_OTHER_SOFT: return DebugSource::Other; + } + return al::nullopt; +} + +constexpr al::optional GetDebugType(ALenum type) noexcept +{ + switch(type) + { + case AL_DEBUG_TYPE_ERROR_SOFT: return DebugType::Error; + case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: return DebugType::DeprecatedBehavior; + case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: return DebugType::UndefinedBehavior; + case AL_DEBUG_TYPE_PORTABILITY_SOFT: return DebugType::Portability; + case AL_DEBUG_TYPE_PERFORMANCE_SOFT: return DebugType::Performance; + case AL_DEBUG_TYPE_MARKER_SOFT: return DebugType::Marker; + case AL_DEBUG_TYPE_OTHER_SOFT: return DebugType::Other; + } + return al::nullopt; +} + +constexpr al::optional GetDebugSeverity(ALenum severity) noexcept +{ + switch(severity) + { + case AL_DEBUG_SEVERITY_HIGH_SOFT: return DebugSeverity::High; + case AL_DEBUG_SEVERITY_MEDIUM_SOFT: return DebugSeverity::Medium; + case AL_DEBUG_SEVERITY_LOW_SOFT: return DebugSeverity::Low; + case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: return DebugSeverity::Notification; + } + return al::nullopt; +} + } // namespace @@ -49,45 +91,21 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type if(!message) return context->setError(AL_INVALID_VALUE, "Null message pointer"); - DebugSource dsource{}; - switch(source) - { - case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: dsource = DebugSource::ThirdParty; break; - case AL_DEBUG_SOURCE_APPLICATION_SOFT: dsource = DebugSource::Application; break; - case AL_DEBUG_SOURCE_API_SOFT: - case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: - case AL_DEBUG_SOURCE_OTHER_SOFT: - return context->setError(AL_INVALID_ENUM, "Debug source enum 0x%04x not allowed", source); - default: - return context->setError(AL_INVALID_ENUM, "Invalid debug source enum 0x%04x", source); - } + auto dsource = GetDebugSource(source); + if(!dsource) + return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source); + if(*dsource != DebugSource::ThirdParty && *dsource != DebugSource::Application) + return context->setError(AL_INVALID_ENUM, "Debug source 0x%04x not allowed", source); - DebugType dtype{}; - switch(type) - { - case AL_DEBUG_TYPE_ERROR_SOFT: dtype = DebugType::Error; break; - case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: dtype = DebugType::DeprecatedBehavior; break; - case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: dtype = DebugType::UndefinedBehavior; break; - case AL_DEBUG_TYPE_PORTABILITY_SOFT: dtype = DebugType::Portability; break; - case AL_DEBUG_TYPE_PERFORMANCE_SOFT: dtype = DebugType::Performance; break; - case AL_DEBUG_TYPE_MARKER_SOFT: dtype = DebugType::Marker; break; - case AL_DEBUG_TYPE_OTHER_SOFT: dtype = DebugType::Other; break; - default: + auto dtype = GetDebugType(type); + if(!dtype) return context->setError(AL_INVALID_ENUM, "Invalid debug type 0x%04x", type); - } - DebugSeverity dseverity{}; - switch(severity) - { - case AL_DEBUG_SEVERITY_HIGH_SOFT: dseverity = DebugSeverity::High; break; - case AL_DEBUG_SEVERITY_MEDIUM_SOFT: dseverity = DebugSeverity::Medium; break; - case AL_DEBUG_SEVERITY_LOW_SOFT: dseverity = DebugSeverity::Low; break; - case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: dseverity = DebugSeverity::Notification; break; - default: + auto dseverity = GetDebugSeverity(severity); + if(!dseverity) return context->setError(AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity); - } - context->debugMessage(dsource, dtype, id, dseverity, length, message); + context->debugMessage(*dsource, *dtype, id, *dseverity, length, message); } @@ -122,43 +140,30 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ static constexpr auto Values = make_array(); al::span srcIndices{al::as_span(Values).subspan()}; - switch(source) + if(source != AL_DONT_CARE_SOFT) { - case AL_DEBUG_SOURCE_API_SOFT: srcIndices = srcIndices.subspan(0, 1); break; - case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: srcIndices = srcIndices.subspan(1, 1); break; - case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: srcIndices = srcIndices.subspan(2, 1); break; - case AL_DEBUG_SOURCE_APPLICATION_SOFT: srcIndices = srcIndices.subspan(3, 1); break; - case AL_DEBUG_SOURCE_OTHER_SOFT: srcIndices = srcIndices.subspan(4, 1); break; - case AL_DONT_CARE_SOFT: break; - default: - return context->setError(AL_INVALID_VALUE, "Invalid debug source 0x%04x", source); + auto dsource = GetDebugSource(source); + if(!dsource) + return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source); + srcIndices = srcIndices.subspan(al::to_underlying(*dsource), 1); } al::span typeIndices{al::as_span(Values).subspan()}; - switch(type) + if(type != AL_DONT_CARE_SOFT) { - case AL_DEBUG_TYPE_ERROR_SOFT: typeIndices = typeIndices.subspan(0, 1); break; - case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(1, 1); break; - case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: typeIndices = typeIndices.subspan(2, 1); break; - case AL_DEBUG_TYPE_PORTABILITY_SOFT: typeIndices = typeIndices.subspan(3, 1); break; - case AL_DEBUG_TYPE_PERFORMANCE_SOFT: typeIndices = typeIndices.subspan(4, 1); break; - case AL_DEBUG_TYPE_MARKER_SOFT: typeIndices = typeIndices.subspan(5, 1); break; - case AL_DEBUG_TYPE_OTHER_SOFT: typeIndices = typeIndices.subspan(6, 1); break; - case AL_DONT_CARE_SOFT: break; - default: - return context->setError(AL_INVALID_VALUE, "Invalid debug type 0x%04x", type); + auto dtype = GetDebugType(type); + if(!dtype) + return context->setError(AL_INVALID_ENUM, "Invalid debug type 0x%04x", type); + typeIndices = typeIndices.subspan(al::to_underlying(*dtype), 1); } al::span svrIndices{al::as_span(Values).subspan()}; - switch(severity) + if(severity != AL_DONT_CARE_SOFT) { - case AL_DEBUG_SEVERITY_HIGH_SOFT: svrIndices = svrIndices.subspan(0, 1); break; - case AL_DEBUG_SEVERITY_MEDIUM_SOFT: svrIndices = svrIndices.subspan(1, 1); break; - case AL_DEBUG_SEVERITY_LOW_SOFT: svrIndices = svrIndices.subspan(2, 1); break; - case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: svrIndices = svrIndices.subspan(3, 1); break; - case AL_DONT_CARE_SOFT: break; - default: - return context->setError(AL_INVALID_VALUE, "Invalid debug severity 0x%04x", severity); + auto dseverity = GetDebugSeverity(severity); + if(!dseverity) + return context->setError(AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity); + svrIndices = svrIndices.subspan(al::to_underlying(*dseverity), 1); } std::lock_guard _{context->mDebugCbLock}; diff --git a/alc/context.cpp b/alc/context.cpp index 5b476009..7fcb6539 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -304,45 +304,56 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message) { static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); + static auto get_source_enum = [](DebugSource source) noexcept + { + switch(source) + { + case DebugSource::API: return AL_DEBUG_SOURCE_API_SOFT; + case DebugSource::System: return AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT; + case DebugSource::ThirdParty: return AL_DEBUG_SOURCE_THIRD_PARTY_SOFT; + case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_SOFT; + case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_SOFT; + } + }; + static auto get_type_enum = [](DebugType type) noexcept + { + switch(type) + { + case DebugType::Error: return AL_DEBUG_TYPE_ERROR_SOFT; + case DebugType::DeprecatedBehavior: return AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT; + case DebugType::UndefinedBehavior: return AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT; + case DebugType::Portability: return AL_DEBUG_TYPE_PORTABILITY_SOFT; + case DebugType::Performance: return AL_DEBUG_TYPE_PERFORMANCE_SOFT; + case DebugType::Marker: return AL_DEBUG_TYPE_MARKER_SOFT; + case DebugType::Other: return AL_DEBUG_TYPE_OTHER_SOFT; + } + }; + static auto get_severity_enum = [](DebugSeverity severity) noexcept + { + switch(severity) + { + case DebugSeverity::High: return AL_DEBUG_SEVERITY_HIGH_SOFT; + case DebugSeverity::Medium: return AL_DEBUG_SEVERITY_MEDIUM_SOFT; + case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_SOFT; + case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_SOFT; + } + }; std::lock_guard _{mDebugCbLock}; if(!mDebugEnabled.load()) UNLIKELY return; - uint filter{0}; - switch(source) - { - case DebugSource::API: filter |= 1<<(DebugSourceBase+0); break; - case DebugSource::System: filter |= 1<<(DebugSourceBase+1); break; - case DebugSource::ThirdParty: filter |= 1<<(DebugSourceBase+2); break; - case DebugSource::Application: filter |= 1<<(DebugSourceBase+3); break; - case DebugSource::Other: filter |= 1<<(DebugSourceBase+4); break; - } - switch(type) - { - case DebugType::Error: filter |= 1<<(DebugTypeBase+0); break; - case DebugType::DeprecatedBehavior: filter |= 1<<(DebugTypeBase+1); break; - case DebugType::UndefinedBehavior: filter |= 1<<(DebugTypeBase+2); break; - case DebugType::Portability: filter |= 1<<(DebugTypeBase+3); break; - case DebugType::Performance: filter |= 1<<(DebugTypeBase+4); break; - case DebugType::Marker: filter |= 1<<(DebugTypeBase+5); break; - case DebugType::Other: filter |= 1<<(DebugTypeBase+6); break; - } - switch(severity) - { - case DebugSeverity::High: filter |= 1<<(DebugSeverityBase+0); break; - case DebugSeverity::Medium: filter |= 1<<(DebugSeverityBase+1); break; - case DebugSeverity::Low: filter |= 1<<(DebugSeverityBase+2); break; - case DebugSeverity::Notification: filter |= 1<<(DebugSeverityBase+3); break; - } + const uint filter{(1u<<(DebugSourceBase+al::to_underlying(source))) + | (1u<<(DebugTypeBase+al::to_underlying(type))) + | (1u<<(DebugSeverityBase+al::to_underlying(severity)))}; auto iter = std::lower_bound(mDebugFilters.cbegin(), mDebugFilters.cend(), filter); if(iter != mDebugFilters.cend() && *iter == filter) return; if(mDebugCb) - mDebugCb(al::to_underlying(source), al::to_underlying(type), id, - al::to_underlying(severity), length, message, mDebugParam); + mDebugCb(get_source_enum(source), get_type_enum(type), id, get_severity_enum(severity), + length, message, mDebugParam); else { /* TODO: Store in a log. */ diff --git a/alc/context.h b/alc/context.h index 8613c2a3..b5ee440b 100644 --- a/alc/context.h +++ b/alc/context.h @@ -35,36 +35,36 @@ struct ALsource; using uint = unsigned int; -constexpr size_t DebugSourceBase{0}; -enum class DebugSource : ALenum { - API = AL_DEBUG_SOURCE_API_SOFT, - System = AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT, - ThirdParty = AL_DEBUG_SOURCE_THIRD_PARTY_SOFT, - Application = AL_DEBUG_SOURCE_APPLICATION_SOFT, - Other = AL_DEBUG_SOURCE_OTHER_SOFT, +constexpr uint DebugSourceBase{0}; +enum class DebugSource : uint8_t { + API = 0, + System, + ThirdParty, + Application, + Other, }; -constexpr size_t DebugSourceCount{5}; - -constexpr size_t DebugTypeBase{DebugSourceBase + DebugSourceCount}; -enum class DebugType : ALenum { - Error = AL_DEBUG_TYPE_ERROR_SOFT, - DeprecatedBehavior = AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT, - UndefinedBehavior = AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT, - Portability = AL_DEBUG_TYPE_PORTABILITY_SOFT, - Performance = AL_DEBUG_TYPE_PERFORMANCE_SOFT, - Marker = AL_DEBUG_TYPE_MARKER_SOFT, - Other = AL_DEBUG_TYPE_OTHER_SOFT, +constexpr uint DebugSourceCount{5}; + +constexpr uint DebugTypeBase{DebugSourceBase + DebugSourceCount}; +enum class DebugType : uint8_t { + Error = 0, + DeprecatedBehavior, + UndefinedBehavior, + Portability, + Performance, + Marker, + Other, }; -constexpr size_t DebugTypeCount{7}; - -constexpr size_t DebugSeverityBase{DebugTypeBase + DebugTypeCount}; -enum class DebugSeverity : ALenum { - High = AL_DEBUG_SEVERITY_HIGH_SOFT, - Medium = AL_DEBUG_SEVERITY_MEDIUM_SOFT, - Low = AL_DEBUG_SEVERITY_LOW_SOFT, - Notification = AL_DEBUG_SEVERITY_NOTIFICATION_SOFT, +constexpr uint DebugTypeCount{7}; + +constexpr uint DebugSeverityBase{DebugTypeBase + DebugTypeCount}; +enum class DebugSeverity : uint8_t { + High = 0, + Medium, + Low, + Notification, }; -constexpr size_t DebugSeverityCount{4}; +constexpr uint DebugSeverityCount{4}; struct SourceSubList { -- cgit v1.2.3 From b64b500c6b75aebb3b5d1c41206317f81636a21c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Apr 2023 04:22:13 -0700 Subject: Improve some debug error handling --- al/debug.cpp | 8 ++++---- alc/context.cpp | 9 ++++++--- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index 5d01fda9..98c5a0b5 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -120,13 +120,13 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ if(!ids) return context->setError(AL_INVALID_VALUE, "IDs is null with non-0 count"); if(source == AL_DONT_CARE_SOFT) - return context->setError(AL_INVALID_VALUE, + return context->setError(AL_INVALID_OPERATION, "Debug source cannot be AL_DONT_CARE_SOFT with IDs"); if(type == AL_DONT_CARE_SOFT) - return context->setError(AL_INVALID_VALUE, + return context->setError(AL_INVALID_OPERATION, "Debug type cannot be AL_DONT_CARE_SOFT with IDs"); if(severity != AL_DONT_CARE_SOFT) - return context->setError(AL_INVALID_VALUE, + return context->setError(AL_INVALID_OPERATION, "Debug severity must be AL_DONT_CARE_SOFT with IDs"); return context->setError(AL_INVALID_VALUE, "Debug ID filtering not supported"); @@ -134,7 +134,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ } if(enable != AL_TRUE && enable != AL_FALSE) - return context->setError(AL_INVALID_VALUE, "Invalid debug enable %d", enable); + return context->setError(AL_INVALID_ENUM, "Invalid debug enable %d", enable); static constexpr size_t ElemCount{DebugSourceCount + DebugTypeCount + DebugSeverityCount}; static constexpr auto Values = make_array(); diff --git a/alc/context.cpp b/alc/context.cpp index 7fcb6539..6553f322 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -304,7 +304,7 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message) { static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); - static auto get_source_enum = [](DebugSource source) noexcept + static auto get_source_enum = [](DebugSource source) { switch(source) { @@ -314,8 +314,9 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_SOFT; case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_SOFT; } + throw std::runtime_error{"Unexpected debug source value "+std::to_string(al::to_underlying(source))}; }; - static auto get_type_enum = [](DebugType type) noexcept + static auto get_type_enum = [](DebugType type) { switch(type) { @@ -327,8 +328,9 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, case DebugType::Marker: return AL_DEBUG_TYPE_MARKER_SOFT; case DebugType::Other: return AL_DEBUG_TYPE_OTHER_SOFT; } + throw std::runtime_error{"Unexpected debug type value "+std::to_string(al::to_underlying(type))}; }; - static auto get_severity_enum = [](DebugSeverity severity) noexcept + static auto get_severity_enum = [](DebugSeverity severity) { switch(severity) { @@ -337,6 +339,7 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_SOFT; case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_SOFT; } + throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; }; std::lock_guard _{mDebugCbLock}; -- cgit v1.2.3 From f2a0df87916de7b9fa8b65a52814c9a09fc6bee9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Apr 2023 14:36:56 -0700 Subject: Unlock the debug lock when calling the callback There's no full guarantee about calling AL functions in a debug callback, due to a risk of deadlocks from an AL call that tries to take a lock that's already held at the time the callback is invoked, but this helps more work. --- alc/context.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'alc') diff --git a/alc/context.cpp b/alc/context.cpp index 6553f322..4e5a3ab6 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -342,7 +342,7 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; }; - std::lock_guard _{mDebugCbLock}; + std::unique_lock debuglock{mDebugCbLock}; if(!mDebugEnabled.load()) UNLIKELY return; @@ -355,8 +355,13 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, return; if(mDebugCb) - mDebugCb(get_source_enum(source), get_type_enum(type), id, get_severity_enum(severity), - length, message, mDebugParam); + { + auto callback = mDebugCb; + auto param = mDebugParam; + debuglock.unlock(); + callback(get_source_enum(source), get_type_enum(type), id, get_severity_enum(severity), + length, message, param); + } else { /* TODO: Store in a log. */ -- cgit v1.2.3 From 22077687cf4b9fdfd29d78debc2daf044deee81d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Apr 2023 17:46:18 -0700 Subject: Implement debug log storage --- al/debug.cpp | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ al/debug.h | 9 ++++++ al/state.cpp | 61 ++++++++++++++++++++++++++++++++++++- alc/alc.cpp | 5 ++++ alc/context.cpp | 29 +++++++++++++++++- alc/context.h | 19 ++++++++++++ alc/inprogext.h | 6 ++++ 7 files changed, 220 insertions(+), 2 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index 2694d7b4..ab81f5a8 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -71,6 +71,46 @@ constexpr al::optional GetDebugSeverity(ALenum severity) noexcept } // namespace +ALenum GetDebugSourceEnum(DebugSource source) +{ + switch(source) + { + case DebugSource::API: return AL_DEBUG_SOURCE_API_SOFT; + case DebugSource::System: return AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT; + case DebugSource::ThirdParty: return AL_DEBUG_SOURCE_THIRD_PARTY_SOFT; + case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_SOFT; + case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_SOFT; + } + throw std::runtime_error{"Unexpected debug source value "+std::to_string(al::to_underlying(source))}; +} + +ALenum GetDebugTypeEnum(DebugType type) +{ + switch(type) + { + case DebugType::Error: return AL_DEBUG_TYPE_ERROR_SOFT; + case DebugType::DeprecatedBehavior: return AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT; + case DebugType::UndefinedBehavior: return AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT; + case DebugType::Portability: return AL_DEBUG_TYPE_PORTABILITY_SOFT; + case DebugType::Performance: return AL_DEBUG_TYPE_PERFORMANCE_SOFT; + case DebugType::Marker: return AL_DEBUG_TYPE_MARKER_SOFT; + case DebugType::Other: return AL_DEBUG_TYPE_OTHER_SOFT; + } + throw std::runtime_error{"Unexpected debug type value "+std::to_string(al::to_underlying(type))}; +} + +ALenum GetDebugSeverityEnum(DebugSeverity severity) +{ + switch(severity) + { + case DebugSeverity::High: return AL_DEBUG_SEVERITY_HIGH_SOFT; + case DebugSeverity::Medium: return AL_DEBUG_SEVERITY_MEDIUM_SOFT; + case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_SOFT; + case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_SOFT; + } + throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; +} + FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept { @@ -91,6 +131,18 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type if(!message) return context->setError(AL_INVALID_VALUE, "Null message pointer"); + if(length < 0) + { + size_t newlen{std::strlen(message)}; + if(newlen > MaxDebugMessageLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu > %d)", newlen, + MaxDebugMessageLength); + length = static_cast(newlen); + } + else if(length > MaxDebugMessageLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Debug message too long (%d > %d)", length, + MaxDebugMessageLength); + auto dsource = GetDebugSource(source); if(!dsource) return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source); @@ -189,3 +241,44 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ std::for_each(srcIndices.cbegin(), srcIndices.cend(), [apply_type](const uint idx){ apply_type(1<setError(AL_INVALID_VALUE, "Negative debug log buffer size"); + return 0; + } + + std::lock_guard _{context->mDebugCbLock}; + ALsizei logBufWritten{0}; + for(ALuint i{0};i < count;++i) + { + if(context->mDebugLog.empty()) + return i; + + auto &entry = context->mDebugLog.front(); + const size_t tocopy{entry.mMessage.size() + 1}; + const size_t avail{static_cast(logBufSize - logBufWritten)}; + if(avail < tocopy) + return i; + + if(sources) sources[i] = GetDebugSourceEnum(entry.mSource); + if(types) types[i] = GetDebugTypeEnum(entry.mType); + if(ids) ids[i] = entry.mId; + if(severities) severities[i] = GetDebugSeverityEnum(entry.mSeverity); + if(lengths) lengths[i] = static_cast(tocopy); + if(logBuf) std::copy_n(entry.mMessage.data(), tocopy, logBuf+logBufWritten); + + logBufWritten += static_cast(tocopy); + context->mDebugLog.pop_front(); + } + + return count; +} diff --git a/al/debug.h b/al/debug.h index a268f690..23b0ca1b 100644 --- a/al/debug.h +++ b/al/debug.h @@ -1,4 +1,13 @@ #ifndef AL_DEBUG_H #define AL_DEBUG_H +#include + + +/* Somewhat arbitrary. Avoid letting it get out of control if the app enables + * logging but never reads it. + */ +constexpr uint8_t MaxDebugLoggedMessages{64}; +constexpr uint16_t MaxDebugMessageLength{1024}; + #endif /* AL_DEBUG_H */ diff --git a/al/state.cpp b/al/state.cpp index 7b7377f7..1e1a0085 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -33,6 +33,7 @@ #include "AL/alc.h" #include "AL/alext.h" +#include "al/debug.h" #include "alc/alu.h" #include "alc/context.h" #include "alc/inprogext.h" @@ -259,6 +260,10 @@ START_API_FUNC case AL_DISTANCE_MODEL: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: return alGetInteger(pname) != 0; } @@ -299,6 +304,10 @@ START_API_FUNC case AL_DISTANCE_MODEL: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: return alGetInteger(pname); } @@ -325,8 +334,11 @@ START_API_FUNC case AL_DISTANCE_MODEL: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: return static_cast(alGetInteger(pname)); - break; case AL_DEFERRED_UPDATES_SOFT: return alGetBoolean(pname) ? 1.0f : 0.0f; @@ -401,6 +413,29 @@ START_API_FUNC value = al::to_underlying(ResamplerDefault); break; + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + { + std::lock_guard __{context->mDebugCbLock}; + value = static_cast(context->mDebugLog.size()); + break; + } + + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + { + std::lock_guard __{context->mDebugCbLock}; + value = context->mDebugLog.empty() ? 0 + : static_cast(context->mDebugLog.front().mMessage.size()+1); + break; + } + + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + value = MaxDebugMessageLength; + break; + + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + value = MaxDebugLoggedMessages; + break; + #ifdef ALSOFT_EAX #define EAX_ERROR "[alGetInteger] EAX not enabled." @@ -452,6 +487,10 @@ START_API_FUNC case AL_DISTANCE_MODEL: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: return alGetInteger(pname); } @@ -519,6 +558,10 @@ START_API_FUNC case AL_GAIN_LIMIT_SOFT: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: values[0] = alGetBoolean(pname); return; } @@ -552,6 +595,10 @@ START_API_FUNC case AL_GAIN_LIMIT_SOFT: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: values[0] = alGetDouble(pname); return; } @@ -585,6 +632,10 @@ START_API_FUNC case AL_GAIN_LIMIT_SOFT: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: values[0] = alGetFloat(pname); return; } @@ -618,6 +669,10 @@ START_API_FUNC case AL_GAIN_LIMIT_SOFT: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: values[0] = alGetInteger(pname); return; } @@ -651,6 +706,10 @@ START_API_FUNC case AL_GAIN_LIMIT_SOFT: case AL_NUM_RESAMPLERS_SOFT: case AL_DEFAULT_RESAMPLER_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: values[0] = alGetInteger64SOFT(pname); return; } diff --git a/alc/alc.cpp b/alc/alc.cpp index b6dc111d..504737ec 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -463,6 +463,7 @@ const struct { DECL(alDebugMessageCallbackSOFT), DECL(alDebugMessageInsertSOFT), DECL(alDebugMessageControlSOFT), + DECL(alGetDebugMessageLogSOFT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), @@ -939,6 +940,10 @@ constexpr struct { DECL(AL_DEBUG_SEVERITY_MEDIUM_SOFT), DECL(AL_DEBUG_SEVERITY_LOW_SOFT), DECL(AL_DEBUG_SEVERITY_NOTIFICATION_SOFT), + DECL(AL_DEBUG_LOGGED_MESSAGES_SOFT), + DECL(AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT), + DECL(AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT), + DECL(AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT), DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), diff --git a/alc/context.cpp b/alc/context.cpp index 4e5a3ab6..a07e5412 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -15,6 +15,7 @@ #include "AL/efx.h" #include "al/auxeffectslot.h" +#include "al/debug.h" #include "al/source.h" #include "al/effect.h" #include "al/event.h" @@ -342,6 +343,22 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; }; + if(length < 0) + { + size_t newlen{std::strlen(message)}; + if(newlen > MaxDebugMessageLength) UNLIKELY + { + ERR("Debug message too long (%zu > %d)\n", newlen, MaxDebugMessageLength); + return; + } + length = static_cast(newlen); + } + else if(length > MaxDebugMessageLength) UNLIKELY + { + ERR("Debug message too long (%d > %d)\n", length, MaxDebugMessageLength); + return; + } + std::unique_lock debuglock{mDebugCbLock}; if(!mDebugEnabled.load()) UNLIKELY return; @@ -364,7 +381,17 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, } else { - /* TODO: Store in a log. */ + if(mDebugLog.size() < MaxDebugLoggedMessages) + mDebugLog.emplace_back(source, type, id, severity, message); + else UNLIKELY + ERR("Debug message log overflow. Lost message:\n" + " Source: 0x%04x\n" + " Type: 0x%04x\n" + " ID: %u\n" + " Severity: 0x%04x\n" + " Message: \"%s\"\n", + get_source_enum(source), get_type_enum(type), id, get_severity_enum(severity), + message); } } diff --git a/alc/context.h b/alc/context.h index b5ee440b..031e061e 100644 --- a/alc/context.h +++ b/alc/context.h @@ -2,6 +2,7 @@ #define ALC_CONTEXT_H #include +#include #include #include #include @@ -66,6 +67,23 @@ enum class DebugSeverity : uint8_t { }; constexpr uint DebugSeverityCount{4}; +struct LogEntry { + const DebugSource mSource; + const DebugType mType; + const DebugSeverity mSeverity; + const uint mId; + + std::string mMessage; + + template + LogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message) + : mSource{source}, mType{type}, mSeverity{severity}, mId{id} + , mMessage{std::forward(message)} + { } + LogEntry(const LogEntry&) = default; + LogEntry(LogEntry&&) = default; +}; + struct SourceSubList { uint64_t FreeMask{~0_u64}; @@ -127,6 +145,7 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { ALDEBUGPROCSOFT mDebugCb{}; void *mDebugParam{nullptr}; std::vector mDebugFilters; + std::deque mDebugLog; ALlistener mListener{}; diff --git a/alc/inprogext.h b/alc/inprogext.h index a4e2c353..f73963cb 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -76,15 +76,21 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_DEBUG_SEVERITY_MEDIUM_SOFT 0x19C2 #define AL_DEBUG_SEVERITY_LOW_SOFT 0x19C3 #define AL_DEBUG_SEVERITY_NOTIFICATION_SOFT 0x19C4 +#define AL_DEBUG_LOGGED_MESSAGES_SOFT 0x19C5 +#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT 0x19C6 +#define AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT 0x19C7 +#define AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT 0x19C8 typedef void (AL_APIENTRY*ALDEBUGPROCSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam); typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKSOFT)(ALDEBUGPROCSOFT callback, void *userParam); typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLSOFT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable); +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGSOFT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf); #ifdef AL_ALEXT_PROTOTYPES void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept; void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept; +ALuint AL_APIENTRY alGetDebugMessageLogSOFT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept; #endif #endif -- cgit v1.2.3 From 9215e8c9d5f4fdc7b2e552203f5836264542c4a3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Apr 2023 18:17:24 -0700 Subject: Add an extension string for the in-progress debug extension --- alc/context.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'alc') diff --git a/alc/context.cpp b/alc/context.cpp index a07e5412..4b477184 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -71,6 +71,7 @@ constexpr ALchar alExtList[] = "AL_SOFT_buffer_length_query " "AL_SOFT_callback_buffer " "AL_SOFTX_convolution_reverb " + "AL_SOFTX_debug " "AL_SOFT_deferred_updates " "AL_SOFT_direct_channels " "AL_SOFT_direct_channels_remix " -- cgit v1.2.3 From 3953cb5dbef7add70e72f41bbf36d5fdf1b02917 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Apr 2023 19:22:38 -0700 Subject: Fix shadowing warnings and add another missing include --- alc/context.cpp | 55 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) (limited to 'alc') diff --git a/alc/context.cpp b/alc/context.cpp index 4b477184..66de19d6 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -306,7 +307,28 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message) { static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); - static auto get_source_enum = [](DebugSource source) + + if(length < 0) + { + size_t newlen{std::strlen(message)}; + if(newlen > MaxDebugMessageLength) UNLIKELY + { + ERR("Debug message too long (%zu > %d)\n", newlen, MaxDebugMessageLength); + return; + } + length = static_cast(newlen); + } + else if(length > MaxDebugMessageLength) UNLIKELY + { + ERR("Debug message too long (%d > %d)\n", length, MaxDebugMessageLength); + return; + } + + std::unique_lock debuglock{mDebugCbLock}; + if(!mDebugEnabled.load()) UNLIKELY + return; + + auto get_source_enum = [source]() { switch(source) { @@ -318,7 +340,7 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, } throw std::runtime_error{"Unexpected debug source value "+std::to_string(al::to_underlying(source))}; }; - static auto get_type_enum = [](DebugType type) + auto get_type_enum = [type]() { switch(type) { @@ -332,7 +354,7 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, } throw std::runtime_error{"Unexpected debug type value "+std::to_string(al::to_underlying(type))}; }; - static auto get_severity_enum = [](DebugSeverity severity) + auto get_severity_enum = [severity]() { switch(severity) { @@ -344,26 +366,6 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; }; - if(length < 0) - { - size_t newlen{std::strlen(message)}; - if(newlen > MaxDebugMessageLength) UNLIKELY - { - ERR("Debug message too long (%zu > %d)\n", newlen, MaxDebugMessageLength); - return; - } - length = static_cast(newlen); - } - else if(length > MaxDebugMessageLength) UNLIKELY - { - ERR("Debug message too long (%d > %d)\n", length, MaxDebugMessageLength); - return; - } - - std::unique_lock debuglock{mDebugCbLock}; - if(!mDebugEnabled.load()) UNLIKELY - return; - const uint filter{(1u<<(DebugSourceBase+al::to_underlying(source))) | (1u<<(DebugTypeBase+al::to_underlying(type))) | (1u<<(DebugSeverityBase+al::to_underlying(severity)))}; @@ -377,8 +379,8 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, auto callback = mDebugCb; auto param = mDebugParam; debuglock.unlock(); - callback(get_source_enum(source), get_type_enum(type), id, get_severity_enum(severity), - length, message, param); + callback(get_source_enum(), get_type_enum(), id, get_severity_enum(), length, message, + param); } else { @@ -391,8 +393,7 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, " ID: %u\n" " Severity: 0x%04x\n" " Message: \"%s\"\n", - get_source_enum(source), get_type_enum(type), id, get_severity_enum(severity), - message); + get_source_enum(), get_type_enum(), id, get_severity_enum(), message); } } -- cgit v1.2.3 From 931e261fe0944c1876a95a373996351f3424f399 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 1 May 2023 01:22:29 -0700 Subject: Implement debug message filtering for IDs --- al/debug.cpp | 71 +++++++++++++++++++++++++++++++++++++++------------------ alc/context.cpp | 11 +++++++++ alc/context.h | 2 ++ 3 files changed, 62 insertions(+), 22 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index 702f165a..26a69aff 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -183,9 +183,6 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ if(severity != AL_DONT_CARE_SOFT) return context->setError(AL_INVALID_OPERATION, "Debug severity must be AL_DONT_CARE_SOFT with IDs"); - - return context->setError(AL_INVALID_VALUE, "Debug ID filtering not supported"); - return; } if(enable != AL_TRUE && enable != AL_FALSE) @@ -222,27 +219,57 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ } std::lock_guard _{context->mDebugCbLock}; - auto apply_filter = [enable,&context](const uint filter) - { - auto iter = std::lower_bound(context->mDebugFilters.cbegin(), - context->mDebugFilters.cend(), filter); - if(!enable && (iter == context->mDebugFilters.cend() || *iter != filter)) - context->mDebugFilters.insert(iter, filter); - else if(enable && iter != context->mDebugFilters.cend() && *iter == filter) - context->mDebugFilters.erase(iter); - }; - auto apply_severity = [apply_filter,svrIndices](const uint filter) + if(count > 0) { - std::for_each(svrIndices.cbegin(), svrIndices.cend(), - [apply_filter,filter](const uint idx){ apply_filter(filter | (1<(count))) + { + if(!enable) + { + auto &idfilters = context->mDebugIdFilters[id]; + auto iter = std::lower_bound(idfilters.cbegin(), idfilters.cend(), filter); + if(iter == idfilters.cend() || *iter != filter) + idfilters.insert(iter, filter); + continue; + } + + auto iditer = context->mDebugIdFilters.find(id); + if(iditer == context->mDebugIdFilters.end()) + continue; + auto iter = std::lower_bound(iditer->second.cbegin(), iditer->second.cend(), filter); + if(iter != iditer->second.cend() && *iter == filter) + { + iditer->second.erase(iter); + if(iditer->second.empty()) + context->mDebugIdFilters.erase(iditer); + } + } + } + else { - std::for_each(typeIndices.cbegin(), typeIndices.cend(), - [apply_severity,filter](const uint idx){ apply_severity(filter | (1<mDebugFilters.cbegin(), + context->mDebugFilters.cend(), filter); + if(!enable && (iter == context->mDebugFilters.cend() || *iter != filter)) + context->mDebugFilters.insert(iter, filter); + else if(enable && iter != context->mDebugFilters.cend() && *iter == filter) + context->mDebugFilters.erase(iter); + }; + auto apply_severity = [apply_filter,svrIndices](const uint filter) + { + std::for_each(svrIndices.cbegin(), svrIndices.cend(), + [apply_filter,filter](const uint idx){ apply_filter(filter | (1<second.cbegin(), iditer->second.cend(), filter); + if(iter != iditer->second.cend() && *iter == filter) + return; + } + const uint filter{(1u<<(DebugSourceBase+al::to_underlying(source))) | (1u<<(DebugTypeBase+al::to_underlying(type))) | (1u<<(DebugSeverityBase+al::to_underlying(severity)))}; diff --git a/alc/context.h b/alc/context.h index 031e061e..c626160b 100644 --- a/alc/context.h +++ b/alc/context.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "AL/al.h" @@ -145,6 +146,7 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { ALDEBUGPROCSOFT mDebugCb{}; void *mDebugParam{nullptr}; std::vector mDebugFilters; + std::unordered_map> mDebugIdFilters; std::deque mDebugLog; ALlistener mListener{}; -- cgit v1.2.3 From 0e7d078b01e423e7973cc593046f9716d1ca8c0b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 1 May 2023 01:38:16 -0700 Subject: Avoid assigning to existing optional Reduces the amount inlining the compiler has to do, though the uhj/filter config option is no longer recognized (it has been deprecated, amd I don't think it was in an actual release). --- alc/alc.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index 504737ec..63654b1a 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -1201,13 +1201,7 @@ void alc_initconfig(void) } Voice::InitMixer(ConfigValueStr(nullptr, nullptr, "resampler")); - auto uhjfiltopt = ConfigValueStr(nullptr, "uhj", "decode-filter"); - if(!uhjfiltopt) - { - if((uhjfiltopt = ConfigValueStr(nullptr, "uhj", "filter"))) - WARN("uhj/filter is deprecated, please use uhj/decode-filter\n"); - } - if(uhjfiltopt) + if(auto uhjfiltopt = ConfigValueStr(nullptr, "uhj", "decode-filter")) { if(al::strcasecmp(uhjfiltopt->c_str(), "fir256") == 0) UhjDecodeQuality = UhjQualityType::FIR256; @@ -1218,7 +1212,7 @@ void alc_initconfig(void) else WARN("Unsupported uhj/decode-filter: %s\n", uhjfiltopt->c_str()); } - if((uhjfiltopt = ConfigValueStr(nullptr, "uhj", "encode-filter"))) + if(auto uhjfiltopt = ConfigValueStr(nullptr, "uhj", "encode-filter")) { if(al::strcasecmp(uhjfiltopt->c_str(), "fir256") == 0) UhjEncodeQuality = UhjQualityType::FIR256; -- cgit v1.2.3 From bd8c13d7883cb0a570f724885c7a55ad687dada6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 1 May 2023 03:43:25 -0700 Subject: Fix some debug message length limit checks --- al/debug.cpp | 11 +++++++---- alc/context.cpp | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index 26a69aff..66cbc622 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -134,15 +134,18 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type if(!message) return context->setError(AL_INVALID_VALUE, "Null message pointer"); + /* MaxDebugMessageLength is the size including the null terminator, + * does not include the null terminator. + */ if(length < 0) { size_t newlen{std::strlen(message)}; - if(newlen > MaxDebugMessageLength) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu > %d)", newlen, - MaxDebugMessageLength); + if(newlen >= MaxDebugMessageLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu >= %d)", + newlen, MaxDebugMessageLength); length = static_cast(newlen); } - else if(length > MaxDebugMessageLength) UNLIKELY + else if(length >= MaxDebugMessageLength) UNLIKELY return context->setError(AL_INVALID_VALUE, "Debug message too long (%d > %d)", length, MaxDebugMessageLength); diff --git a/alc/context.cpp b/alc/context.cpp index d4019bc9..bb4930ee 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -308,19 +308,22 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, { static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); + /* MaxDebugMessageLength is the size including the null terminator, + * does not include the null terminator. + */ if(length < 0) { size_t newlen{std::strlen(message)}; - if(newlen > MaxDebugMessageLength) UNLIKELY + if(newlen >= MaxDebugMessageLength) UNLIKELY { - ERR("Debug message too long (%zu > %d)\n", newlen, MaxDebugMessageLength); + ERR("Debug message too long (%zu >= %d)\n", newlen, MaxDebugMessageLength); return; } length = static_cast(newlen); } - else if(length > MaxDebugMessageLength) UNLIKELY + else if(length >= MaxDebugMessageLength) UNLIKELY { - ERR("Debug message too long (%d > %d)\n", length, MaxDebugMessageLength); + ERR("Debug message too long (%d >= %d)\n", length, MaxDebugMessageLength); return; } -- cgit v1.2.3 From 89f67ad6f9878ecfb48b49ce0dd69b9ecb065d0b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 1 May 2023 14:46:26 -0700 Subject: Use a 64-bit value for tracking ID filters --- al/debug.cpp | 29 +++++++++-------------------- alc/context.cpp | 23 +++++++++-------------- alc/context.h | 2 +- 3 files changed, 19 insertions(+), 35 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index 66cbc622..70c7c4db 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -224,29 +224,18 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ std::lock_guard _{context->mDebugCbLock}; if(count > 0) { - const uint filter{(1u<(count))) { - if(!enable) - { - auto &idfilters = context->mDebugIdFilters[id]; - auto iter = std::lower_bound(idfilters.cbegin(), idfilters.cend(), filter); - if(iter == idfilters.cend() || *iter != filter) - idfilters.insert(iter, filter); - continue; - } - - auto iditer = context->mDebugIdFilters.find(id); - if(iditer == context->mDebugIdFilters.end()) - continue; - auto iter = std::lower_bound(iditer->second.cbegin(), iditer->second.cend(), filter); - if(iter != iditer->second.cend() && *iter == filter) - { - iditer->second.erase(iter); - if(iditer->second.empty()) - context->mDebugIdFilters.erase(iditer); - } + const uint64_t filter{filterbase | (uint64_t{id} << 32)}; + + auto iter = std::lower_bound(context->mDebugIdFilters.cbegin(), + context->mDebugIdFilters.cend(), filter); + if(!enable && (iter == context->mDebugIdFilters.cend() || *iter != filter)) + context->mDebugIdFilters.insert(iter, filter); + else if(enable && iter != context->mDebugIdFilters.cend() && *iter == filter) + context->mDebugIdFilters.erase(iter); } } else diff --git a/alc/context.cpp b/alc/context.cpp index bb4930ee..7d10a91d 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -369,21 +369,16 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; }; - auto iditer = mDebugIdFilters.find(id); - if(iditer != mDebugIdFilters.end()) - { - const uint filter{(1u<<(DebugSourceBase+al::to_underlying(source))) - | (1u<<(DebugTypeBase+al::to_underlying(type)))}; - - auto iter = std::lower_bound(iditer->second.cbegin(), iditer->second.cend(), filter); - if(iter != iditer->second.cend() && *iter == filter) - return; - } - - const uint filter{(1u<<(DebugSourceBase+al::to_underlying(source))) - | (1u<<(DebugTypeBase+al::to_underlying(type))) - | (1u<<(DebugSeverityBase+al::to_underlying(severity)))}; + const uint64_t idfilter{(1_u64 << (DebugSourceBase+al::to_underlying(source))) + | (1_u64 << (DebugTypeBase+al::to_underlying(type))) + | (uint64_t{id} << 32)}; + auto iditer = std::lower_bound(mDebugIdFilters.cbegin(), mDebugIdFilters.cend(), idfilter); + if(iditer != mDebugIdFilters.cend() && *iditer == idfilter) + return; + const uint filter{(1u << (DebugSourceBase+al::to_underlying(source))) + | (1u << (DebugTypeBase+al::to_underlying(type))) + | (1u << (DebugSeverityBase+al::to_underlying(severity)))}; auto iter = std::lower_bound(mDebugFilters.cbegin(), mDebugFilters.cend(), filter); if(iter != mDebugFilters.cend() && *iter == filter) return; diff --git a/alc/context.h b/alc/context.h index c626160b..b3f548c8 100644 --- a/alc/context.h +++ b/alc/context.h @@ -146,7 +146,7 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { ALDEBUGPROCSOFT mDebugCb{}; void *mDebugParam{nullptr}; std::vector mDebugFilters; - std::unordered_map> mDebugIdFilters; + std::vector mDebugIdFilters; std::deque mDebugLog; ALlistener mListener{}; -- cgit v1.2.3 From bb08a416f1b0e31292b896f2f8845e365daee6b1 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 1 May 2023 17:11:49 -0700 Subject: Put the debug filters into a group --- al/debug.cpp | 26 +++++++++++----------- al/debug.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ al/error.cpp | 1 + alc/alc.cpp | 1 + alc/context.cpp | 10 +++++---- alc/context.h | 60 +++++++------------------------------------------ 6 files changed, 98 insertions(+), 69 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index 70c7c4db..fc893490 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -222,6 +222,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ } std::lock_guard _{context->mDebugCbLock}; + DebugGroup &debug = context->mDebugGroups.back(); if(count > 0) { const uint filterbase{(1u<mDebugIdFilters.cbegin(), - context->mDebugIdFilters.cend(), filter); - if(!enable && (iter == context->mDebugIdFilters.cend() || *iter != filter)) - context->mDebugIdFilters.insert(iter, filter); - else if(enable && iter != context->mDebugIdFilters.cend() && *iter == filter) - context->mDebugIdFilters.erase(iter); + auto iter = std::lower_bound(debug.mIdFilters.cbegin(), debug.mIdFilters.cend(), + filter); + if(!enable && (iter == debug.mIdFilters.cend() || *iter != filter)) + debug.mIdFilters.insert(iter, filter); + else if(enable && iter != debug.mIdFilters.cend() && *iter == filter) + debug.mIdFilters.erase(iter); } } else { - auto apply_filter = [enable,&context](const uint filter) + auto apply_filter = [enable,&debug](const uint filter) { - auto iter = std::lower_bound(context->mDebugFilters.cbegin(), - context->mDebugFilters.cend(), filter); - if(!enable && (iter == context->mDebugFilters.cend() || *iter != filter)) - context->mDebugFilters.insert(iter, filter); - else if(enable && iter != context->mDebugFilters.cend() && *iter == filter) - context->mDebugFilters.erase(iter); + auto iter = std::lower_bound(debug.mFilters.cbegin(), debug.mFilters.cend(), filter); + if(!enable && (iter == debug.mFilters.cend() || *iter != filter)) + debug.mFilters.insert(iter, filter); + else if(enable && iter != debug.mFilters.cend() && *iter == filter) + debug.mFilters.erase(iter); }; auto apply_severity = [apply_filter,svrIndices](const uint filter) { diff --git a/al/debug.h b/al/debug.h index 23b0ca1b..c2147cf4 100644 --- a/al/debug.h +++ b/al/debug.h @@ -2,6 +2,10 @@ #define AL_DEBUG_H #include +#include +#include + +using uint = unsigned int; /* Somewhat arbitrary. Avoid letting it get out of control if the app enables @@ -10,4 +14,69 @@ constexpr uint8_t MaxDebugLoggedMessages{64}; constexpr uint16_t MaxDebugMessageLength{1024}; + +constexpr uint DebugSourceBase{0}; +enum class DebugSource : uint8_t { + API = 0, + System, + ThirdParty, + Application, + Other, +}; +constexpr uint DebugSourceCount{5}; + +constexpr uint DebugTypeBase{DebugSourceBase + DebugSourceCount}; +enum class DebugType : uint8_t { + Error = 0, + DeprecatedBehavior, + UndefinedBehavior, + Portability, + Performance, + Marker, + Other, +}; +constexpr uint DebugTypeCount{7}; + +constexpr uint DebugSeverityBase{DebugTypeBase + DebugTypeCount}; +enum class DebugSeverity : uint8_t { + High = 0, + Medium, + Low, + Notification, +}; +constexpr uint DebugSeverityCount{4}; + +struct DebugGroup { + const uint mId; + const DebugSource mSource; + std::string mMessage; + std::vector mFilters; + std::vector mIdFilters; + + template + DebugGroup(DebugSource source, uint id, T&& message) + : mId{id}, mSource{source}, mMessage{std::forward(message)} + { } + DebugGroup(const DebugGroup&) = default; + DebugGroup(DebugGroup&&) = default; +}; + + +struct DebugLogEntry { + const DebugSource mSource; + const DebugType mType; + const DebugSeverity mSeverity; + const uint mId; + + std::string mMessage; + + template + DebugLogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message) + : mSource{source}, mType{type}, mSeverity{severity}, mId{id} + , mMessage{std::forward(message)} + { } + DebugLogEntry(const DebugLogEntry&) = default; + DebugLogEntry(DebugLogEntry&&) = default; +}; + #endif /* AL_DEBUG_H */ diff --git a/al/error.cpp b/al/error.cpp index 70081a2e..39fd9f0a 100644 --- a/al/error.cpp +++ b/al/error.cpp @@ -35,6 +35,7 @@ #include "AL/al.h" #include "AL/alc.h" +#include "al/debug.h" #include "alc/context.h" #include "almalloc.h" #include "core/except.h" diff --git a/alc/alc.cpp b/alc/alc.cpp index 63654b1a..aa65222c 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -61,6 +61,7 @@ #include "al/auxeffectslot.h" #include "al/buffer.h" +#include "al/debug.h" #include "al/effect.h" #include "al/filter.h" #include "al/listener.h" diff --git a/alc/context.cpp b/alc/context.cpp index 7d10a91d..755a1e41 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -122,6 +122,7 @@ void ALCcontext::setThreadContext(ALCcontext *context) noexcept ALCcontext::ALCcontext(al::intrusive_ptr device) : ContextBase{device.get()}, mALDevice{std::move(device)} { + mDebugGroups.emplace_back(DebugSource::Other, 0, std::string{}); } ALCcontext::~ALCcontext() @@ -328,6 +329,7 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, } std::unique_lock debuglock{mDebugCbLock}; + DebugGroup &debug = mDebugGroups.back(); if(!mDebugEnabled.load()) UNLIKELY return; @@ -372,15 +374,15 @@ void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, const uint64_t idfilter{(1_u64 << (DebugSourceBase+al::to_underlying(source))) | (1_u64 << (DebugTypeBase+al::to_underlying(type))) | (uint64_t{id} << 32)}; - auto iditer = std::lower_bound(mDebugIdFilters.cbegin(), mDebugIdFilters.cend(), idfilter); - if(iditer != mDebugIdFilters.cend() && *iditer == idfilter) + auto iditer = std::lower_bound(debug.mIdFilters.cbegin(), debug.mIdFilters.cend(), idfilter); + if(iditer != debug.mIdFilters.cend() && *iditer == idfilter) return; const uint filter{(1u << (DebugSourceBase+al::to_underlying(source))) | (1u << (DebugTypeBase+al::to_underlying(type))) | (1u << (DebugSeverityBase+al::to_underlying(severity)))}; - auto iter = std::lower_bound(mDebugFilters.cbegin(), mDebugFilters.cend(), filter); - if(iter != mDebugFilters.cend() && *iter == filter) + auto iter = std::lower_bound(debug.mFilters.cbegin(), debug.mFilters.cend(), filter); + if(iter != debug.mFilters.cend() && *iter == filter) return; if(mDebugCb) diff --git a/alc/context.h b/alc/context.h index b3f548c8..3e31c9b8 100644 --- a/alc/context.h +++ b/alc/context.h @@ -33,57 +33,14 @@ struct ALeffect; struct ALeffectslot; struct ALsource; +struct DebugGroup; +struct DebugLogEntry; -using uint = unsigned int; - +enum class DebugSource : uint8_t; +enum class DebugType : uint8_t; +enum class DebugSeverity : uint8_t; -constexpr uint DebugSourceBase{0}; -enum class DebugSource : uint8_t { - API = 0, - System, - ThirdParty, - Application, - Other, -}; -constexpr uint DebugSourceCount{5}; - -constexpr uint DebugTypeBase{DebugSourceBase + DebugSourceCount}; -enum class DebugType : uint8_t { - Error = 0, - DeprecatedBehavior, - UndefinedBehavior, - Portability, - Performance, - Marker, - Other, -}; -constexpr uint DebugTypeCount{7}; - -constexpr uint DebugSeverityBase{DebugTypeBase + DebugTypeCount}; -enum class DebugSeverity : uint8_t { - High = 0, - Medium, - Low, - Notification, -}; -constexpr uint DebugSeverityCount{4}; - -struct LogEntry { - const DebugSource mSource; - const DebugType mType; - const DebugSeverity mSeverity; - const uint mId; - - std::string mMessage; - - template - LogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message) - : mSource{source}, mType{type}, mSeverity{severity}, mId{id} - , mMessage{std::forward(message)} - { } - LogEntry(const LogEntry&) = default; - LogEntry(LogEntry&&) = default; -}; +using uint = unsigned int; struct SourceSubList { @@ -145,9 +102,8 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { std::mutex mDebugCbLock; ALDEBUGPROCSOFT mDebugCb{}; void *mDebugParam{nullptr}; - std::vector mDebugFilters; - std::vector mDebugIdFilters; - std::deque mDebugLog; + std::vector mDebugGroups; + std::deque mDebugLog; ALlistener mListener{}; -- cgit v1.2.3 From e1b573284b649c6fef42ab5b6ca51978c4a1329a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 1 May 2023 19:11:26 -0700 Subject: Implement pushing/popping debug groups --- al/debug.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- al/debug.h | 5 +- al/state.cpp | 23 +++++++++ alc/alc.cpp | 7 +++ alc/context.cpp | 105 ---------------------------------------- alc/context.h | 7 +-- alc/inprogext.h | 27 +++++++---- 7 files changed, 197 insertions(+), 122 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index fc893490..2dd0e7c7 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -17,12 +17,15 @@ #include "alc/inprogext.h" #include "aloptional.h" #include "alspan.h" +#include "core/logging.h" #include "opthelpers.h" #include "threads.h" namespace { +static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); + template constexpr auto make_array(std::integer_sequence) { return std::array{Vals...}; } @@ -55,6 +58,8 @@ constexpr al::optional GetDebugType(ALenum type) noexcept case AL_DEBUG_TYPE_PORTABILITY_SOFT: return DebugType::Portability; case AL_DEBUG_TYPE_PERFORMANCE_SOFT: return DebugType::Performance; case AL_DEBUG_TYPE_MARKER_SOFT: return DebugType::Marker; + case AL_DEBUG_TYPE_PUSH_GROUP_SOFT: return DebugType::PushGroup; + case AL_DEBUG_TYPE_POP_GROUP_SOFT: return DebugType::PopGroup; case AL_DEBUG_TYPE_OTHER_SOFT: return DebugType::Other; } return al::nullopt; @@ -72,7 +77,6 @@ constexpr al::optional GetDebugSeverity(ALenum severity) noexcept return al::nullopt; } -} // namespace ALenum GetDebugSourceEnum(DebugSource source) { @@ -97,6 +101,8 @@ ALenum GetDebugTypeEnum(DebugType type) case DebugType::Portability: return AL_DEBUG_TYPE_PORTABILITY_SOFT; case DebugType::Performance: return AL_DEBUG_TYPE_PERFORMANCE_SOFT; case DebugType::Marker: return AL_DEBUG_TYPE_MARKER_SOFT; + case DebugType::PushGroup: return AL_DEBUG_TYPE_PUSH_GROUP_SOFT; + case DebugType::PopGroup: return AL_DEBUG_TYPE_POP_GROUP_SOFT; case DebugType::Other: return AL_DEBUG_TYPE_OTHER_SOFT; } throw std::runtime_error{"Unexpected debug type value "+std::to_string(al::to_underlying(type))}; @@ -114,6 +120,74 @@ ALenum GetDebugSeverityEnum(DebugSeverity severity) throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; } +} // namespace + + +void ALCcontext::sendDebugMessage(std::unique_lock &debuglock, DebugSource source, + DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message) +{ + if(!mDebugEnabled.load()) UNLIKELY + return; + + /* MaxDebugMessageLength is the size including the null terminator, + * does not include the null terminator. + */ + if(length < 0) + { + size_t newlen{std::strlen(message)}; + if(newlen >= MaxDebugMessageLength) UNLIKELY + { + ERR("Debug message too long (%zu >= %d)\n", newlen, MaxDebugMessageLength); + return; + } + length = static_cast(newlen); + } + else if(length >= MaxDebugMessageLength) UNLIKELY + { + ERR("Debug message too long (%d >= %d)\n", length, MaxDebugMessageLength); + return; + } + + DebugGroup &debug = mDebugGroups.back(); + + const uint64_t idfilter{(1_u64 << (DebugSourceBase+al::to_underlying(source))) + | (1_u64 << (DebugTypeBase+al::to_underlying(type))) + | (uint64_t{id} << 32)}; + auto iditer = std::lower_bound(debug.mIdFilters.cbegin(), debug.mIdFilters.cend(), idfilter); + if(iditer != debug.mIdFilters.cend() && *iditer == idfilter) + return; + + const uint filter{(1u << (DebugSourceBase+al::to_underlying(source))) + | (1u << (DebugTypeBase+al::to_underlying(type))) + | (1u << (DebugSeverityBase+al::to_underlying(severity)))}; + auto iter = std::lower_bound(debug.mFilters.cbegin(), debug.mFilters.cend(), filter); + if(iter != debug.mFilters.cend() && *iter == filter) + return; + + if(mDebugCb) + { + auto callback = mDebugCb; + auto param = mDebugParam; + debuglock.unlock(); + callback(GetDebugSourceEnum(source), GetDebugTypeEnum(type), id, + GetDebugSeverityEnum(severity), length, message, param); + } + else + { + if(mDebugLog.size() < MaxDebugLoggedMessages) + mDebugLog.emplace_back(source, type, id, severity, message); + else UNLIKELY + ERR("Debug message log overflow. Lost message:\n" + " Source: 0x%04x\n" + " Type: 0x%04x\n" + " ID: %u\n" + " Severity: 0x%04x\n" + " Message: \"%s\"\n", + GetDebugSourceEnum(source), GetDebugTypeEnum(type), id, + GetDebugSeverityEnum(severity), message); + } +} + FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept { @@ -134,9 +208,6 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type if(!message) return context->setError(AL_INVALID_VALUE, "Null message pointer"); - /* MaxDebugMessageLength is the size including the null terminator, - * does not include the null terminator. - */ if(length < 0) { size_t newlen{std::strlen(message)}; @@ -265,6 +336,72 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ } +FORCE_ALIGN void AL_APIENTRY alPushDebugGroupSOFT(ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + if(length < 0) + { + size_t newlen{std::strlen(message)}; + if(newlen >= MaxDebugMessageLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu >= %d)", + newlen, MaxDebugMessageLength); + length = static_cast(newlen); + } + else if(length >= MaxDebugMessageLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Debug message too long (%d > %d)", length, + MaxDebugMessageLength); + + auto dsource = GetDebugSource(source); + if(!dsource) + return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source); + if(*dsource != DebugSource::ThirdParty && *dsource != DebugSource::Application) + return context->setError(AL_INVALID_ENUM, "Debug source 0x%04x not allowed", source); + + std::unique_lock debuglock{context->mDebugCbLock}; + if(context->mDebugGroups.size() >= MaxDebugGroupDepth) + { + debuglock.unlock(); + return context->setError(AL_STACK_OVERFLOW_SOFT, "Pushing too many debug groups"); + } + + context->mDebugGroups.emplace_back(*dsource, id, message); + auto &oldback = *(context->mDebugGroups.end()-2); + auto &newback = context->mDebugGroups.back(); + + newback.mFilters = oldback.mFilters; + newback.mIdFilters = oldback.mIdFilters; + + context->sendDebugMessage(debuglock, newback.mSource, DebugType::PushGroup, newback.mId, + DebugSeverity::Notification, static_cast(newback.mMessage.size()), + newback.mMessage.data()); +} + +FORCE_ALIGN void AL_APIENTRY alPopDebugGroupSOFT(void) noexcept +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + std::unique_lock debuglock{context->mDebugCbLock}; + if(context->mDebugGroups.size() <= 1) + { + debuglock.unlock(); + return context->setError(AL_STACK_UNDERFLOW_SOFT, + "Attempting to pop the default debug group"); + } + + DebugGroup &debug = context->mDebugGroups.back(); + const auto source = debug.mSource; + const auto id = debug.mId; + std::string message{std::move(debug.mMessage)}; + + context->mDebugGroups.pop_back(); + context->sendDebugMessage(debuglock, source, DebugType::PopGroup, id, + DebugSeverity::Notification, static_cast(message.size()), message.data()); +} + + FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogSOFT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept diff --git a/al/debug.h b/al/debug.h index c2147cf4..8f83fd5e 100644 --- a/al/debug.h +++ b/al/debug.h @@ -13,6 +13,7 @@ using uint = unsigned int; */ constexpr uint8_t MaxDebugLoggedMessages{64}; constexpr uint16_t MaxDebugMessageLength{1024}; +constexpr uint8_t MaxDebugGroupDepth{64}; constexpr uint DebugSourceBase{0}; @@ -33,9 +34,11 @@ enum class DebugType : uint8_t { Portability, Performance, Marker, + PushGroup, + PopGroup, Other, }; -constexpr uint DebugTypeCount{7}; +constexpr uint DebugTypeCount{9}; constexpr uint DebugSeverityBase{DebugTypeBase + DebugTypeCount}; enum class DebugSeverity : uint8_t { diff --git a/al/state.cpp b/al/state.cpp index 1e1a0085..2a350646 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -69,6 +69,8 @@ constexpr ALchar alErrInvalidEnum[] = "Invalid Enum"; constexpr ALchar alErrInvalidValue[] = "Invalid Value"; constexpr ALchar alErrInvalidOp[] = "Invalid Operation"; constexpr ALchar alErrOutOfMemory[] = "Out of Memory"; +constexpr ALchar alStackOverflow[] = "Stack Overflow"; +constexpr ALchar alStackUnderflow[] = "Stack Underflow"; /* Resampler strings */ template struct ResamplerName { }; @@ -264,6 +266,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: return alGetInteger(pname) != 0; } @@ -308,6 +311,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: return alGetInteger(pname); } @@ -338,6 +342,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: return static_cast(alGetInteger(pname)); case AL_DEFERRED_UPDATES_SOFT: @@ -436,6 +441,10 @@ START_API_FUNC value = MaxDebugLoggedMessages; break; + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: + value = MaxDebugGroupDepth; + break; + #ifdef ALSOFT_EAX #define EAX_ERROR "[alGetInteger] EAX not enabled." @@ -491,6 +500,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: return alGetInteger(pname); } @@ -562,6 +572,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: values[0] = alGetBoolean(pname); return; } @@ -599,6 +610,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: values[0] = alGetDouble(pname); return; } @@ -636,6 +648,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: values[0] = alGetFloat(pname); return; } @@ -673,6 +686,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: values[0] = alGetInteger(pname); return; } @@ -710,6 +724,7 @@ START_API_FUNC case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: values[0] = alGetInteger64SOFT(pname); return; } @@ -806,6 +821,14 @@ START_API_FUNC value = alErrOutOfMemory; break; + case AL_STACK_OVERFLOW_SOFT: + value = alStackOverflow; + break; + + case AL_STACK_UNDERFLOW_SOFT: + value = alStackUnderflow; + break; + default: context->setError(AL_INVALID_VALUE, "Invalid string property 0x%04x", pname); } diff --git a/alc/alc.cpp b/alc/alc.cpp index aa65222c..50982ed2 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -464,6 +464,8 @@ const struct { DECL(alDebugMessageCallbackSOFT), DECL(alDebugMessageInsertSOFT), DECL(alDebugMessageControlSOFT), + DECL(alPushDebugGroupSOFT), + DECL(alPopDebugGroupSOFT), DECL(alGetDebugMessageLogSOFT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { @@ -936,6 +938,8 @@ constexpr struct { DECL(AL_DEBUG_TYPE_PORTABILITY_SOFT), DECL(AL_DEBUG_TYPE_PERFORMANCE_SOFT), DECL(AL_DEBUG_TYPE_MARKER_SOFT), + DECL(AL_DEBUG_TYPE_PUSH_GROUP_SOFT), + DECL(AL_DEBUG_TYPE_POP_GROUP_SOFT), DECL(AL_DEBUG_TYPE_OTHER_SOFT), DECL(AL_DEBUG_SEVERITY_HIGH_SOFT), DECL(AL_DEBUG_SEVERITY_MEDIUM_SOFT), @@ -945,6 +949,9 @@ constexpr struct { DECL(AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT), DECL(AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT), DECL(AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT), + DECL(AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT), + DECL(AL_STACK_OVERFLOW_SOFT), + DECL(AL_STACK_UNDERFLOW_SOFT), DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), diff --git a/alc/context.cpp b/alc/context.cpp index 755a1e41..0c8253fb 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -304,111 +304,6 @@ void ALCcontext::applyAllUpdates() } -void ALCcontext::sendDebugMessage(DebugSource source, DebugType type, ALuint id, - DebugSeverity severity, ALsizei length, const char *message) -{ - static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); - - /* MaxDebugMessageLength is the size including the null terminator, - * does not include the null terminator. - */ - if(length < 0) - { - size_t newlen{std::strlen(message)}; - if(newlen >= MaxDebugMessageLength) UNLIKELY - { - ERR("Debug message too long (%zu >= %d)\n", newlen, MaxDebugMessageLength); - return; - } - length = static_cast(newlen); - } - else if(length >= MaxDebugMessageLength) UNLIKELY - { - ERR("Debug message too long (%d >= %d)\n", length, MaxDebugMessageLength); - return; - } - - std::unique_lock debuglock{mDebugCbLock}; - DebugGroup &debug = mDebugGroups.back(); - if(!mDebugEnabled.load()) UNLIKELY - return; - - auto get_source_enum = [source]() - { - switch(source) - { - case DebugSource::API: return AL_DEBUG_SOURCE_API_SOFT; - case DebugSource::System: return AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT; - case DebugSource::ThirdParty: return AL_DEBUG_SOURCE_THIRD_PARTY_SOFT; - case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_SOFT; - case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_SOFT; - } - throw std::runtime_error{"Unexpected debug source value "+std::to_string(al::to_underlying(source))}; - }; - auto get_type_enum = [type]() - { - switch(type) - { - case DebugType::Error: return AL_DEBUG_TYPE_ERROR_SOFT; - case DebugType::DeprecatedBehavior: return AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT; - case DebugType::UndefinedBehavior: return AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT; - case DebugType::Portability: return AL_DEBUG_TYPE_PORTABILITY_SOFT; - case DebugType::Performance: return AL_DEBUG_TYPE_PERFORMANCE_SOFT; - case DebugType::Marker: return AL_DEBUG_TYPE_MARKER_SOFT; - case DebugType::Other: return AL_DEBUG_TYPE_OTHER_SOFT; - } - throw std::runtime_error{"Unexpected debug type value "+std::to_string(al::to_underlying(type))}; - }; - auto get_severity_enum = [severity]() - { - switch(severity) - { - case DebugSeverity::High: return AL_DEBUG_SEVERITY_HIGH_SOFT; - case DebugSeverity::Medium: return AL_DEBUG_SEVERITY_MEDIUM_SOFT; - case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_SOFT; - case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_SOFT; - } - throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; - }; - - const uint64_t idfilter{(1_u64 << (DebugSourceBase+al::to_underlying(source))) - | (1_u64 << (DebugTypeBase+al::to_underlying(type))) - | (uint64_t{id} << 32)}; - auto iditer = std::lower_bound(debug.mIdFilters.cbegin(), debug.mIdFilters.cend(), idfilter); - if(iditer != debug.mIdFilters.cend() && *iditer == idfilter) - return; - - const uint filter{(1u << (DebugSourceBase+al::to_underlying(source))) - | (1u << (DebugTypeBase+al::to_underlying(type))) - | (1u << (DebugSeverityBase+al::to_underlying(severity)))}; - auto iter = std::lower_bound(debug.mFilters.cbegin(), debug.mFilters.cend(), filter); - if(iter != debug.mFilters.cend() && *iter == filter) - return; - - if(mDebugCb) - { - auto callback = mDebugCb; - auto param = mDebugParam; - debuglock.unlock(); - callback(get_source_enum(), get_type_enum(), id, get_severity_enum(), length, message, - param); - } - else - { - if(mDebugLog.size() < MaxDebugLoggedMessages) - mDebugLog.emplace_back(source, type, id, severity, message); - else UNLIKELY - ERR("Debug message log overflow. Lost message:\n" - " Source: 0x%04x\n" - " Type: 0x%04x\n" - " ID: %u\n" - " Severity: 0x%04x\n" - " Message: \"%s\"\n", - get_source_enum(), get_type_enum(), id, get_severity_enum(), message); - } -} - - #ifdef ALSOFT_EAX namespace { diff --git a/alc/context.h b/alc/context.h index 3e31c9b8..8757b041 100644 --- a/alc/context.h +++ b/alc/context.h @@ -166,15 +166,16 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { #endif void setError(ALenum errorCode, const char *msg, ...); - void sendDebugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, - ALsizei length, const char *message); + void sendDebugMessage(std::unique_lock &debuglock, DebugSource source, + DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message); void debugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message) { if(!mDebugEnabled.load(std::memory_order_relaxed)) LIKELY return; - sendDebugMessage(source, type, id, severity, length, message); + std::unique_lock debuglock{mDebugCbLock}; + sendDebugMessage(debuglock, source, type, id, severity, length, message); } /* Process-wide current context */ diff --git a/alc/inprogext.h b/alc/inprogext.h index f73963cb..7f9d7766 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -71,25 +71,34 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_DEBUG_TYPE_PORTABILITY_SOFT 0x19BD #define AL_DEBUG_TYPE_PERFORMANCE_SOFT 0x19BE #define AL_DEBUG_TYPE_MARKER_SOFT 0x19BF -#define AL_DEBUG_TYPE_OTHER_SOFT 0x19C0 -#define AL_DEBUG_SEVERITY_HIGH_SOFT 0x19C1 -#define AL_DEBUG_SEVERITY_MEDIUM_SOFT 0x19C2 -#define AL_DEBUG_SEVERITY_LOW_SOFT 0x19C3 -#define AL_DEBUG_SEVERITY_NOTIFICATION_SOFT 0x19C4 -#define AL_DEBUG_LOGGED_MESSAGES_SOFT 0x19C5 -#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT 0x19C6 -#define AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT 0x19C7 -#define AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT 0x19C8 +#define AL_DEBUG_TYPE_PUSH_GROUP_SOFT 0x19C0 +#define AL_DEBUG_TYPE_POP_GROUP_SOFT 0x19C1 +#define AL_DEBUG_TYPE_OTHER_SOFT 0x19C2 +#define AL_DEBUG_SEVERITY_HIGH_SOFT 0x19C3 +#define AL_DEBUG_SEVERITY_MEDIUM_SOFT 0x19C4 +#define AL_DEBUG_SEVERITY_LOW_SOFT 0x19C5 +#define AL_DEBUG_SEVERITY_NOTIFICATION_SOFT 0x19C6 +#define AL_DEBUG_LOGGED_MESSAGES_SOFT 0x19C7 +#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT 0x19C8 +#define AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT 0x19C9 +#define AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT 0x19CA +#define AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT 0x19CB +#define AL_STACK_OVERFLOW_SOFT 0x19CC +#define AL_STACK_UNDERFLOW_SOFT 0x19CD typedef void (AL_APIENTRY*ALDEBUGPROCSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam); typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKSOFT)(ALDEBUGPROCSOFT callback, void *userParam); typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLSOFT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable); +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPSOFT)(ALenum source, ALuint id, ALsizei length, const ALchar *message); +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPSOFT)(void); typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGSOFT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf); #ifdef AL_ALEXT_PROTOTYPES void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept; void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept; +void AL_APIENTRY alPushDebugGroupSOFT(ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept; +void AL_APIENTRY alPopDebugGroupSOFT(void) noexcept; ALuint AL_APIENTRY alGetDebugMessageLogSOFT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept; #endif #endif -- cgit v1.2.3 From d5e5b211b89de63667eab71faa7e9a13a0b7992d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 1 May 2023 19:19:41 -0700 Subject: Define a struct where it's needed --- al/debug.h | 18 ------------------ alc/context.h | 19 ++++++++++++++++++- 2 files changed, 18 insertions(+), 19 deletions(-) (limited to 'alc') diff --git a/al/debug.h b/al/debug.h index 8f83fd5e..87bc10f6 100644 --- a/al/debug.h +++ b/al/debug.h @@ -64,22 +64,4 @@ struct DebugGroup { DebugGroup(DebugGroup&&) = default; }; - -struct DebugLogEntry { - const DebugSource mSource; - const DebugType mType; - const DebugSeverity mSeverity; - const uint mId; - - std::string mMessage; - - template - DebugLogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message) - : mSource{source}, mType{type}, mSeverity{severity}, mId{id} - , mMessage{std::forward(message)} - { } - DebugLogEntry(const DebugLogEntry&) = default; - DebugLogEntry(DebugLogEntry&&) = default; -}; - #endif /* AL_DEBUG_H */ diff --git a/alc/context.h b/alc/context.h index 8757b041..20c89a31 100644 --- a/alc/context.h +++ b/alc/context.h @@ -34,7 +34,6 @@ struct ALeffect; struct ALeffectslot; struct ALsource; struct DebugGroup; -struct DebugLogEntry; enum class DebugSource : uint8_t; enum class DebugType : uint8_t; @@ -43,6 +42,24 @@ enum class DebugSeverity : uint8_t; using uint = unsigned int; +struct DebugLogEntry { + const DebugSource mSource; + const DebugType mType; + const DebugSeverity mSeverity; + const uint mId; + + std::string mMessage; + + template + DebugLogEntry(DebugSource source, DebugType type, uint id, DebugSeverity severity, T&& message) + : mSource{source}, mType{type}, mSeverity{severity}, mId{id} + , mMessage{std::forward(message)} + { } + DebugLogEntry(const DebugLogEntry&) = default; + DebugLogEntry(DebugLogEntry&&) = default; +}; + + struct SourceSubList { uint64_t FreeMask{~0_u64}; ALsource *Sources{nullptr}; /* 64 */ -- cgit v1.2.3 From f80324873992887f518d97dfb388bbb78079377e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 1 May 2023 21:10:30 -0700 Subject: Reduce code duplication for context queries --- al/state.cpp | 599 ++++++++++++++++++---------------------------------------- alc/context.h | 1 + 2 files changed, 180 insertions(+), 420 deletions(-) (limited to 'alc') diff --git a/al/state.cpp b/al/state.cpp index 2a350646..7f75268f 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -136,6 +136,142 @@ ALenum ALenumFromDistanceModel(DistanceModel model) throw std::runtime_error{"Unexpected distance model "+std::to_string(static_cast(model))}; } +enum PropertyValue : ALenum { + DopplerFactor = AL_DOPPLER_FACTOR, + DopplerVelocity = AL_DOPPLER_VELOCITY, + DistanceModel = AL_DISTANCE_MODEL, + SpeedOfSound = AL_SPEED_OF_SOUND, + DeferredUpdates = AL_DEFERRED_UPDATES_SOFT, + GainLimit = AL_GAIN_LIMIT_SOFT, + NumResamplers = AL_NUM_RESAMPLERS_SOFT, + DefaultResampler = AL_DEFAULT_RESAMPLER_SOFT, + DebugLoggedMessages = AL_DEBUG_LOGGED_MESSAGES_SOFT, + DebugNextLoggedMessageLength = AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT, + MaxDebugMessageLength = AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT, + MaxDebugLoggedMessages = AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT, + MaxDebugGroupDepth = AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT, +#ifdef ALSOFT_EAX + EaxRamSize = AL_EAX_RAM_SIZE, + EaxRamFree = AL_EAX_RAM_FREE, +#endif +}; + +template +struct PropertyCastType { + template + constexpr auto operator()(U&& value) const noexcept + { return static_cast(std::forward(value)); } +}; +/* Special-case ALboolean to be an actual bool instead of a char type. */ +template<> +struct PropertyCastType { + template + constexpr ALboolean operator()(U&& value) const noexcept + { return static_cast(std::forward(value)) ? AL_TRUE : AL_FALSE; } +}; + + +template +void GetValue(ALCcontext *context, ALenum pname, T *values) +{ + auto cast_value = PropertyCastType{}; + + switch(static_cast(pname)) + { + case AL_DOPPLER_FACTOR: + *values = cast_value(context->mDopplerFactor); + return; + + case AL_DOPPLER_VELOCITY: + context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + DebugSeverity::Medium, -1, + "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; " + "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f"); + *values = cast_value(context->mDopplerVelocity); + return; + + case AL_SPEED_OF_SOUND: + *values = cast_value(context->mSpeedOfSound); + return; + + case AL_GAIN_LIMIT_SOFT: + *values = cast_value(GainMixMax / context->mGainBoost); + return; + + case AL_DEFERRED_UPDATES_SOFT: + *values = cast_value(context->mDeferUpdates ? AL_TRUE : AL_FALSE); + return; + + case AL_DISTANCE_MODEL: + *values = cast_value(ALenumFromDistanceModel(context->mDistanceModel)); + return; + + case AL_NUM_RESAMPLERS_SOFT: + *values = cast_value(al::to_underlying(Resampler::Max) + 1); + return; + + case AL_DEFAULT_RESAMPLER_SOFT: + *values = cast_value(al::to_underlying(ResamplerDefault)); + return; + + case AL_DEBUG_LOGGED_MESSAGES_SOFT: + { + std::lock_guard _{context->mDebugCbLock}; + *values = cast_value(context->mDebugLog.size()); + return; + } + + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + { + std::lock_guard _{context->mDebugCbLock}; + *values = cast_value(context->mDebugLog.empty() ? size_t{0} + : (context->mDebugLog.front().mMessage.size()+1)); + return; + } + + case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + *values = cast_value(MaxDebugMessageLength); + return; + + case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + *values = cast_value(MaxDebugLoggedMessages); + return; + + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: + *values = cast_value(MaxDebugGroupDepth); + return; + +#ifdef ALSOFT_EAX + +#define EAX_ERROR "[alGetInteger] EAX not enabled." + + case AL_EAX_RAM_SIZE: + if(eax_g_is_enabled) + { + *values = cast_value(eax_x_ram_max_size); + return; + } + context->setError(AL_INVALID_ENUM, EAX_ERROR); + return; + + case AL_EAX_RAM_FREE: + if(eax_g_is_enabled) + { + auto device = context->mALDevice.get(); + std::lock_guard device_lock{device->BufferLock}; + *values = cast_value(device->eax_x_ram_free_size); + return; + } + context->setError(AL_INVALID_ENUM, EAX_ERROR); + return; + +#undef EAX_ERROR + +#endif // ALSOFT_EAX + } + context->setError(AL_INVALID_ENUM, "Invalid context property 0x%04x", pname); +} + } // namespace /* WARNING: Non-standard export! Not part of any extension, or exposed in the @@ -251,41 +387,8 @@ END_API_FUNC AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname) START_API_FUNC { - switch(pname) - { - case AL_DOPPLER_FACTOR: - case AL_DOPPLER_VELOCITY: - case AL_SPEED_OF_SOUND: - case AL_GAIN_LIMIT_SOFT: - return alGetFloat(pname) != 0.0f; - - case AL_DISTANCE_MODEL: - case AL_NUM_RESAMPLERS_SOFT: - case AL_DEFAULT_RESAMPLER_SOFT: - case AL_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: - return alGetInteger(pname) != 0; - } - - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return AL_FALSE; - - std::lock_guard _{context->mPropLock}; ALboolean value{AL_FALSE}; - switch(pname) - { - case AL_DEFERRED_UPDATES_SOFT: - if(context->mDeferUpdates) - value = AL_TRUE; - break; - - default: - context->setError(AL_INVALID_VALUE, "Invalid boolean property 0x%04x", pname); - } - + alGetBooleanv(pname, &value); return value; } END_API_FUNC @@ -293,39 +396,8 @@ END_API_FUNC AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname) START_API_FUNC { - switch(pname) - { - case AL_DOPPLER_FACTOR: - case AL_DOPPLER_VELOCITY: - case AL_SPEED_OF_SOUND: - case AL_GAIN_LIMIT_SOFT: - return alGetFloat(pname); - - case AL_DEFERRED_UPDATES_SOFT: - return alGetBoolean(pname) ? 1.0 : 0.0; - - case AL_DISTANCE_MODEL: - case AL_NUM_RESAMPLERS_SOFT: - case AL_DEFAULT_RESAMPLER_SOFT: - case AL_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: - return alGetInteger(pname); - } - - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return 0.0; - - std::lock_guard _{context->mPropLock}; ALdouble value{0.0}; - switch(pname) - { - default: - context->setError(AL_INVALID_VALUE, "Invalid double property 0x%04x", pname); - } - + alGetDoublev(pname, &value); return value; } END_API_FUNC @@ -333,53 +405,8 @@ END_API_FUNC AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname) START_API_FUNC { - switch(pname) - { - case AL_DISTANCE_MODEL: - case AL_NUM_RESAMPLERS_SOFT: - case AL_DEFAULT_RESAMPLER_SOFT: - case AL_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: - return static_cast(alGetInteger(pname)); - - case AL_DEFERRED_UPDATES_SOFT: - return alGetBoolean(pname) ? 1.0f : 0.0f; - } - - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return 0.0f; - - std::lock_guard _{context->mPropLock}; ALfloat value{0.0f}; - switch(pname) - { - case AL_DOPPLER_FACTOR: - value = context->mDopplerFactor; - break; - - case AL_DOPPLER_VELOCITY: - context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, - DebugSeverity::Medium, -1, - "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; " - "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f"); - value = context->mDopplerVelocity; - break; - - case AL_SPEED_OF_SOUND: - value = context->mSpeedOfSound; - break; - - case AL_GAIN_LIMIT_SOFT: - value = GainMixMax / context->mGainBoost; - break; - - default: - context->setError(AL_INVALID_VALUE, "Invalid float property 0x%04x", pname); - } - + alGetFloatv(pname, &value); return value; } END_API_FUNC @@ -387,94 +414,8 @@ END_API_FUNC AL_API ALint AL_APIENTRY alGetInteger(ALenum pname) START_API_FUNC { - switch(pname) - { - case AL_DOPPLER_FACTOR: - case AL_DOPPLER_VELOCITY: - case AL_SPEED_OF_SOUND: - case AL_GAIN_LIMIT_SOFT: - return static_cast(alGetFloat(pname)); - - case AL_DEFERRED_UPDATES_SOFT: - return alGetBoolean(pname); - } - - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return 0; - - std::lock_guard _{context->mPropLock}; ALint value{0}; - switch(pname) - { - case AL_DISTANCE_MODEL: - value = ALenumFromDistanceModel(context->mDistanceModel); - break; - - case AL_NUM_RESAMPLERS_SOFT: - value = al::to_underlying(Resampler::Max) + 1; - break; - - case AL_DEFAULT_RESAMPLER_SOFT: - value = al::to_underlying(ResamplerDefault); - break; - - case AL_DEBUG_LOGGED_MESSAGES_SOFT: - { - std::lock_guard __{context->mDebugCbLock}; - value = static_cast(context->mDebugLog.size()); - break; - } - - case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: - { - std::lock_guard __{context->mDebugCbLock}; - value = context->mDebugLog.empty() ? 0 - : static_cast(context->mDebugLog.front().mMessage.size()+1); - break; - } - - case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: - value = MaxDebugMessageLength; - break; - - case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: - value = MaxDebugLoggedMessages; - break; - - case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: - value = MaxDebugGroupDepth; - break; - -#ifdef ALSOFT_EAX - -#define EAX_ERROR "[alGetInteger] EAX not enabled." - - case AL_EAX_RAM_SIZE: - if(eax_g_is_enabled) - value = eax_x_ram_max_size; - else - context->setError(AL_INVALID_VALUE, EAX_ERROR); - break; - - case AL_EAX_RAM_FREE: - if(eax_g_is_enabled) - { - auto device = context->mALDevice.get(); - std::lock_guard device_lock{device->BufferLock}; - value = static_cast(device->eax_x_ram_free_size); - } - else - context->setError(AL_INVALID_VALUE, EAX_ERROR); - break; - -#undef EAX_ERROR - -#endif // ALSOFT_EAX - - default: - context->setError(AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname); - } - + alGetIntegerv(pname, &value); return value; } END_API_FUNC @@ -482,39 +423,8 @@ END_API_FUNC AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname) START_API_FUNC { - switch(pname) - { - case AL_DOPPLER_FACTOR: - case AL_DOPPLER_VELOCITY: - case AL_SPEED_OF_SOUND: - case AL_GAIN_LIMIT_SOFT: - return static_cast(alGetFloat(pname)); - - case AL_DEFERRED_UPDATES_SOFT: - return alGetBoolean(pname); - - case AL_DISTANCE_MODEL: - case AL_NUM_RESAMPLERS_SOFT: - case AL_DEFAULT_RESAMPLER_SOFT: - case AL_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: - return alGetInteger(pname); - } - - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return 0_i64; - - std::lock_guard _{context->mPropLock}; ALint64SOFT value{0}; - switch(pname) - { - default: - context->setError(AL_INVALID_VALUE, "Invalid integer64 property 0x%04x", pname); - } - + alGetInteger64vSOFT(pname, &value); return value; } END_API_FUNC @@ -522,33 +432,8 @@ END_API_FUNC AL_API ALvoid* AL_APIENTRY alGetPointerSOFT(ALenum pname) START_API_FUNC { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return nullptr; - - std::lock_guard _{context->mPropLock}; - void *value{nullptr}; - switch(pname) - { - case AL_EVENT_CALLBACK_FUNCTION_SOFT: - value = reinterpret_cast(context->mEventCb); - break; - - case AL_EVENT_CALLBACK_USER_PARAM_SOFT: - value = context->mEventParam; - break; - - case AL_DEBUG_CALLBACK_FUNCTION_SOFT: - value = reinterpret_cast(context->mDebugCb); - break; - - case AL_DEBUG_CALLBACK_USER_PARAM_SOFT: - value = context->mDebugParam; - break; - - default: - context->setError(AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname); - } - + ALvoid *value{nullptr}; + alGetPointervSOFT(pname, &value); return value; } END_API_FUNC @@ -556,218 +441,92 @@ END_API_FUNC AL_API void AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values) START_API_FUNC { - if(values) - { - switch(pname) - { - case AL_DOPPLER_FACTOR: - case AL_DOPPLER_VELOCITY: - case AL_DISTANCE_MODEL: - case AL_SPEED_OF_SOUND: - case AL_DEFERRED_UPDATES_SOFT: - case AL_GAIN_LIMIT_SOFT: - case AL_NUM_RESAMPLERS_SOFT: - case AL_DEFAULT_RESAMPLER_SOFT: - case AL_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: - values[0] = alGetBoolean(pname); - return; - } - } - ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - if(!values) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(pname) - { - default: - context->setError(AL_INVALID_VALUE, "Invalid boolean-vector property 0x%04x", pname); - } + if(!values) UNLIKELY + return context->setError(AL_INVALID_VALUE, "NULL pointer"); + GetValue(context.get(), pname, values); } END_API_FUNC AL_API void AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values) START_API_FUNC { - if(values) - { - switch(pname) - { - case AL_DOPPLER_FACTOR: - case AL_DOPPLER_VELOCITY: - case AL_DISTANCE_MODEL: - case AL_SPEED_OF_SOUND: - case AL_DEFERRED_UPDATES_SOFT: - case AL_GAIN_LIMIT_SOFT: - case AL_NUM_RESAMPLERS_SOFT: - case AL_DEFAULT_RESAMPLER_SOFT: - case AL_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: - values[0] = alGetDouble(pname); - return; - } - } - ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - if(!values) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(pname) - { - default: - context->setError(AL_INVALID_VALUE, "Invalid double-vector property 0x%04x", pname); - } + if(!values) UNLIKELY + return context->setError(AL_INVALID_VALUE, "NULL pointer"); + GetValue(context.get(), pname, values); } END_API_FUNC AL_API void AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values) START_API_FUNC { - if(values) - { - switch(pname) - { - case AL_DOPPLER_FACTOR: - case AL_DOPPLER_VELOCITY: - case AL_DISTANCE_MODEL: - case AL_SPEED_OF_SOUND: - case AL_DEFERRED_UPDATES_SOFT: - case AL_GAIN_LIMIT_SOFT: - case AL_NUM_RESAMPLERS_SOFT: - case AL_DEFAULT_RESAMPLER_SOFT: - case AL_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: - values[0] = alGetFloat(pname); - return; - } - } - ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - if(!values) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(pname) - { - default: - context->setError(AL_INVALID_VALUE, "Invalid float-vector property 0x%04x", pname); - } + if(!values) UNLIKELY + return context->setError(AL_INVALID_VALUE, "NULL pointer"); + GetValue(context.get(), pname, values); } END_API_FUNC AL_API void AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values) START_API_FUNC { - if(values) - { - switch(pname) - { - case AL_DOPPLER_FACTOR: - case AL_DOPPLER_VELOCITY: - case AL_DISTANCE_MODEL: - case AL_SPEED_OF_SOUND: - case AL_DEFERRED_UPDATES_SOFT: - case AL_GAIN_LIMIT_SOFT: - case AL_NUM_RESAMPLERS_SOFT: - case AL_DEFAULT_RESAMPLER_SOFT: - case AL_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: - values[0] = alGetInteger(pname); - return; - } - } - ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - if(!values) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(pname) - { - default: - context->setError(AL_INVALID_VALUE, "Invalid integer-vector property 0x%04x", pname); - } + if(!values) UNLIKELY + return context->setError(AL_INVALID_VALUE, "NULL pointer"); + GetValue(context.get(), pname, values); } END_API_FUNC AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values) START_API_FUNC { - if(values) - { - switch(pname) - { - case AL_DOPPLER_FACTOR: - case AL_DOPPLER_VELOCITY: - case AL_DISTANCE_MODEL: - case AL_SPEED_OF_SOUND: - case AL_DEFERRED_UPDATES_SOFT: - case AL_GAIN_LIMIT_SOFT: - case AL_NUM_RESAMPLERS_SOFT: - case AL_DEFAULT_RESAMPLER_SOFT: - case AL_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: - case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: - case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: - values[0] = alGetInteger64SOFT(pname); - return; - } - } - ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - if(!values) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(pname) - { - default: - context->setError(AL_INVALID_VALUE, "Invalid integer64-vector property 0x%04x", pname); - } + if(!values) UNLIKELY + return context->setError(AL_INVALID_VALUE, "NULL pointer"); + GetValue(context.get(), pname, values); } END_API_FUNC AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, ALvoid **values) START_API_FUNC { - if(values) - { - switch(pname) - { - case AL_EVENT_CALLBACK_FUNCTION_SOFT: - case AL_EVENT_CALLBACK_USER_PARAM_SOFT: - case AL_DEBUG_CALLBACK_FUNCTION_SOFT: - case AL_DEBUG_CALLBACK_USER_PARAM_SOFT: - values[0] = alGetPointerSOFT(pname); - return; - } - } - ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - if(!values) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(pname) + if(!values) UNLIKELY + return context->setError(AL_INVALID_VALUE, "NULL pointer"); + + switch(pname) { + case AL_EVENT_CALLBACK_FUNCTION_SOFT: + *values = reinterpret_cast(context->mEventCb); + break; + + case AL_EVENT_CALLBACK_USER_PARAM_SOFT: + *values = context->mEventParam; + break; + + case AL_DEBUG_CALLBACK_FUNCTION_SOFT: + *values = reinterpret_cast(context->mDebugCb); + break; + + case AL_DEBUG_CALLBACK_USER_PARAM_SOFT: + *values = context->mDebugParam; + break; + default: - context->setError(AL_INVALID_VALUE, "Invalid pointer-vector property 0x%04x", pname); + context->setError(AL_INVALID_ENUM, "Invalid context pointer property 0x%04x", pname); } } END_API_FUNC diff --git a/alc/context.h b/alc/context.h index 20c89a31..d74bc8d1 100644 --- a/alc/context.h +++ b/alc/context.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 4739b77b8a20800b24b6187dca9aedca5fac367b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 3 May 2023 07:03:07 -0700 Subject: Rename AL_SOFT_debug to AL_EXT_DEBUG --- al/debug.cpp | 159 +++++++++++++++++++++++++++++++++++--------------------- al/state.cpp | 34 ++++++------ alc/alc.cpp | 70 ++++++++++++------------- alc/context.cpp | 2 +- alc/context.h | 2 +- alc/inprogext.h | 88 +++++++++++++++---------------- 6 files changed, 199 insertions(+), 156 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index 2dd0e7c7..f584da99 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -39,11 +39,11 @@ constexpr al::optional GetDebugSource(ALenum source) noexcept { switch(source) { - case AL_DEBUG_SOURCE_API_SOFT: return DebugSource::API; - case AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT: return DebugSource::System; - case AL_DEBUG_SOURCE_THIRD_PARTY_SOFT: return DebugSource::ThirdParty; - case AL_DEBUG_SOURCE_APPLICATION_SOFT: return DebugSource::Application; - case AL_DEBUG_SOURCE_OTHER_SOFT: return DebugSource::Other; + case AL_DEBUG_SOURCE_API_EXT: return DebugSource::API; + case AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT: return DebugSource::System; + case AL_DEBUG_SOURCE_THIRD_PARTY_EXT: return DebugSource::ThirdParty; + case AL_DEBUG_SOURCE_APPLICATION_EXT: return DebugSource::Application; + case AL_DEBUG_SOURCE_OTHER_EXT: return DebugSource::Other; } return al::nullopt; } @@ -52,15 +52,15 @@ constexpr al::optional GetDebugType(ALenum type) noexcept { switch(type) { - case AL_DEBUG_TYPE_ERROR_SOFT: return DebugType::Error; - case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT: return DebugType::DeprecatedBehavior; - case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT: return DebugType::UndefinedBehavior; - case AL_DEBUG_TYPE_PORTABILITY_SOFT: return DebugType::Portability; - case AL_DEBUG_TYPE_PERFORMANCE_SOFT: return DebugType::Performance; - case AL_DEBUG_TYPE_MARKER_SOFT: return DebugType::Marker; - case AL_DEBUG_TYPE_PUSH_GROUP_SOFT: return DebugType::PushGroup; - case AL_DEBUG_TYPE_POP_GROUP_SOFT: return DebugType::PopGroup; - case AL_DEBUG_TYPE_OTHER_SOFT: return DebugType::Other; + case AL_DEBUG_TYPE_ERROR_EXT: return DebugType::Error; + case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT: return DebugType::DeprecatedBehavior; + case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT: return DebugType::UndefinedBehavior; + case AL_DEBUG_TYPE_PORTABILITY_EXT: return DebugType::Portability; + case AL_DEBUG_TYPE_PERFORMANCE_EXT: return DebugType::Performance; + case AL_DEBUG_TYPE_MARKER_EXT: return DebugType::Marker; + case AL_DEBUG_TYPE_PUSH_GROUP_EXT: return DebugType::PushGroup; + case AL_DEBUG_TYPE_POP_GROUP_EXT: return DebugType::PopGroup; + case AL_DEBUG_TYPE_OTHER_EXT: return DebugType::Other; } return al::nullopt; } @@ -69,10 +69,10 @@ constexpr al::optional GetDebugSeverity(ALenum severity) noexcept { switch(severity) { - case AL_DEBUG_SEVERITY_HIGH_SOFT: return DebugSeverity::High; - case AL_DEBUG_SEVERITY_MEDIUM_SOFT: return DebugSeverity::Medium; - case AL_DEBUG_SEVERITY_LOW_SOFT: return DebugSeverity::Low; - case AL_DEBUG_SEVERITY_NOTIFICATION_SOFT: return DebugSeverity::Notification; + case AL_DEBUG_SEVERITY_HIGH_EXT: return DebugSeverity::High; + case AL_DEBUG_SEVERITY_MEDIUM_EXT: return DebugSeverity::Medium; + case AL_DEBUG_SEVERITY_LOW_EXT: return DebugSeverity::Low; + case AL_DEBUG_SEVERITY_NOTIFICATION_EXT: return DebugSeverity::Notification; } return al::nullopt; } @@ -82,11 +82,11 @@ ALenum GetDebugSourceEnum(DebugSource source) { switch(source) { - case DebugSource::API: return AL_DEBUG_SOURCE_API_SOFT; - case DebugSource::System: return AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT; - case DebugSource::ThirdParty: return AL_DEBUG_SOURCE_THIRD_PARTY_SOFT; - case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_SOFT; - case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_SOFT; + case DebugSource::API: return AL_DEBUG_SOURCE_API_EXT; + case DebugSource::System: return AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT; + case DebugSource::ThirdParty: return AL_DEBUG_SOURCE_THIRD_PARTY_EXT; + case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_EXT; + case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_EXT; } throw std::runtime_error{"Unexpected debug source value "+std::to_string(al::to_underlying(source))}; } @@ -95,15 +95,15 @@ ALenum GetDebugTypeEnum(DebugType type) { switch(type) { - case DebugType::Error: return AL_DEBUG_TYPE_ERROR_SOFT; - case DebugType::DeprecatedBehavior: return AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT; - case DebugType::UndefinedBehavior: return AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT; - case DebugType::Portability: return AL_DEBUG_TYPE_PORTABILITY_SOFT; - case DebugType::Performance: return AL_DEBUG_TYPE_PERFORMANCE_SOFT; - case DebugType::Marker: return AL_DEBUG_TYPE_MARKER_SOFT; - case DebugType::PushGroup: return AL_DEBUG_TYPE_PUSH_GROUP_SOFT; - case DebugType::PopGroup: return AL_DEBUG_TYPE_POP_GROUP_SOFT; - case DebugType::Other: return AL_DEBUG_TYPE_OTHER_SOFT; + case DebugType::Error: return AL_DEBUG_TYPE_ERROR_EXT; + case DebugType::DeprecatedBehavior: return AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT; + case DebugType::UndefinedBehavior: return AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT; + case DebugType::Portability: return AL_DEBUG_TYPE_PORTABILITY_EXT; + case DebugType::Performance: return AL_DEBUG_TYPE_PERFORMANCE_EXT; + case DebugType::Marker: return AL_DEBUG_TYPE_MARKER_EXT; + case DebugType::PushGroup: return AL_DEBUG_TYPE_PUSH_GROUP_EXT; + case DebugType::PopGroup: return AL_DEBUG_TYPE_POP_GROUP_EXT; + case DebugType::Other: return AL_DEBUG_TYPE_OTHER_EXT; } throw std::runtime_error{"Unexpected debug type value "+std::to_string(al::to_underlying(type))}; } @@ -112,14 +112,57 @@ ALenum GetDebugSeverityEnum(DebugSeverity severity) { switch(severity) { - case DebugSeverity::High: return AL_DEBUG_SEVERITY_HIGH_SOFT; - case DebugSeverity::Medium: return AL_DEBUG_SEVERITY_MEDIUM_SOFT; - case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_SOFT; - case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_SOFT; + case DebugSeverity::High: return AL_DEBUG_SEVERITY_HIGH_EXT; + case DebugSeverity::Medium: return AL_DEBUG_SEVERITY_MEDIUM_EXT; + case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_EXT; + case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_EXT; } throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; } + +const char *GetDebugSourceName(DebugSource source) +{ + switch(source) + { + case DebugSource::API: return "API"; + case DebugSource::System: return "Audio System"; + case DebugSource::ThirdParty: return "Third Party"; + case DebugSource::Application: return "Application"; + case DebugSource::Other: return "Other"; + } + return ""; +} + +const char *GetDebugTypeName(DebugType type) +{ + switch(type) + { + case DebugType::Error: return "Error"; + case DebugType::DeprecatedBehavior: return "Deprecated Behavior"; + case DebugType::UndefinedBehavior: return "Undefined Behavior"; + case DebugType::Portability: return "Portability"; + case DebugType::Performance: return "Performance"; + case DebugType::Marker: return "Marker"; + case DebugType::PushGroup: return "Push Group"; + case DebugType::PopGroup: return "Pop Group"; + case DebugType::Other: return "Other"; + } + return ""; +} + +const char *GetDebugSeverityName(DebugSeverity severity) +{ + switch(severity) + { + case DebugSeverity::High: return "High"; + case DebugSeverity::Medium: return "Medium"; + case DebugSeverity::Low: return "Low"; + case DebugSeverity::Notification: return "Notification"; + } + return ""; +} + } // namespace @@ -178,18 +221,18 @@ void ALCcontext::sendDebugMessage(std::unique_lock &debuglock, Debug mDebugLog.emplace_back(source, type, id, severity, message); else UNLIKELY ERR("Debug message log overflow. Lost message:\n" - " Source: 0x%04x\n" - " Type: 0x%04x\n" + " Source: %s\n" + " Type: %s\n" " ID: %u\n" - " Severity: 0x%04x\n" + " Severity: %s\n" " Message: \"%s\"\n", - GetDebugSourceEnum(source), GetDebugTypeEnum(type), id, - GetDebugSeverityEnum(severity), message); + GetDebugSourceName(source), GetDebugTypeName(type), id, + GetDebugSeverityName(severity), message); } } -FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept +FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; @@ -199,7 +242,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback context->mDebugParam = userParam; } -FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type, ALuint id, +FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept { ContextRef context{GetContextRef()}; @@ -238,7 +281,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type } -FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, +FORCE_ALIGN void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept { ContextRef context{GetContextRef()}; @@ -248,15 +291,15 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ { if(!ids) return context->setError(AL_INVALID_VALUE, "IDs is null with non-0 count"); - if(source == AL_DONT_CARE_SOFT) + if(source == AL_DONT_CARE_EXT) return context->setError(AL_INVALID_OPERATION, - "Debug source cannot be AL_DONT_CARE_SOFT with IDs"); - if(type == AL_DONT_CARE_SOFT) + "Debug source cannot be AL_DONT_CARE_EXT with IDs"); + if(type == AL_DONT_CARE_EXT) return context->setError(AL_INVALID_OPERATION, - "Debug type cannot be AL_DONT_CARE_SOFT with IDs"); - if(severity != AL_DONT_CARE_SOFT) + "Debug type cannot be AL_DONT_CARE_EXT with IDs"); + if(severity != AL_DONT_CARE_EXT) return context->setError(AL_INVALID_OPERATION, - "Debug severity must be AL_DONT_CARE_SOFT with IDs"); + "Debug severity must be AL_DONT_CARE_EXT with IDs"); } if(enable != AL_TRUE && enable != AL_FALSE) @@ -266,7 +309,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ static constexpr auto Values = make_array(); al::span srcIndices{al::as_span(Values).subspan()}; - if(source != AL_DONT_CARE_SOFT) + if(source != AL_DONT_CARE_EXT) { auto dsource = GetDebugSource(source); if(!dsource) @@ -275,7 +318,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ } al::span typeIndices{al::as_span(Values).subspan()}; - if(type != AL_DONT_CARE_SOFT) + if(type != AL_DONT_CARE_EXT) { auto dtype = GetDebugType(type); if(!dtype) @@ -284,7 +327,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ } al::span svrIndices{al::as_span(Values).subspan()}; - if(severity != AL_DONT_CARE_SOFT) + if(severity != AL_DONT_CARE_EXT) { auto dseverity = GetDebugSeverity(severity); if(!dseverity) @@ -336,7 +379,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum typ } -FORCE_ALIGN void AL_APIENTRY alPushDebugGroupSOFT(ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept +FORCE_ALIGN void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; @@ -363,7 +406,7 @@ FORCE_ALIGN void AL_APIENTRY alPushDebugGroupSOFT(ALenum source, ALuint id, ALsi if(context->mDebugGroups.size() >= MaxDebugGroupDepth) { debuglock.unlock(); - return context->setError(AL_STACK_OVERFLOW_SOFT, "Pushing too many debug groups"); + return context->setError(AL_STACK_OVERFLOW_EXT, "Pushing too many debug groups"); } context->mDebugGroups.emplace_back(*dsource, id, message); @@ -378,7 +421,7 @@ FORCE_ALIGN void AL_APIENTRY alPushDebugGroupSOFT(ALenum source, ALuint id, ALsi newback.mMessage.data()); } -FORCE_ALIGN void AL_APIENTRY alPopDebugGroupSOFT(void) noexcept +FORCE_ALIGN void AL_APIENTRY alPopDebugGroupEXT(void) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; @@ -387,7 +430,7 @@ FORCE_ALIGN void AL_APIENTRY alPopDebugGroupSOFT(void) noexcept if(context->mDebugGroups.size() <= 1) { debuglock.unlock(); - return context->setError(AL_STACK_UNDERFLOW_SOFT, + return context->setError(AL_STACK_UNDERFLOW_EXT, "Attempting to pop the default debug group"); } @@ -402,7 +445,7 @@ FORCE_ALIGN void AL_APIENTRY alPopDebugGroupSOFT(void) noexcept } -FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogSOFT(ALuint count, ALsizei logBufSize, +FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept { diff --git a/al/state.cpp b/al/state.cpp index 7f75268f..71c9b703 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -145,11 +145,11 @@ enum PropertyValue : ALenum { GainLimit = AL_GAIN_LIMIT_SOFT, NumResamplers = AL_NUM_RESAMPLERS_SOFT, DefaultResampler = AL_DEFAULT_RESAMPLER_SOFT, - DebugLoggedMessages = AL_DEBUG_LOGGED_MESSAGES_SOFT, - DebugNextLoggedMessageLength = AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT, - MaxDebugMessageLength = AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT, - MaxDebugLoggedMessages = AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT, - MaxDebugGroupDepth = AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT, + DebugLoggedMessages = AL_DEBUG_LOGGED_MESSAGES_EXT, + DebugNextLoggedMessageLength = AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT, + MaxDebugMessageLength = AL_MAX_DEBUG_MESSAGE_LENGTH_EXT, + MaxDebugLoggedMessages = AL_MAX_DEBUG_LOGGED_MESSAGES_EXT, + MaxDebugGroupDepth = AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT, #ifdef ALSOFT_EAX EaxRamSize = AL_EAX_RAM_SIZE, EaxRamFree = AL_EAX_RAM_FREE, @@ -214,14 +214,14 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) *values = cast_value(al::to_underlying(ResamplerDefault)); return; - case AL_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_DEBUG_LOGGED_MESSAGES_EXT: { std::lock_guard _{context->mDebugCbLock}; *values = cast_value(context->mDebugLog.size()); return; } - case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT: + case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT: { std::lock_guard _{context->mDebugCbLock}; *values = cast_value(context->mDebugLog.empty() ? size_t{0} @@ -229,15 +229,15 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) return; } - case AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT: + case AL_MAX_DEBUG_MESSAGE_LENGTH_EXT: *values = cast_value(MaxDebugMessageLength); return; - case AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT: + case AL_MAX_DEBUG_LOGGED_MESSAGES_EXT: *values = cast_value(MaxDebugLoggedMessages); return; - case AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT: + case AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT: *values = cast_value(MaxDebugGroupDepth); return; @@ -310,7 +310,7 @@ START_API_FUNC } break; - case AL_DEBUG_OUTPUT_SOFT: + case AL_DEBUG_OUTPUT_EXT: context->mDebugEnabled = true; break; @@ -340,7 +340,7 @@ START_API_FUNC } break; - case AL_DEBUG_OUTPUT_SOFT: + case AL_DEBUG_OUTPUT_EXT: context->mDebugEnabled = false; break; @@ -368,7 +368,7 @@ START_API_FUNC value = context->mSourceDistanceModel ? AL_TRUE : AL_FALSE; break; - case AL_DEBUG_OUTPUT_SOFT: + case AL_DEBUG_OUTPUT_EXT: value = context->mDebugEnabled ? AL_TRUE : AL_FALSE; break; @@ -517,11 +517,11 @@ START_API_FUNC *values = context->mEventParam; break; - case AL_DEBUG_CALLBACK_FUNCTION_SOFT: + case AL_DEBUG_CALLBACK_FUNCTION_EXT: *values = reinterpret_cast(context->mDebugCb); break; - case AL_DEBUG_CALLBACK_USER_PARAM_SOFT: + case AL_DEBUG_CALLBACK_USER_PARAM_EXT: *values = context->mDebugParam; break; @@ -580,11 +580,11 @@ START_API_FUNC value = alErrOutOfMemory; break; - case AL_STACK_OVERFLOW_SOFT: + case AL_STACK_OVERFLOW_EXT: value = alStackOverflow; break; - case AL_STACK_UNDERFLOW_SOFT: + case AL_STACK_UNDERFLOW_EXT: value = alStackUnderflow; break; diff --git a/alc/alc.cpp b/alc/alc.cpp index 50982ed2..de5bc232 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -461,12 +461,12 @@ const struct { DECL(alBufferDataStatic), - DECL(alDebugMessageCallbackSOFT), - DECL(alDebugMessageInsertSOFT), - DECL(alDebugMessageControlSOFT), - DECL(alPushDebugGroupSOFT), - DECL(alPopDebugGroupSOFT), - DECL(alGetDebugMessageLogSOFT), + DECL(alDebugMessageCallbackEXT), + DECL(alDebugMessageInsertEXT), + DECL(alDebugMessageControlEXT), + DECL(alPushDebugGroupEXT), + DECL(alPopDebugGroupEXT), + DECL(alGetDebugMessageLogEXT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), @@ -923,35 +923,35 @@ constexpr struct { DECL(AL_FORMAT_UHJ4CHN_MULAW_SOFT), DECL(AL_FORMAT_UHJ4CHN_ALAW_SOFT), - DECL(AL_DONT_CARE_SOFT), - DECL(AL_DEBUG_OUTPUT_SOFT), - DECL(AL_DEBUG_CALLBACK_FUNCTION_SOFT), - DECL(AL_DEBUG_CALLBACK_USER_PARAM_SOFT), - DECL(AL_DEBUG_SOURCE_API_SOFT), - DECL(AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT), - DECL(AL_DEBUG_SOURCE_THIRD_PARTY_SOFT), - DECL(AL_DEBUG_SOURCE_APPLICATION_SOFT), - DECL(AL_DEBUG_SOURCE_OTHER_SOFT), - DECL(AL_DEBUG_TYPE_ERROR_SOFT), - DECL(AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT), - DECL(AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT), - DECL(AL_DEBUG_TYPE_PORTABILITY_SOFT), - DECL(AL_DEBUG_TYPE_PERFORMANCE_SOFT), - DECL(AL_DEBUG_TYPE_MARKER_SOFT), - DECL(AL_DEBUG_TYPE_PUSH_GROUP_SOFT), - DECL(AL_DEBUG_TYPE_POP_GROUP_SOFT), - DECL(AL_DEBUG_TYPE_OTHER_SOFT), - DECL(AL_DEBUG_SEVERITY_HIGH_SOFT), - DECL(AL_DEBUG_SEVERITY_MEDIUM_SOFT), - DECL(AL_DEBUG_SEVERITY_LOW_SOFT), - DECL(AL_DEBUG_SEVERITY_NOTIFICATION_SOFT), - DECL(AL_DEBUG_LOGGED_MESSAGES_SOFT), - DECL(AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT), - DECL(AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT), - DECL(AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT), - DECL(AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT), - DECL(AL_STACK_OVERFLOW_SOFT), - DECL(AL_STACK_UNDERFLOW_SOFT), + DECL(AL_DONT_CARE_EXT), + DECL(AL_DEBUG_OUTPUT_EXT), + DECL(AL_DEBUG_CALLBACK_FUNCTION_EXT), + DECL(AL_DEBUG_CALLBACK_USER_PARAM_EXT), + DECL(AL_DEBUG_SOURCE_API_EXT), + DECL(AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT), + DECL(AL_DEBUG_SOURCE_THIRD_PARTY_EXT), + DECL(AL_DEBUG_SOURCE_APPLICATION_EXT), + DECL(AL_DEBUG_SOURCE_OTHER_EXT), + DECL(AL_DEBUG_TYPE_ERROR_EXT), + DECL(AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT), + DECL(AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT), + DECL(AL_DEBUG_TYPE_PORTABILITY_EXT), + DECL(AL_DEBUG_TYPE_PERFORMANCE_EXT), + DECL(AL_DEBUG_TYPE_MARKER_EXT), + DECL(AL_DEBUG_TYPE_PUSH_GROUP_EXT), + DECL(AL_DEBUG_TYPE_POP_GROUP_EXT), + DECL(AL_DEBUG_TYPE_OTHER_EXT), + DECL(AL_DEBUG_SEVERITY_HIGH_EXT), + DECL(AL_DEBUG_SEVERITY_MEDIUM_EXT), + DECL(AL_DEBUG_SEVERITY_LOW_EXT), + DECL(AL_DEBUG_SEVERITY_NOTIFICATION_EXT), + DECL(AL_DEBUG_LOGGED_MESSAGES_EXT), + DECL(AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT), + DECL(AL_MAX_DEBUG_MESSAGE_LENGTH_EXT), + DECL(AL_MAX_DEBUG_LOGGED_MESSAGES_EXT), + DECL(AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT), + DECL(AL_STACK_OVERFLOW_EXT), + DECL(AL_STACK_UNDERFLOW_EXT), DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), diff --git a/alc/context.cpp b/alc/context.cpp index 0c8253fb..6a2f57ca 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -51,6 +51,7 @@ using voidp = void*; constexpr ALchar alExtList[] = "AL_EXT_ALAW " "AL_EXT_BFORMAT " + "AL_EXTX_DEBUG " "AL_EXT_DOUBLE " "AL_EXT_EXPONENT_DISTANCE " "AL_EXT_FLOAT32 " @@ -72,7 +73,6 @@ constexpr ALchar alExtList[] = "AL_SOFT_buffer_length_query " "AL_SOFT_callback_buffer " "AL_SOFTX_convolution_reverb " - "AL_SOFTX_debug " "AL_SOFT_deferred_updates " "AL_SOFT_direct_channels " "AL_SOFT_direct_channels_remix " diff --git a/alc/context.h b/alc/context.h index d74bc8d1..9381db04 100644 --- a/alc/context.h +++ b/alc/context.h @@ -118,7 +118,7 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { void *mEventParam{nullptr}; std::mutex mDebugCbLock; - ALDEBUGPROCSOFT mDebugCb{}; + ALDEBUGPROCEXT mDebugCb{}; void *mDebugParam{nullptr}; std::vector mDebugGroups; std::deque mDebugLog; diff --git a/alc/inprogext.h b/alc/inprogext.h index 7f9d7766..9db3b65b 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -54,52 +54,52 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_STOP_SOURCES_ON_DISCONNECT_SOFT 0x19AB #endif -#ifndef AL_SOFT_debug -#define AL_SOFT_debug -#define AL_DONT_CARE_SOFT 0x0002 -#define AL_DEBUG_OUTPUT_SOFT 0x19B2 -#define AL_DEBUG_CALLBACK_FUNCTION_SOFT 0x19B3 -#define AL_DEBUG_CALLBACK_USER_PARAM_SOFT 0x19B4 -#define AL_DEBUG_SOURCE_API_SOFT 0x19B5 -#define AL_DEBUG_SOURCE_AUDIO_SYSTEM_SOFT 0x19B6 -#define AL_DEBUG_SOURCE_THIRD_PARTY_SOFT 0x19B7 -#define AL_DEBUG_SOURCE_APPLICATION_SOFT 0x19B8 -#define AL_DEBUG_SOURCE_OTHER_SOFT 0x19B9 -#define AL_DEBUG_TYPE_ERROR_SOFT 0x19BA -#define AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_SOFT 0x19BB -#define AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_SOFT 0x19BC -#define AL_DEBUG_TYPE_PORTABILITY_SOFT 0x19BD -#define AL_DEBUG_TYPE_PERFORMANCE_SOFT 0x19BE -#define AL_DEBUG_TYPE_MARKER_SOFT 0x19BF -#define AL_DEBUG_TYPE_PUSH_GROUP_SOFT 0x19C0 -#define AL_DEBUG_TYPE_POP_GROUP_SOFT 0x19C1 -#define AL_DEBUG_TYPE_OTHER_SOFT 0x19C2 -#define AL_DEBUG_SEVERITY_HIGH_SOFT 0x19C3 -#define AL_DEBUG_SEVERITY_MEDIUM_SOFT 0x19C4 -#define AL_DEBUG_SEVERITY_LOW_SOFT 0x19C5 -#define AL_DEBUG_SEVERITY_NOTIFICATION_SOFT 0x19C6 -#define AL_DEBUG_LOGGED_MESSAGES_SOFT 0x19C7 -#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_SOFT 0x19C8 -#define AL_MAX_DEBUG_MESSAGE_LENGTH_SOFT 0x19C9 -#define AL_MAX_DEBUG_LOGGED_MESSAGES_SOFT 0x19CA -#define AL_MAX_DEBUG_GROUP_STACK_DEPTH_SOFT 0x19CB -#define AL_STACK_OVERFLOW_SOFT 0x19CC -#define AL_STACK_UNDERFLOW_SOFT 0x19CD +#ifndef AL_EXT_DEBUG +#define AL_EXT_DEBUG +#define AL_DONT_CARE_EXT 0x0002 +#define AL_DEBUG_OUTPUT_EXT 0x19B2 +#define AL_DEBUG_CALLBACK_FUNCTION_EXT 0x19B3 +#define AL_DEBUG_CALLBACK_USER_PARAM_EXT 0x19B4 +#define AL_DEBUG_SOURCE_API_EXT 0x19B5 +#define AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT 0x19B6 +#define AL_DEBUG_SOURCE_THIRD_PARTY_EXT 0x19B7 +#define AL_DEBUG_SOURCE_APPLICATION_EXT 0x19B8 +#define AL_DEBUG_SOURCE_OTHER_EXT 0x19B9 +#define AL_DEBUG_TYPE_ERROR_EXT 0x19BA +#define AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT 0x19BB +#define AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT 0x19BC +#define AL_DEBUG_TYPE_PORTABILITY_EXT 0x19BD +#define AL_DEBUG_TYPE_PERFORMANCE_EXT 0x19BE +#define AL_DEBUG_TYPE_MARKER_EXT 0x19BF +#define AL_DEBUG_TYPE_PUSH_GROUP_EXT 0x19C0 +#define AL_DEBUG_TYPE_POP_GROUP_EXT 0x19C1 +#define AL_DEBUG_TYPE_OTHER_EXT 0x19C2 +#define AL_DEBUG_SEVERITY_HIGH_EXT 0x19C3 +#define AL_DEBUG_SEVERITY_MEDIUM_EXT 0x19C4 +#define AL_DEBUG_SEVERITY_LOW_EXT 0x19C5 +#define AL_DEBUG_SEVERITY_NOTIFICATION_EXT 0x19C6 +#define AL_DEBUG_LOGGED_MESSAGES_EXT 0x19C7 +#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT 0x19C8 +#define AL_MAX_DEBUG_MESSAGE_LENGTH_EXT 0x19C9 +#define AL_MAX_DEBUG_LOGGED_MESSAGES_EXT 0x19CA +#define AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT 0x19CB +#define AL_STACK_OVERFLOW_EXT 0x19CC +#define AL_STACK_UNDERFLOW_EXT 0x19CD -typedef void (AL_APIENTRY*ALDEBUGPROCSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam); -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKSOFT)(ALDEBUGPROCSOFT callback, void *userParam); -typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTSOFT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLSOFT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable); -typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPSOFT)(ALenum source, ALuint id, ALsizei length, const ALchar *message); -typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPSOFT)(void); -typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGSOFT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf); +typedef void (AL_APIENTRY*ALDEBUGPROCEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam); +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKEXT)(ALDEBUGPROCEXT callback, void *userParam); +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLEXT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable); +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPEXT)(ALenum source, ALuint id, ALsizei length, const ALchar *message); +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void); +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf); #ifdef AL_ALEXT_PROTOTYPES -void AL_APIENTRY alDebugMessageCallbackSOFT(ALDEBUGPROCSOFT callback, void *userParam) noexcept; -void AL_APIENTRY alDebugMessageInsertSOFT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; -void AL_APIENTRY alDebugMessageControlSOFT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept; -void AL_APIENTRY alPushDebugGroupSOFT(ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept; -void AL_APIENTRY alPopDebugGroupSOFT(void) noexcept; -ALuint AL_APIENTRY alGetDebugMessageLogSOFT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept; +void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) noexcept; +void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; +void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept; +void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept; +void AL_APIENTRY alPopDebugGroupEXT(void) noexcept; +ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept; #endif #endif -- cgit v1.2.3 From ce588ea5a3c3ee6c7fce64ec501a03ebaca373d4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 3 May 2023 10:42:32 -0700 Subject: Implement a context debug flag Setting the debug flag at context creation enables more debug messages for the created context, and enables debug messages by default. --- al/debug.cpp | 15 ++++++++++----- al/state.cpp | 23 +++++++++++++++-------- alc/alc.cpp | 41 ++++++++++++++++++++++++++++++----------- alc/context.cpp | 7 ++++--- alc/context.h | 9 ++++++++- alc/inprogext.h | 11 +++++++++-- 6 files changed, 76 insertions(+), 30 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index fa16ff73..786fcd1f 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -248,6 +248,9 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; + if(!context->mContextFlags.test(ContextFlags::DebugBit)) + return; + if(!message) return context->setError(AL_INVALID_VALUE, "Null message pointer"); @@ -416,9 +419,10 @@ FORCE_ALIGN void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsiz newback.mFilters = oldback.mFilters; newback.mIdFilters = oldback.mIdFilters; - context->sendDebugMessage(debuglock, newback.mSource, DebugType::PushGroup, newback.mId, - DebugSeverity::Notification, static_cast(newback.mMessage.size()), - newback.mMessage.data()); + if(context->mContextFlags.test(ContextFlags::DebugBit)) + context->sendDebugMessage(debuglock, newback.mSource, DebugType::PushGroup, newback.mId, + DebugSeverity::Notification, static_cast(newback.mMessage.size()), + newback.mMessage.data()); } FORCE_ALIGN void AL_APIENTRY alPopDebugGroupEXT(void) noexcept @@ -440,8 +444,9 @@ FORCE_ALIGN void AL_APIENTRY alPopDebugGroupEXT(void) noexcept std::string message{std::move(debug.mMessage)}; context->mDebugGroups.pop_back(); - context->sendDebugMessage(debuglock, source, DebugType::PopGroup, id, - DebugSeverity::Notification, static_cast(message.size()), message.data()); + if(context->mContextFlags.test(ContextFlags::DebugBit)) + context->sendDebugMessage(debuglock, source, DebugType::PopGroup, id, + DebugSeverity::Notification, static_cast(message.size()), message.data()); } diff --git a/al/state.cpp b/al/state.cpp index 71c9b703..efc6398d 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -150,6 +150,7 @@ enum PropertyValue : ALenum { MaxDebugMessageLength = AL_MAX_DEBUG_MESSAGE_LENGTH_EXT, MaxDebugLoggedMessages = AL_MAX_DEBUG_LOGGED_MESSAGES_EXT, MaxDebugGroupDepth = AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT, + ContextFlags = AL_CONTEXT_FLAGS_EXT, #ifdef ALSOFT_EAX EaxRamSize = AL_EAX_RAM_SIZE, EaxRamFree = AL_EAX_RAM_FREE, @@ -183,10 +184,11 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) return; case AL_DOPPLER_VELOCITY: - context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, - DebugSeverity::Medium, -1, - "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; " - "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f"); + if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY + context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + DebugSeverity::Medium, -1, + "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; " + "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f"); *values = cast_value(context->mDopplerVelocity); return; @@ -241,6 +243,10 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) *values = cast_value(MaxDebugGroupDepth); return; + case AL_CONTEXT_FLAGS_EXT: + *values = cast_value(context->mContextFlags.to_ulong()); + return; + #ifdef ALSOFT_EAX #define EAX_ERROR "[alGetInteger] EAX not enabled." @@ -618,10 +624,11 @@ START_API_FUNC ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, - DebugSeverity::Medium, -1, - "alDopplerVelocity is deprecated in AL 1.1, use alSpeedOfSound; " - "alDopplerVelocity(x) -> alSpeedOfSound(343.3f * x)"); + if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY + context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + DebugSeverity::Medium, -1, + "alDopplerVelocity is deprecated in AL 1.1, use alSpeedOfSound; " + "alDopplerVelocity(x) -> alSpeedOfSound(343.3f * x)"); if(!(value >= 0.0f && std::isfinite(value))) context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value); diff --git a/alc/alc.cpp b/alc/alc.cpp index de5bc232..8932a084 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -573,6 +573,9 @@ constexpr struct { DECL(ALC_INVALID_VALUE), DECL(ALC_OUT_OF_MEMORY), + DECL(ALC_CONTEXT_FLAGS_EXT), + DECL(ALC_CONTEXT_DEBUG_BIT_EXT), + DECL(AL_INVALID), DECL(AL_NONE), @@ -1021,6 +1024,7 @@ constexpr ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT " "ALC_ENUMERATION_EXT " "ALC_EXT_CAPTURE " + "ALC_EXTX_debug " "ALC_EXT_DEDICATED " "ALC_EXT_disconnect " "ALC_EXT_EFX " @@ -2619,11 +2623,12 @@ START_API_FUNC return; } - ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, -1, - "alcSuspendContext behavior is not portable -- some implementations suspend all " - "rendering, some only defer property changes, and some are completely no-op; consider " - "using alcDevicePauseSOFT to suspend all rendering, or alDeferUpdatesSOFT to only defer " - "property changes"); + if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY + ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, -1, + "alcSuspendContext behavior is not portable -- some implementations suspend all " + "rendering, some only defer property changes, and some are completely no-op; consider " + "using alcDevicePauseSOFT to suspend all rendering, or alDeferUpdatesSOFT to only " + "defer property changes"); if(SuspendDefers) { @@ -2643,11 +2648,12 @@ START_API_FUNC return; } - ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, -1, - "alcProcessContext behavior is not portable -- some implementations resume rendering, " - "some apply deferred property changes, and some are completely no-op; consider using " - "alcDeviceResumeSOFT to resume rendering, or alProcessUpdatesSOFT to apply deferred " - "property changes"); + if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY + ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, -1, + "alcProcessContext behavior is not portable -- some implementations resume rendering, " + "some apply deferred property changes, and some are completely no-op; consider using " + "alcDeviceResumeSOFT to resume rendering, or alProcessUpdatesSOFT to apply deferred " + "property changes"); if(SuspendDefers) { @@ -3366,7 +3372,20 @@ START_API_FUNC return nullptr; } - ContextRef context{new ALCcontext{dev}}; + ContextFlagBitset ctxflags{0}; + if(attrList) + { + for(size_t i{0};attrList[i];i+=2) + { + if(attrList[i] == ALC_CONTEXT_FLAGS_EXT) + { + ctxflags = static_cast(attrList[i+1]); + break; + } + } + } + + ContextRef context{new ALCcontext{dev, ctxflags}}; context->init(); if(auto volopt = dev->configValue(nullptr, "volume-adjust")) diff --git a/alc/context.cpp b/alc/context.cpp index 6a2f57ca..2fbf67af 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -51,7 +51,7 @@ using voidp = void*; constexpr ALchar alExtList[] = "AL_EXT_ALAW " "AL_EXT_BFORMAT " - "AL_EXTX_DEBUG " + "AL_EXTX_debug " "AL_EXT_DOUBLE " "AL_EXT_EXPONENT_DISTANCE " "AL_EXT_FLOAT32 " @@ -119,10 +119,11 @@ void ALCcontext::setThreadContext(ALCcontext *context) noexcept { sThreadContext.set(context); } #endif -ALCcontext::ALCcontext(al::intrusive_ptr device) - : ContextBase{device.get()}, mALDevice{std::move(device)} +ALCcontext::ALCcontext(al::intrusive_ptr device, ContextFlagBitset flags) + : ContextBase{device.get()}, mALDevice{std::move(device)}, mContextFlags{flags} { mDebugGroups.emplace_back(DebugSource::Other, 0, std::string{}); + mDebugEnabled.store(mContextFlags.test(ContextFlags::DebugBit), std::memory_order_relaxed); } ALCcontext::~ALCcontext() diff --git a/alc/context.h b/alc/context.h index 9381db04..402794eb 100644 --- a/alc/context.h +++ b/alc/context.h @@ -43,6 +43,12 @@ enum class DebugSeverity : uint8_t; using uint = unsigned int; +enum ContextFlags { + DebugBit = 0, /* ALC_CONTEXT_DEBUG_BIT_EXT */ +}; +using ContextFlagBitset = std::bitset; + + struct DebugLogEntry { const DebugSource mSource; const DebugType mType; @@ -103,6 +109,7 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { std::atomic mLastError{AL_NO_ERROR}; + const ContextFlagBitset mContextFlags; std::atomic mDebugEnabled{false}; DistanceModel mDistanceModel{DistanceModel::Default}; @@ -141,7 +148,7 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { std::string mExtensionListOverride{}; - ALCcontext(al::intrusive_ptr device); + ALCcontext(al::intrusive_ptr device, ContextFlagBitset flags); ALCcontext(const ALCcontext&) = delete; ALCcontext& operator=(const ALCcontext&) = delete; ~ALCcontext(); diff --git a/alc/inprogext.h b/alc/inprogext.h index 9db3b65b..b39eaa58 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -54,8 +54,14 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_STOP_SOURCES_ON_DISCONNECT_SOFT 0x19AB #endif -#ifndef AL_EXT_DEBUG -#define AL_EXT_DEBUG +#ifndef ALC_EXT_debug +#define ALC_EXT_debug +#define ALC_CONTEXT_FLAGS_EXT 0x19CE +#define ALC_CONTEXT_DEBUG_BIT_EXT 0x0001 +#endif + +#ifndef AL_EXT_debug +#define AL_EXT_debug #define AL_DONT_CARE_EXT 0x0002 #define AL_DEBUG_OUTPUT_EXT 0x19B2 #define AL_DEBUG_CALLBACK_FUNCTION_EXT 0x19B3 @@ -85,6 +91,7 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT 0x19CB #define AL_STACK_OVERFLOW_EXT 0x19CC #define AL_STACK_UNDERFLOW_EXT 0x19CD +#define AL_CONTEXT_FLAGS_EXT 0x19CE typedef void (AL_APIENTRY*ALDEBUGPROCEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam); typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKEXT)(ALDEBUGPROCEXT callback, void *userParam); -- cgit v1.2.3 From 7cda37a67c8f147536c53f0073df9a9e61d40587 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 4 May 2023 08:03:40 -0700 Subject: Replace al::optional with std::optional --- CMakeLists.txt | 1 - al/buffer.cpp | 20 ++++++++++---------- al/debug.cpp | 14 +++++++------- al/eax/fx_slot_index.h | 7 +++---- al/effects/chorus.cpp | 6 +++--- al/effects/fshifter.cpp | 6 +++--- al/effects/modulator.cpp | 6 +++--- al/effects/vmorpher.cpp | 10 +++++----- al/source.cpp | 30 +++++++++++++++--------------- al/state.cpp | 6 +++--- alc/alc.cpp | 44 ++++++++++++++++++++++---------------------- alc/alconfig.cpp | 22 +++++++++++----------- alc/alconfig.h | 12 ++++++------ alc/alu.cpp | 1 + alc/alu.h | 5 ++--- alc/backends/alsa.cpp | 1 - alc/backends/base.cpp | 1 - alc/backends/oss.cpp | 1 - alc/backends/pipewire.cpp | 8 ++++---- alc/backends/pulseaudio.cpp | 6 +++--- alc/device.h | 13 +++++++------ alc/panning.cpp | 4 ++-- common/aloptional.h | 17 ----------------- common/strutils.cpp | 8 ++++---- common/strutils.h | 7 +++---- core/ambdec.cpp | 8 ++++---- core/ambdec.h | 4 ++-- core/cpu_caps.cpp | 4 ++-- core/cpu_caps.h | 5 ++--- core/helpers.cpp | 8 ++++---- core/hrtf.cpp | 4 ++-- core/hrtf.h | 4 ++-- core/voice.cpp | 4 ++-- core/voice.h | 4 ++-- utils/makemhr/loaddef.cpp | 5 ++--- utils/makemhr/loadsofa.cpp | 4 ++-- 36 files changed, 143 insertions(+), 167 deletions(-) delete mode 100644 common/aloptional.h (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index 764b4590..07377ddb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -599,7 +599,6 @@ set(COMMON_OBJS common/almalloc.h common/alnumbers.h common/alnumeric.h - common/aloptional.h common/alspan.h common/alstring.cpp common/alstring.h diff --git a/al/buffer.cpp b/al/buffer.cpp index b89ad5af..4f0bcf8c 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -49,7 +50,6 @@ #include "alc/inprogext.h" #include "almalloc.h" #include "alnumeric.h" -#include "aloptional.h" #include "atomic.h" #include "core/except.h" #include "core/logging.h" @@ -64,14 +64,14 @@ namespace { -al::optional AmbiLayoutFromEnum(ALenum layout) +std::optional AmbiLayoutFromEnum(ALenum layout) { switch(layout) { case AL_FUMA_SOFT: return AmbiLayout::FuMa; case AL_ACN_SOFT: return AmbiLayout::ACN; } - return al::nullopt; + return std::nullopt; } ALenum EnumFromAmbiLayout(AmbiLayout layout) { @@ -83,7 +83,7 @@ ALenum EnumFromAmbiLayout(AmbiLayout layout) throw std::runtime_error{"Invalid AmbiLayout: "+std::to_string(int(layout))}; } -al::optional AmbiScalingFromEnum(ALenum scale) +std::optional AmbiScalingFromEnum(ALenum scale) { switch(scale) { @@ -91,7 +91,7 @@ al::optional AmbiScalingFromEnum(ALenum scale) case AL_SN3D_SOFT: return AmbiScaling::SN3D; case AL_N3D_SOFT: return AmbiScaling::N3D; } - return al::nullopt; + return std::nullopt; } ALenum EnumFromAmbiScaling(AmbiScaling scale) { @@ -106,7 +106,7 @@ ALenum EnumFromAmbiScaling(AmbiScaling scale) } #ifdef ALSOFT_EAX -al::optional EaxStorageFromEnum(ALenum scale) +std::optional EaxStorageFromEnum(ALenum scale) { switch(scale) { @@ -114,7 +114,7 @@ al::optional EaxStorageFromEnum(ALenum scale) case AL_STORAGE_ACCESSIBLE: return EaxStorage::Accessible; case AL_STORAGE_HARDWARE: return EaxStorage::Hardware; } - return al::nullopt; + return std::nullopt; } ALenum EnumFromEaxStorage(EaxStorage storage) { @@ -536,7 +536,7 @@ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, struct DecompResult { FmtChannels channels; FmtType type; }; -al::optional DecomposeUserFormat(ALenum format) +std::optional DecomposeUserFormat(ALenum format) { struct FormatMap { ALenum format; @@ -624,9 +624,9 @@ al::optional DecomposeUserFormat(ALenum format) for(const auto &fmt : UserFmtList) { if(fmt.format == format) - return al::make_optional({fmt.channels, fmt.type}); + return DecompResult{fmt.channels, fmt.type}; } - return al::nullopt; + return std::nullopt; } } // namespace diff --git a/al/debug.cpp b/al/debug.cpp index 786fcd1f..3df85d62 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -15,7 +16,6 @@ #include "alc/context.h" #include "alc/inprogext.h" -#include "aloptional.h" #include "alspan.h" #include "core/logging.h" #include "opthelpers.h" @@ -35,7 +35,7 @@ constexpr auto make_array() { return make_array(std::make_integer_sequence{}); } -constexpr al::optional GetDebugSource(ALenum source) noexcept +constexpr std::optional GetDebugSource(ALenum source) noexcept { switch(source) { @@ -45,10 +45,10 @@ constexpr al::optional GetDebugSource(ALenum source) noexcept case AL_DEBUG_SOURCE_APPLICATION_EXT: return DebugSource::Application; case AL_DEBUG_SOURCE_OTHER_EXT: return DebugSource::Other; } - return al::nullopt; + return std::nullopt; } -constexpr al::optional GetDebugType(ALenum type) noexcept +constexpr std::optional GetDebugType(ALenum type) noexcept { switch(type) { @@ -62,10 +62,10 @@ constexpr al::optional GetDebugType(ALenum type) noexcept case AL_DEBUG_TYPE_POP_GROUP_EXT: return DebugType::PopGroup; case AL_DEBUG_TYPE_OTHER_EXT: return DebugType::Other; } - return al::nullopt; + return std::nullopt; } -constexpr al::optional GetDebugSeverity(ALenum severity) noexcept +constexpr std::optional GetDebugSeverity(ALenum severity) noexcept { switch(severity) { @@ -74,7 +74,7 @@ constexpr al::optional GetDebugSeverity(ALenum severity) noexcept case AL_DEBUG_SEVERITY_LOW_EXT: return DebugSeverity::Low; case AL_DEBUG_SEVERITY_NOTIFICATION_EXT: return DebugSeverity::Notification; } - return al::nullopt; + return std::nullopt; } diff --git a/al/eax/fx_slot_index.h b/al/eax/fx_slot_index.h index 63dba037..9f350d9b 100644 --- a/al/eax/fx_slot_index.h +++ b/al/eax/fx_slot_index.h @@ -3,17 +3,16 @@ #include +#include -#include "aloptional.h" #include "api.h" using EaxFxSlotIndexValue = std::size_t; -class EaxFxSlotIndex : public al::optional -{ +class EaxFxSlotIndex : public std::optional { public: - using al::optional::optional; + using std::optional::optional; EaxFxSlotIndex& operator=(const EaxFxSlotIndexValue &value) { set(value); return *this; } EaxFxSlotIndex& operator=(const GUID &guid) { set(guid); return *this; } diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index 305259a4..2e0c23dd 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -1,13 +1,13 @@ #include "config.h" +#include #include #include "AL/al.h" #include "AL/efx.h" #include "alc/effects/base.h" -#include "aloptional.h" #include "core/logging.h" #include "effects.h" @@ -27,14 +27,14 @@ static_assert(FlangerMaxDelay >= AL_FLANGER_MAX_DELAY, "Flanger max delay too sm static_assert(AL_CHORUS_WAVEFORM_SINUSOID == AL_FLANGER_WAVEFORM_SINUSOID, "Chorus/Flanger waveform value mismatch"); static_assert(AL_CHORUS_WAVEFORM_TRIANGLE == AL_FLANGER_WAVEFORM_TRIANGLE, "Chorus/Flanger waveform value mismatch"); -inline al::optional WaveformFromEnum(ALenum type) +inline std::optional WaveformFromEnum(ALenum type) { switch(type) { case AL_CHORUS_WAVEFORM_SINUSOID: return ChorusWaveform::Sinusoid; case AL_CHORUS_WAVEFORM_TRIANGLE: return ChorusWaveform::Triangle; } - return al::nullopt; + return std::nullopt; } inline ALenum EnumFromWaveform(ChorusWaveform type) { diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index 949db203..54e71408 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -1,13 +1,13 @@ #include "config.h" +#include #include #include "AL/al.h" #include "AL/efx.h" #include "alc/effects/base.h" -#include "aloptional.h" #include "effects.h" #ifdef ALSOFT_EAX @@ -20,7 +20,7 @@ namespace { -al::optional DirectionFromEmum(ALenum value) +std::optional DirectionFromEmum(ALenum value) { switch(value) { @@ -28,7 +28,7 @@ al::optional DirectionFromEmum(ALenum value) case AL_FREQUENCY_SHIFTER_DIRECTION_UP: return FShifterDirection::Up; case AL_FREQUENCY_SHIFTER_DIRECTION_OFF: return FShifterDirection::Off; } - return al::nullopt; + return std::nullopt; } ALenum EnumFromDirection(FShifterDirection dir) { diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index 5f37d08f..228fe084 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -1,13 +1,13 @@ #include "config.h" +#include #include #include "AL/al.h" #include "AL/efx.h" #include "alc/effects/base.h" -#include "aloptional.h" #include "effects.h" #ifdef ALSOFT_EAX @@ -20,7 +20,7 @@ namespace { -al::optional WaveformFromEmum(ALenum value) +std::optional WaveformFromEmum(ALenum value) { switch(value) { @@ -28,7 +28,7 @@ al::optional WaveformFromEmum(ALenum value) case AL_RING_MODULATOR_SAWTOOTH: return ModulatorWaveform::Sawtooth; case AL_RING_MODULATOR_SQUARE: return ModulatorWaveform::Square; } - return al::nullopt; + return std::nullopt; } ALenum EnumFromWaveform(ModulatorWaveform type) { diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index 21ea3680..6268ea7f 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -1,13 +1,13 @@ #include "config.h" +#include #include #include "AL/al.h" #include "AL/efx.h" #include "alc/effects/base.h" -#include "aloptional.h" #include "effects.h" #ifdef ALSOFT_EAX @@ -20,7 +20,7 @@ namespace { -al::optional PhenomeFromEnum(ALenum val) +std::optional PhenomeFromEnum(ALenum val) { #define HANDLE_PHENOME(x) case AL_VOCAL_MORPHER_PHONEME_ ## x: \ return VMorpherPhenome::x @@ -57,7 +57,7 @@ al::optional PhenomeFromEnum(ALenum val) HANDLE_PHENOME(V); HANDLE_PHENOME(Z); } - return al::nullopt; + return std::nullopt; #undef HANDLE_PHENOME } ALenum EnumFromPhenome(VMorpherPhenome phenome) @@ -100,7 +100,7 @@ ALenum EnumFromPhenome(VMorpherPhenome phenome) #undef HANDLE_PHENOME } -al::optional WaveformFromEmum(ALenum value) +std::optional WaveformFromEmum(ALenum value) { switch(value) { @@ -108,7 +108,7 @@ al::optional WaveformFromEmum(ALenum value) case AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE: return VMorpherWaveform::Triangle; case AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH: return VMorpherWaveform::Sawtooth; } - return al::nullopt; + return std::nullopt; } ALenum EnumFromWaveform(VMorpherWaveform type) { diff --git a/al/source.cpp b/al/source.cpp index f51c3bca..2b0540b4 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -55,7 +56,6 @@ #include "alc/inprogext.h" #include "almalloc.h" #include "alnumeric.h" -#include "aloptional.h" #include "alspan.h" #include "atomic.h" #include "auxeffectslot.h" @@ -395,8 +395,8 @@ struct VoicePos { * using the givem offset type and offset. If the offset is out of range, * returns an empty optional. */ -al::optional GetSampleOffset(al::deque &BufferList, ALenum OffsetType, - double Offset) +std::optional GetSampleOffset(al::deque &BufferList, + ALenum OffsetType, double Offset) { /* Find the first valid Buffer in the Queue */ const ALbuffer *BufferFmt{nullptr}; @@ -406,7 +406,7 @@ al::optional GetSampleOffset(al::deque &BufferList, if(BufferFmt) break; } if(!BufferFmt) UNLIKELY - return al::nullopt; + return std::nullopt; /* Get sample frame offset */ int64_t offset{}; @@ -452,12 +452,12 @@ al::optional GetSampleOffset(al::deque &BufferList, if(offset < 0) { if(offset < std::numeric_limits::min()) - return al::nullopt; + return std::nullopt; return VoicePos{static_cast(offset), frac, &BufferList.front()}; } if(BufferFmt->mCallback) - return al::nullopt; + return std::nullopt; int64_t totalBufferLen{0}; for(auto &item : BufferList) @@ -473,7 +473,7 @@ al::optional GetSampleOffset(al::deque &BufferList, } /* Offset is out of range of the queue */ - return al::nullopt; + return std::nullopt; } @@ -798,7 +798,7 @@ inline ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id) noexcept } -al::optional StereoModeFromEnum(ALenum mode) +std::optional StereoModeFromEnum(ALenum mode) { switch(mode) { @@ -806,7 +806,7 @@ al::optional StereoModeFromEnum(ALenum mode) case AL_SUPER_STEREO_SOFT: return SourceStereo::Enhanced; } WARN("Unsupported stereo mode: 0x%04x\n", mode); - return al::nullopt; + return std::nullopt; } ALenum EnumFromStereoMode(SourceStereo mode) { @@ -818,7 +818,7 @@ ALenum EnumFromStereoMode(SourceStereo mode) throw std::runtime_error{"Invalid SourceStereo: "+std::to_string(int(mode))}; } -al::optional SpatializeModeFromEnum(ALenum mode) +std::optional SpatializeModeFromEnum(ALenum mode) { switch(mode) { @@ -827,7 +827,7 @@ al::optional SpatializeModeFromEnum(ALenum mode) case AL_AUTO_SOFT: return SpatializeMode::Auto; } WARN("Unsupported spatialize mode: 0x%04x\n", mode); - return al::nullopt; + return std::nullopt; } ALenum EnumFromSpatializeMode(SpatializeMode mode) { @@ -840,7 +840,7 @@ ALenum EnumFromSpatializeMode(SpatializeMode mode) throw std::runtime_error{"Invalid SpatializeMode: "+std::to_string(int(mode))}; } -al::optional DirectModeFromEnum(ALenum mode) +std::optional DirectModeFromEnum(ALenum mode) { switch(mode) { @@ -849,7 +849,7 @@ al::optional DirectModeFromEnum(ALenum mode) case AL_REMIX_UNMATCHED_SOFT: return DirectMode::RemixMismatch; } WARN("Unsupported direct mode: 0x%04x\n", mode); - return al::nullopt; + return std::nullopt; } ALenum EnumFromDirectMode(DirectMode mode) { @@ -862,7 +862,7 @@ ALenum EnumFromDirectMode(DirectMode mode) throw std::runtime_error{"Invalid DirectMode: "+std::to_string(int(mode))}; } -al::optional DistanceModelFromALenum(ALenum model) +std::optional DistanceModelFromALenum(ALenum model) { switch(model) { @@ -874,7 +874,7 @@ al::optional DistanceModelFromALenum(ALenum model) case AL_EXPONENT_DISTANCE: return DistanceModel::Exponent; case AL_EXPONENT_DISTANCE_CLAMPED: return DistanceModel::ExponentClamped; } - return al::nullopt; + return std::nullopt; } ALenum ALenumFromDistanceModel(DistanceModel model) { diff --git a/al/state.cpp b/al/state.cpp index efc6398d..77b104a4 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -38,7 +39,6 @@ #include "alc/context.h" #include "alc/inprogext.h" #include "alnumeric.h" -#include "aloptional.h" #include "atomic.h" #include "core/context.h" #include "core/except.h" @@ -107,7 +107,7 @@ const ALchar *GetResamplerName(const Resampler rtype) throw std::runtime_error{"Unexpected resampler index"}; } -al::optional DistanceModelFromALenum(ALenum model) +std::optional DistanceModelFromALenum(ALenum model) { switch(model) { @@ -119,7 +119,7 @@ al::optional DistanceModelFromALenum(ALenum model) case AL_EXPONENT_DISTANCE: return DistanceModel::Exponent; case AL_EXPONENT_DISTANCE_CLAMPED: return DistanceModel::ExponentClamped; } - return al::nullopt; + return std::nullopt; } ALenum ALenumFromDistanceModel(DistanceModel model) { diff --git a/alc/alc.cpp b/alc/alc.cpp index 8932a084..2da5c5db 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -71,7 +72,6 @@ #include "alconfig.h" #include "almalloc.h" #include "alnumeric.h" -#include "aloptional.h" #include "alspan.h" #include "alstring.h" #include "alu.h" @@ -1443,7 +1443,7 @@ void ProbeCaptureDeviceList() struct DevFmtPair { DevFmtChannels chans; DevFmtType type; }; -al::optional DecomposeDevFormat(ALenum format) +std::optional DecomposeDevFormat(ALenum format) { static const struct { ALenum format; @@ -1478,13 +1478,13 @@ al::optional DecomposeDevFormat(ALenum format) for(const auto &item : list) { if(item.format == format) - return al::make_optional({item.channels, item.type}); + return DevFmtPair{item.channels, item.type}; } - return al::nullopt; + return std::nullopt; } -al::optional DevFmtTypeFromEnum(ALCenum type) +std::optional DevFmtTypeFromEnum(ALCenum type) { switch(type) { @@ -1497,7 +1497,7 @@ al::optional DevFmtTypeFromEnum(ALCenum type) case ALC_FLOAT_SOFT: return DevFmtFloat; } WARN("Unsupported format type: 0x%04x\n", type); - return al::nullopt; + return std::nullopt; } ALCenum EnumFromDevFmt(DevFmtType type) { @@ -1514,7 +1514,7 @@ ALCenum EnumFromDevFmt(DevFmtType type) throw std::runtime_error{"Invalid DevFmtType: "+std::to_string(int(type))}; } -al::optional DevFmtChannelsFromEnum(ALCenum channels) +std::optional DevFmtChannelsFromEnum(ALCenum channels) { switch(channels) { @@ -1527,7 +1527,7 @@ al::optional DevFmtChannelsFromEnum(ALCenum channels) case ALC_BFORMAT3D_SOFT: return DevFmtAmbi3D; } WARN("Unsupported format channels: 0x%04x\n", channels); - return al::nullopt; + return std::nullopt; } ALCenum EnumFromDevFmt(DevFmtChannels channels) { @@ -1547,7 +1547,7 @@ ALCenum EnumFromDevFmt(DevFmtChannels channels) throw std::runtime_error{"Invalid DevFmtChannels: "+std::to_string(int(channels))}; } -al::optional DevAmbiLayoutFromEnum(ALCenum layout) +std::optional DevAmbiLayoutFromEnum(ALCenum layout) { switch(layout) { @@ -1555,7 +1555,7 @@ al::optional DevAmbiLayoutFromEnum(ALCenum layout) case ALC_ACN_SOFT: return DevAmbiLayout::ACN; } WARN("Unsupported ambisonic layout: 0x%04x\n", layout); - return al::nullopt; + return std::nullopt; } ALCenum EnumFromDevAmbi(DevAmbiLayout layout) { @@ -1567,7 +1567,7 @@ ALCenum EnumFromDevAmbi(DevAmbiLayout layout) throw std::runtime_error{"Invalid DevAmbiLayout: "+std::to_string(int(layout))}; } -al::optional DevAmbiScalingFromEnum(ALCenum scaling) +std::optional DevAmbiScalingFromEnum(ALCenum scaling) { switch(scaling) { @@ -1576,7 +1576,7 @@ al::optional DevAmbiScalingFromEnum(ALCenum scaling) case ALC_N3D_SOFT: return DevAmbiScaling::N3D; } WARN("Unsupported ambisonic scaling: 0x%04x\n", scaling); - return al::nullopt; + return std::nullopt; } ALCenum EnumFromDevAmbi(DevAmbiScaling scaling) { @@ -1731,13 +1731,13 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) uint numMono{device->NumMonoSources}; uint numStereo{device->NumStereoSources}; uint numSends{device->NumAuxSends}; - al::optional stereomode; - al::optional optlimit; - al::optional optsrate; - al::optional optchans; - al::optional opttype; - al::optional optlayout; - al::optional optscale; + std::optional stereomode; + std::optional optlimit; + std::optional optsrate; + std::optional optchans; + std::optional opttype; + std::optional optlayout; + std::optional optscale; uint period_size{DEFAULT_UPDATE_SIZE}; uint buffer_size{DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES}; int hrtf_id{-1}; @@ -1880,7 +1880,7 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) if(attrList && attrList[0]) { ALenum outmode{ALC_ANY_SOFT}; - al::optional opthrtf; + std::optional opthrtf; int freqAttr{}; #define ATTRIBUTE(a) a: TRACE("%s = %d\n", #a, attrList[attrIdx + 1]); @@ -1940,7 +1940,7 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) else if(attrList[attrIdx + 1] == ALC_TRUE) opthrtf = true; else if(attrList[attrIdx + 1] == ALC_DONT_CARE_SOFT) - opthrtf = al::nullopt; + opthrtf = std::nullopt; break; case ATTRIBUTE(ALC_HRTF_ID_SOFT) @@ -1953,7 +1953,7 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) else if(attrList[attrIdx + 1] == ALC_TRUE) optlimit = true; else if(attrList[attrIdx + 1] == ALC_DONT_CARE_SOFT) - optlimit = al::nullopt; + optlimit = std::nullopt; break; case ATTRIBUTE(ALC_OUTPUT_MODE_SOFT) diff --git a/alc/alconfig.cpp b/alc/alconfig.cpp index b0544b89..56cad9e0 100644 --- a/alc/alconfig.cpp +++ b/alc/alconfig.cpp @@ -52,7 +52,7 @@ struct ConfigEntry { std::string key; std::string value; }; -al::vector ConfOpts; +std::vector ConfOpts; std::string &lstrip(std::string &line) @@ -483,40 +483,40 @@ void ReadALConfig() } #endif -al::optional ConfigValueStr(const char *devName, const char *blockName, const char *keyName) +std::optional ConfigValueStr(const char *devName, const char *blockName, const char *keyName) { if(const char *val{GetConfigValue(devName, blockName, keyName)}) return val; - return al::nullopt; + return std::nullopt; } -al::optional ConfigValueInt(const char *devName, const char *blockName, const char *keyName) +std::optional ConfigValueInt(const char *devName, const char *blockName, const char *keyName) { if(const char *val{GetConfigValue(devName, blockName, keyName)}) return static_cast(std::strtol(val, nullptr, 0)); - return al::nullopt; + return std::nullopt; } -al::optional ConfigValueUInt(const char *devName, const char *blockName, const char *keyName) +std::optional ConfigValueUInt(const char *devName, const char *blockName, const char *keyName) { if(const char *val{GetConfigValue(devName, blockName, keyName)}) return static_cast(std::strtoul(val, nullptr, 0)); - return al::nullopt; + return std::nullopt; } -al::optional ConfigValueFloat(const char *devName, const char *blockName, const char *keyName) +std::optional ConfigValueFloat(const char *devName, const char *blockName, const char *keyName) { if(const char *val{GetConfigValue(devName, blockName, keyName)}) return std::strtof(val, nullptr); - return al::nullopt; + return std::nullopt; } -al::optional ConfigValueBool(const char *devName, const char *blockName, const char *keyName) +std::optional ConfigValueBool(const char *devName, const char *blockName, const char *keyName) { if(const char *val{GetConfigValue(devName, blockName, keyName)}) return al::strcasecmp(val, "on") == 0 || al::strcasecmp(val, "yes") == 0 || al::strcasecmp(val, "true")==0 || atoi(val) != 0; - return al::nullopt; + return std::nullopt; } bool GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, bool def) diff --git a/alc/alconfig.h b/alc/alconfig.h index df2830cc..1eb44405 100644 --- a/alc/alconfig.h +++ b/alc/alconfig.h @@ -1,18 +1,18 @@ #ifndef ALCONFIG_H #define ALCONFIG_H +#include #include -#include "aloptional.h" void ReadALConfig(); bool GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, bool def); -al::optional ConfigValueStr(const char *devName, const char *blockName, const char *keyName); -al::optional ConfigValueInt(const char *devName, const char *blockName, const char *keyName); -al::optional ConfigValueUInt(const char *devName, const char *blockName, const char *keyName); -al::optional ConfigValueFloat(const char *devName, const char *blockName, const char *keyName); -al::optional ConfigValueBool(const char *devName, const char *blockName, const char *keyName); +std::optional ConfigValueStr(const char *devName, const char *blockName, const char *keyName); +std::optional ConfigValueInt(const char *devName, const char *blockName, const char *keyName); +std::optional ConfigValueUInt(const char *devName, const char *blockName, const char *keyName); +std::optional ConfigValueFloat(const char *devName, const char *blockName, const char *keyName); +std::optional ConfigValueBool(const char *devName, const char *blockName, const char *keyName); #endif /* ALCONFIG_H */ diff --git a/alc/alu.cpp b/alc/alu.cpp index e9ad68b1..fc22febb 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include diff --git a/alc/alu.h b/alc/alu.h index 67fd09e5..253940cf 100644 --- a/alc/alu.h +++ b/alc/alu.h @@ -2,8 +2,7 @@ #define ALU_H #include - -#include "aloptional.h" +#include struct ALCcontext; struct ALCdevice; @@ -31,7 +30,7 @@ void aluInit(CompatFlagBitset flags, const float nfcscale); * Set up the appropriate panning method and mixing method given the device * properties. */ -void aluInitRenderer(ALCdevice *device, int hrtf_id, al::optional stereomode); +void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optional stereomode); void aluInitEffectPanning(EffectSlot *slot, ALCcontext *context); diff --git a/alc/backends/alsa.cpp b/alc/backends/alsa.cpp index d620a83c..01021868 100644 --- a/alc/backends/alsa.cpp +++ b/alc/backends/alsa.cpp @@ -39,7 +39,6 @@ #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" -#include "aloptional.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" diff --git a/alc/backends/base.cpp b/alc/backends/base.cpp index e5ad8494..45254c47 100644 --- a/alc/backends/base.cpp +++ b/alc/backends/base.cpp @@ -14,7 +14,6 @@ #include "albit.h" #include "core/logging.h" -#include "aloptional.h" #endif #include "atomic.h" diff --git a/alc/backends/oss.cpp b/alc/backends/oss.cpp index 6d4fa261..f76024f4 100644 --- a/alc/backends/oss.cpp +++ b/alc/backends/oss.cpp @@ -45,7 +45,6 @@ #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" -#include "aloptional.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index c6569a74..d3c8e77e 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -40,7 +41,6 @@ #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" -#include "aloptional.h" #include "alspan.h" #include "alstring.h" #include "core/devformat.h" @@ -304,12 +304,12 @@ al::span> get_array_span(const spa_pod *pod) } template -al::optional> get_value(const spa_pod *value) +std::optional> get_value(const spa_pod *value) { Pod_t val{}; if(PodInfo::get_value(value, &val) == 0) return val; - return al::nullopt; + return std::nullopt; } /* Internally, PipeWire types "inherit" from each other, but this is hidden @@ -997,7 +997,7 @@ int MetadataProxy::propertyCallback(uint32_t id, const char *key, const char *ty auto get_json_string = [](spa_json *iter) { - al::optional str; + std::optional str; const char *val{}; int len{spa_json_next(iter, &val)}; diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index 4b0e316f..6f706c7f 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,6 @@ #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" -#include "aloptional.h" #include "alspan.h" #include "core/devformat.h" #include "core/device.h" @@ -615,7 +615,7 @@ struct PulsePlayback final : public BackendBase { PulseMainloop mMainloop; - al::optional mDeviceName{al::nullopt}; + std::optional mDeviceName{std::nullopt}; bool mIs51Rear{false}; pa_buffer_attr mAttr; @@ -1042,7 +1042,7 @@ struct PulseCapture final : public BackendBase { PulseMainloop mMainloop; - al::optional mDeviceName{al::nullopt}; + std::optional mDeviceName{std::nullopt}; al::span mCapBuffer; size_t mHoleLength{0}; diff --git a/alc/device.h b/alc/device.h index ef50f53e..d5e82ce3 100644 --- a/alc/device.h +++ b/alc/device.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -141,25 +142,25 @@ struct ALCdevice : public al::intrusive_ref, DeviceBase { { return GetConfigValueBool(DeviceName.c_str(), block, key, def); } template - inline al::optional configValue(const char *block, const char *key) = delete; + inline std::optional configValue(const char *block, const char *key) = delete; DEF_NEWDEL(ALCdevice) }; template<> -inline al::optional ALCdevice::configValue(const char *block, const char *key) +inline std::optional ALCdevice::configValue(const char *block, const char *key) { return ConfigValueStr(DeviceName.c_str(), block, key); } template<> -inline al::optional ALCdevice::configValue(const char *block, const char *key) +inline std::optional ALCdevice::configValue(const char *block, const char *key) { return ConfigValueInt(DeviceName.c_str(), block, key); } template<> -inline al::optional ALCdevice::configValue(const char *block, const char *key) +inline std::optional ALCdevice::configValue(const char *block, const char *key) { return ConfigValueUInt(DeviceName.c_str(), block, key); } template<> -inline al::optional ALCdevice::configValue(const char *block, const char *key) +inline std::optional ALCdevice::configValue(const char *block, const char *key) { return ConfigValueFloat(DeviceName.c_str(), block, key); } template<> -inline al::optional ALCdevice::configValue(const char *block, const char *key) +inline std::optional ALCdevice::configValue(const char *block, const char *key) { return ConfigValueBool(DeviceName.c_str(), block, key); } #endif diff --git a/alc/panning.cpp b/alc/panning.cpp index d118f99c..a3d639fc 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "AL/al.h" @@ -45,7 +46,6 @@ #include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" -#include "aloptional.h" #include "alspan.h" #include "alstring.h" #include "alu.h" @@ -933,7 +933,7 @@ void InitUhjPanning(ALCdevice *device) } // namespace -void aluInitRenderer(ALCdevice *device, int hrtf_id, al::optional stereomode) +void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optional stereomode) { /* Hold the HRTF the device last used, in case it's used again. */ HrtfStorePtr old_hrtf{std::move(device->mHrtf)}; diff --git a/common/aloptional.h b/common/aloptional.h deleted file mode 100644 index 45b0cf8a..00000000 --- a/common/aloptional.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef AL_OPTIONAL_H -#define AL_OPTIONAL_H - -#include - -namespace al { - -constexpr auto nullopt = std::nullopt; - -template -using optional = std::optional; - -using std::make_optional; - -} // namespace al - -#endif /* AL_OPTIONAL_H */ diff --git a/common/strutils.cpp b/common/strutils.cpp index d0418eff..b221b6ec 100644 --- a/common/strutils.cpp +++ b/common/strutils.cpp @@ -43,21 +43,21 @@ std::wstring utf8_to_wstr(const char *str) namespace al { -al::optional getenv(const char *envname) +std::optional getenv(const char *envname) { const char *str{std::getenv(envname)}; if(str && str[0] != '\0') return str; - return al::nullopt; + return std::nullopt; } #ifdef _WIN32 -al::optional getenv(const WCHAR *envname) +std::optional getenv(const WCHAR *envname) { const WCHAR *str{_wgetenv(envname)}; if(str && str[0] != L'\0') return str; - return al::nullopt; + return std::nullopt; } #endif diff --git a/common/strutils.h b/common/strutils.h index 0c7a0e22..67f057a7 100644 --- a/common/strutils.h +++ b/common/strutils.h @@ -1,10 +1,9 @@ #ifndef AL_STRUTILS_H #define AL_STRUTILS_H +#include #include -#include "aloptional.h" - #ifdef _WIN32 #include @@ -14,9 +13,9 @@ std::wstring utf8_to_wstr(const char *str); namespace al { -al::optional getenv(const char *envname); +std::optional getenv(const char *envname); #ifdef _WIN32 -al::optional getenv(const wchar_t *envname); +std::optional getenv(const wchar_t *envname); #endif } // namespace al diff --git a/core/ambdec.cpp b/core/ambdec.cpp index 8ca182c4..a056e63f 100644 --- a/core/ambdec.cpp +++ b/core/ambdec.cpp @@ -47,9 +47,9 @@ enum class ReaderScope { #else [[gnu::format(printf,2,3)]] #endif -al::optional make_error(size_t linenum, const char *fmt, ...) +std::optional make_error(size_t linenum, const char *fmt, ...) { - al::optional ret; + std::optional ret; auto &str = ret.emplace(); str.resize(256); @@ -77,7 +77,7 @@ al::optional make_error(size_t linenum, const char *fmt, ...) AmbDecConf::~AmbDecConf() = default; -al::optional AmbDecConf::load(const char *fname) noexcept +std::optional AmbDecConf::load(const char *fname) noexcept { al::ifstream f{fname}; if(!f.is_open()) @@ -291,7 +291,7 @@ al::optional AmbDecConf::load(const char *fname) noexcept if(CoeffScale == AmbDecScale::Unset) return make_error(linenum, "No coefficient scaling defined"); - return al::nullopt; + return std::nullopt; } else return make_error(linenum, "Unexpected command: %s", command.c_str()); diff --git a/core/ambdec.h b/core/ambdec.h index 7f739781..19f68697 100644 --- a/core/ambdec.h +++ b/core/ambdec.h @@ -3,9 +3,9 @@ #include #include +#include #include -#include "aloptional.h" #include "core/ambidefs.h" /* Helpers to read .ambdec configuration files. */ @@ -49,7 +49,7 @@ struct AmbDecConf { ~AmbDecConf(); - al::optional load(const char *fname) noexcept; + std::optional load(const char *fname) noexcept; }; #endif /* CORE_AMBDEC_H */ diff --git a/core/cpu_caps.cpp b/core/cpu_caps.cpp index 165edb24..1a064cf4 100644 --- a/core/cpu_caps.cpp +++ b/core/cpu_caps.cpp @@ -51,14 +51,14 @@ inline std::array get_cpuid(unsigned int f) } // namespace -al::optional GetCPUInfo() +std::optional GetCPUInfo() { CPUInfo ret; #ifdef CAN_GET_CPUID auto cpuregs = get_cpuid(0); if(cpuregs[0] == 0) - return al::nullopt; + return std::nullopt; const reg_type maxfunc{cpuregs[0]}; diff --git a/core/cpu_caps.h b/core/cpu_caps.h index ffd671d0..0826a49b 100644 --- a/core/cpu_caps.h +++ b/core/cpu_caps.h @@ -1,10 +1,9 @@ #ifndef CORE_CPU_CAPS_H #define CORE_CPU_CAPS_H +#include #include -#include "aloptional.h" - extern int CPUCapFlags; enum { @@ -21,6 +20,6 @@ struct CPUInfo { int mCaps{0}; }; -al::optional GetCPUInfo(); +std::optional GetCPUInfo(); #endif /* CORE_CPU_CAPS_H */ diff --git a/core/helpers.cpp b/core/helpers.cpp index 71ddbc23..58cc74e5 100644 --- a/core/helpers.cpp +++ b/core/helpers.cpp @@ -9,15 +9,15 @@ #include #include #include -#include #include +#include +#include #include #include #include "almalloc.h" #include "alfstream.h" #include "alnumeric.h" -#include "aloptional.h" #include "alspan.h" #include "alstring.h" #include "logging.h" @@ -38,7 +38,7 @@ bool AllowRTTimeLimit{true}; const PathNamePair &GetProcBinary() { - static al::optional procbin; + static std::optional procbin; if(procbin) return *procbin; auto fullpath = std::vector(256); @@ -209,7 +209,7 @@ void SetRTPriority(void) const PathNamePair &GetProcBinary() { - static al::optional procbin; + static std::optional procbin; if(procbin) return *procbin; std::vector pathname; diff --git a/core/hrtf.cpp b/core/hrtf.cpp index cdafe93c..c54d96d1 100644 --- a/core/hrtf.cpp +++ b/core/hrtf.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -25,7 +26,6 @@ #include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" -#include "aloptional.h" #include "alspan.h" #include "ambidefs.h" #include "filters/splitter.h" @@ -1221,7 +1221,7 @@ al::span GetResource(int name) } // namespace -al::vector EnumerateHrtf(al::optional pathopt) +al::vector EnumerateHrtf(std::optional pathopt) { std::lock_guard _{EnumeratedHrtfLock}; EnumeratedHrtfs.clear(); diff --git a/core/hrtf.h b/core/hrtf.h index eb18682a..7215711b 100644 --- a/core/hrtf.h +++ b/core/hrtf.h @@ -4,10 +4,10 @@ #include #include #include +#include #include #include "almalloc.h" -#include "aloptional.h" #include "alspan.h" #include "atomic.h" #include "ambidefs.h" @@ -83,7 +83,7 @@ struct DirectHrtfState { }; -al::vector EnumerateHrtf(al::optional pathopt); +al::vector EnumerateHrtf(std::optional pathopt); HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate); #endif /* CORE_HRTF_H */ diff --git a/core/voice.cpp b/core/voice.cpp index 6a747f85..090b10a3 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -12,13 +12,13 @@ #include #include #include +#include #include #include #include #include "albyte.h" #include "alnumeric.h" -#include "aloptional.h" #include "alspan.h" #include "alstring.h" #include "ambidefs.h" @@ -129,7 +129,7 @@ inline HrtfMixerBlendFunc SelectHrtfBlendMixer() } // namespace -void Voice::InitMixer(al::optional resampler) +void Voice::InitMixer(std::optional resampler) { if(resampler) { diff --git a/core/voice.h b/core/voice.h index 57ee7b01..9d74ff6b 100644 --- a/core/voice.h +++ b/core/voice.h @@ -6,12 +6,12 @@ #include #include #include +#include #include #include #include "albyte.h" #include "almalloc.h" -#include "aloptional.h" #include "alspan.h" #include "bufferline.h" #include "buffer_storage.h" @@ -270,7 +270,7 @@ struct Voice { void prepare(DeviceBase *device); - static void InitMixer(al::optional resampler); + static void InitMixer(std::optional resampler); DEF_NEWDEL(Voice) }; diff --git a/utils/makemhr/loaddef.cpp b/utils/makemhr/loaddef.cpp index e8092363..84fbb48b 100644 --- a/utils/makemhr/loaddef.cpp +++ b/utils/makemhr/loaddef.cpp @@ -33,11 +33,10 @@ #include #include #include -#include +#include #include #include "alfstream.h" -#include "aloptional.h" #include "alspan.h" #include "alstring.h" #include "makemhr.h" @@ -1755,7 +1754,7 @@ static int ProcessSources(TokenReaderT *tr, HrirDataT *hData, const uint outRate PPhaseResampler onsetResampler; onsetResampler.init(hData->mIrRate, OnsetRateMultiple*hData->mIrRate); - al::optional resampler; + std::optional resampler; if(outRate && outRate != hData->mIrRate) resampler.emplace().init(hData->mIrRate, outRate); const double rateScale{outRate ? static_cast(outRate) / hData->mIrRate : 1.0}; diff --git a/utils/makemhr/loadsofa.cpp b/utils/makemhr/loadsofa.cpp index dcb0a35e..9e661839 100644 --- a/utils/makemhr/loadsofa.cpp +++ b/utils/makemhr/loadsofa.cpp @@ -33,11 +33,11 @@ #include #include #include +#include #include #include #include -#include "aloptional.h" #include "alspan.h" #include "makemhr.h" #include "polyphase_resampler.h" @@ -265,7 +265,7 @@ static bool LoadResponses(MYSOFA_HRTF *sofaHrtf, HrirDataT *hData, const DelayTy double *hrirs = hData->mHrirsBase.data(); std::unique_ptr restmp; - al::optional resampler; + std::optional resampler; if(outRate && outRate != hData->mIrRate) { resampler.emplace().init(hData->mIrRate, outRate); -- cgit v1.2.3 From 3d2e586636f765eb2fccebb757305295d7b2c954 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 4 May 2023 08:33:43 -0700 Subject: Update ComPtr and use an out_ptr() function --- alc/backends/dsound.cpp | 15 ++++---- alc/backends/wasapi.cpp | 67 ++++++++++++++-------------------- common/comptr.h | 95 +++++++++++++++++++++++++++++++++++-------------- 3 files changed, 101 insertions(+), 76 deletions(-) (limited to 'alc') diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index f549c0fe..51dc36f6 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -347,7 +347,7 @@ void DSoundPlayback::open(const char *name) //DirectSound Init code ComPtr ds; if(SUCCEEDED(hr)) - hr = DirectSoundCreate(guid, ds.getPtr(), nullptr); + hr = DirectSoundCreate(guid, al::out_ptr(ds), nullptr); if(SUCCEEDED(hr)) hr = ds->SetCooperativeLevel(GetForegroundWindow(), DSSCL_PRIORITY); if(FAILED(hr)) @@ -460,7 +460,7 @@ retry_open: DSBUFFERDESC DSBDescription{}; DSBDescription.dwSize = sizeof(DSBDescription); DSBDescription.dwFlags = DSBCAPS_PRIMARYBUFFER; - hr = mDS->CreateSoundBuffer(&DSBDescription, mPrimaryBuffer.getPtr(), nullptr); + hr = mDS->CreateSoundBuffer(&DSBDescription, al::out_ptr(mPrimaryBuffer), nullptr); } if(SUCCEEDED(hr)) hr = mPrimaryBuffer->SetFormat(&OutputType.Format); @@ -480,7 +480,7 @@ retry_open: DSBDescription.dwBufferBytes = mDevice->BufferSize * OutputType.Format.nBlockAlign; DSBDescription.lpwfxFormat = &OutputType.Format; - hr = mDS->CreateSoundBuffer(&DSBDescription, mBuffer.getPtr(), nullptr); + hr = mDS->CreateSoundBuffer(&DSBDescription, al::out_ptr(mBuffer), nullptr); if(FAILED(hr) && mDevice->FmtType == DevFmtFloat) { mDevice->FmtType = DevFmtShort; @@ -490,12 +490,9 @@ retry_open: if(SUCCEEDED(hr)) { - void *ptr; - hr = mBuffer->QueryInterface(IID_IDirectSoundNotify, &ptr); + hr = mBuffer->QueryInterface(IID_IDirectSoundNotify, al::out_ptr(mNotifies)); if(SUCCEEDED(hr)) { - mNotifies = ComPtr{static_cast(ptr)}; - uint num_updates{mDevice->BufferSize / mDevice->UpdateSize}; assert(num_updates <= MAX_UPDATES); @@ -679,9 +676,9 @@ void DSoundCapture::open(const char *name) DSCBDescription.lpwfxFormat = &InputType.Format; //DirectSoundCapture Init code - hr = DirectSoundCaptureCreate(guid, mDSC.getPtr(), nullptr); + hr = DirectSoundCaptureCreate(guid, al::out_ptr(mDSC), nullptr); if(SUCCEEDED(hr)) - mDSC->CreateCaptureBuffer(&DSCBDescription, mDSCbuffer.getPtr(), nullptr); + mDSC->CreateCaptureBuffer(&DSCBDescription, al::out_ptr(mDSCbuffer), nullptr); if(SUCCEEDED(hr)) mRing = RingBuffer::Create(mDevice->BufferSize, InputType.Format.nBlockAlign, false); diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index e834eef4..e66656ce 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -199,7 +199,7 @@ NameGUIDPair get_device_name_and_guid(IMMDevice *device) std::string name, guid; ComPtr ps; - HRESULT hr = device->OpenPropertyStore(STGM_READ, ps.getPtr()); + HRESULT hr = device->OpenPropertyStore(STGM_READ, al::out_ptr(ps)); if(FAILED(hr)) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); @@ -242,7 +242,7 @@ NameGUIDPair get_device_name_and_guid(IMMDevice *device) EndpointFormFactor get_device_formfactor(IMMDevice *device) { ComPtr ps; - HRESULT hr{device->OpenPropertyStore(STGM_READ, ps.getPtr())}; + HRESULT hr{device->OpenPropertyStore(STGM_READ, al::out_ptr(ps))}; if(FAILED(hr)) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); @@ -306,7 +306,7 @@ void probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, al::vector{}.swap(list); ComPtr coll; - HRESULT hr{devenum->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, coll.getPtr())}; + HRESULT hr{devenum->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, al::out_ptr(coll))}; if(FAILED(hr)) { ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); @@ -319,7 +319,7 @@ void probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, al::vector device; - hr = devenum->GetDefaultAudioEndpoint(flowdir, eMultimedia, device.getPtr()); + hr = devenum->GetDefaultAudioEndpoint(flowdir, eMultimedia, al::out_ptr(device)); if(SUCCEEDED(hr)) { if(WCHAR *devid{get_device_id(device.get())}) @@ -327,12 +327,12 @@ void probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, al::vectorItem(i, device.getPtr()); + device = nullptr; + hr = coll->Item(i, al::out_ptr(device)); if(FAILED(hr)) continue; if(WCHAR *devid{get_device_id(device.get())}) @@ -340,7 +340,6 @@ void probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, al::vector *promise) case MsgType::EnumeratePlayback: case MsgType::EnumerateCapture: { - void *ptr{}; + ComPtr devenum; hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, &ptr); + IID_IMMDeviceEnumerator, al::out_ptr(devenum)); if(FAILED(hr)) msg.mPromise.set_value(hr); else { - ComPtr devenum{static_cast(ptr)}; - if(msg.mType == MsgType::EnumeratePlayback) probe_devices(devenum.get(), eRender, PlaybackDevices); else if(msg.mType == MsgType::EnumerateCapture) @@ -841,17 +838,16 @@ HRESULT WasapiPlayback::openProxy(const char *name) devid = iter->devid.c_str(); } - void *ptr; + ComPtr enumerator; ComPtr mmdev; HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, &ptr)}; + IID_IMMDeviceEnumerator, al::out_ptr(enumerator))}; if(SUCCEEDED(hr)) { - ComPtr enumerator{static_cast(ptr)}; if(!devid) - hr = enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, mmdev.getPtr()); + hr = enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, al::out_ptr(mmdev)); else - hr = enumerator->GetDevice(devid, mmdev.getPtr()); + hr = enumerator->GetDevice(devid, al::out_ptr(mmdev)); } if(FAILED(hr)) { @@ -886,14 +882,13 @@ HRESULT WasapiPlayback::resetProxy() { mClient = nullptr; - void *ptr; - HRESULT hr{mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, &ptr)}; + HRESULT hr{mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, + al::out_ptr(mClient))}; if(FAILED(hr)) { ERR("Failed to reactivate audio client: 0x%08lx\n", hr); return hr; } - mClient = ComPtr{static_cast(ptr)}; WAVEFORMATEX *wfx; hr = mClient->GetMixFormat(&wfx); @@ -1242,11 +1237,9 @@ HRESULT WasapiPlayback::startProxy() return hr; } - void *ptr; - hr = mClient->GetService(IID_IAudioRenderClient, &ptr); + hr = mClient->GetService(IID_IAudioRenderClient, al::out_ptr(mRender)); if(SUCCEEDED(hr)) { - mRender = ComPtr{static_cast(ptr)}; try { mKillNow.store(false, std::memory_order_release); mThread = std::thread{std::mem_fn(&WasapiPlayback::mixerProc), this}; @@ -1516,16 +1509,15 @@ HRESULT WasapiCapture::openProxy(const char *name) devid = iter->devid.c_str(); } - void *ptr; + ComPtr enumerator; HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, &ptr)}; + IID_IMMDeviceEnumerator, al::out_ptr(enumerator))}; if(SUCCEEDED(hr)) { - ComPtr enumerator{static_cast(ptr)}; if(!devid) - hr = enumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, mMMDev.getPtr()); + hr = enumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, al::out_ptr(mMMDev)); else - hr = enumerator->GetDevice(devid, mMMDev.getPtr()); + hr = enumerator->GetDevice(devid, al::out_ptr(mMMDev)); } if(FAILED(hr)) { @@ -1550,14 +1542,13 @@ HRESULT WasapiCapture::resetProxy() { mClient = nullptr; - void *ptr; - HRESULT hr{mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, &ptr)}; + HRESULT hr{mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, + al::out_ptr(mClient))}; if(FAILED(hr)) { ERR("Failed to reactivate audio client: 0x%08lx\n", hr); return hr; } - mClient = ComPtr{static_cast(ptr)}; WAVEFORMATEX *wfx; hr = mClient->GetMixFormat(&wfx); @@ -1849,11 +1840,9 @@ HRESULT WasapiCapture::startProxy() return hr; } - void *ptr; - hr = mClient->GetService(IID_IAudioCaptureClient, &ptr); + hr = mClient->GetService(IID_IAudioCaptureClient, al::out_ptr(mCapture)); if(SUCCEEDED(hr)) { - mCapture = ComPtr{static_cast(ptr)}; try { mKillNow.store(false, std::memory_order_release); mThread = std::thread{std::mem_fn(&WasapiCapture::recordProc), this}; @@ -1916,19 +1905,15 @@ bool WasapiBackendFactory::init() return hr; } - void *ptr{}; + ComPtr enumerator; hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, &ptr); + IID_IMMDeviceEnumerator, al::out_ptr(enumerator)); if(FAILED(hr)) - { WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); - CoUninitialize(); - return hr; - } - static_cast(ptr)->Release(); + enumerator = nullptr; CoUninitialize(); - return S_OK; + return hr; }); InitResult = res.get(); diff --git a/common/comptr.h b/common/comptr.h index cdc6dec0..5a733ea2 100644 --- a/common/comptr.h +++ b/common/comptr.h @@ -2,49 +2,46 @@ #define COMMON_COMPTR_H #include +#include +#include #include - -#include "opthelpers.h" - +#include template -class ComPtr { - T *mPtr{nullptr}; +struct ComPtr { + using element_type = T; + + static constexpr bool RefIsNoexcept{noexcept(std::declval().AddRef()) + && noexcept(std::declval().Release())}; -public: ComPtr() noexcept = default; - ComPtr(const ComPtr &rhs) : mPtr{rhs.mPtr} { if(mPtr) mPtr->AddRef(); } + ComPtr(const ComPtr &rhs) noexcept(RefIsNoexcept) : mPtr{rhs.mPtr} + { if(mPtr) mPtr->AddRef(); } ComPtr(ComPtr&& rhs) noexcept : mPtr{rhs.mPtr} { rhs.mPtr = nullptr; } ComPtr(std::nullptr_t) noexcept { } explicit ComPtr(T *ptr) noexcept : mPtr{ptr} { } ~ComPtr() { if(mPtr) mPtr->Release(); } - ComPtr& operator=(const ComPtr &rhs) + ComPtr& operator=(const ComPtr &rhs) noexcept(RefIsNoexcept) { - if(!rhs.mPtr) + if constexpr(RefIsNoexcept) { - if(mPtr) - mPtr->Release(); - mPtr = nullptr; + if(rhs.mPtr) rhs.mPtr->AddRef(); + if(mPtr) mPtr->Release(); + mPtr = rhs.mPtr; + return *this; } else { - rhs.mPtr->AddRef(); - try { - if(mPtr) - mPtr->Release(); - mPtr = rhs.mPtr; - } - catch(...) { - rhs.mPtr->Release(); - throw; - } + ComPtr tmp{rhs}; + if(mPtr) mPtr->Release(); + mPtr = tmp.release(); + return *this; } - return *this; } - ComPtr& operator=(ComPtr&& rhs) + ComPtr& operator=(ComPtr&& rhs) noexcept(RefIsNoexcept) { - if(&rhs != this) LIKELY + if(&rhs != this) { if(mPtr) mPtr->Release(); mPtr = std::exchange(rhs.mPtr, nullptr); @@ -52,17 +49,63 @@ public: return *this; } + void reset(T *ptr=nullptr) noexcept(RefIsNoexcept) + { + if(mPtr) mPtr->Release(); + mPtr = ptr; + } + explicit operator bool() const noexcept { return mPtr != nullptr; } T& operator*() const noexcept { return *mPtr; } T* operator->() const noexcept { return mPtr; } T* get() const noexcept { return mPtr; } - T** getPtr() noexcept { return &mPtr; } T* release() noexcept { return std::exchange(mPtr, nullptr); } void swap(ComPtr &rhs) noexcept { std::swap(mPtr, rhs.mPtr); } void swap(ComPtr&& rhs) noexcept { std::swap(mPtr, rhs.mPtr); } + +private: + T *mPtr{nullptr}; }; + +namespace al { + +template +class out_ptr_t { + static_assert(!std::is_same_v); + + SP &mRes; + std::variant mPtr{}; + +public: + out_ptr_t(SP &res) : mRes{res} { } + ~out_ptr_t() + { + auto set_res = [this](auto &ptr) + { mRes.reset(static_cast(ptr)); }; + std::visit(set_res, mPtr); + } + out_ptr_t(const out_ptr_t&) = delete; + + out_ptr_t& operator=(const out_ptr_t&) = delete; + + operator PT*() noexcept + { return &std::get(mPtr); } + + operator void**() noexcept + { return &mPtr.template emplace(); } +}; + +template +auto out_ptr(SP &res) +{ + using ptype = typename SP::element_type*; + return out_ptr_t{res}; +} + +} // namespace al + #endif -- cgit v1.2.3 From 6e0a0a2692a4303d6410c24bf83e09ca47ac6759 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 4 May 2023 09:16:59 -0700 Subject: Make and use a bit_cast function Instead of reinterpret_casting between incompatible types --- al/buffer.cpp | 2 +- al/state.cpp | 5 +++-- alc/alc.cpp | 2 +- alc/alconfig.cpp | 3 ++- alc/backends/alsa.cpp | 3 ++- alc/backends/dsound.cpp | 3 ++- alc/backends/jack.cpp | 5 +++-- alc/backends/pipewire.cpp | 9 +++++---- alc/backends/portaudio.cpp | 3 ++- alc/backends/pulseaudio.cpp | 3 ++- alc/backends/wasapi.cpp | 4 ++-- common/albit.h | 11 +++++++++++ common/dynload.cpp | 3 ++- core/dbus_wrap.cpp | 3 ++- 14 files changed, 40 insertions(+), 19 deletions(-) (limited to 'alc') diff --git a/al/buffer.cpp b/al/buffer.cpp index 4f0bcf8c..ad74a7f7 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -1463,7 +1463,7 @@ START_API_FUNC else switch(param) { case AL_BUFFER_CALLBACK_FUNCTION_SOFT: - *value = reinterpret_cast(albuf->mCallback); + *value = al::bit_cast(albuf->mCallback); break; case AL_BUFFER_CALLBACK_USER_PARAM_SOFT: *value = albuf->mUserData; diff --git a/al/state.cpp b/al/state.cpp index 77b104a4..fb3186c7 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -35,6 +35,7 @@ #include "AL/alext.h" #include "al/debug.h" +#include "albit.h" #include "alc/alu.h" #include "alc/context.h" #include "alc/inprogext.h" @@ -516,7 +517,7 @@ START_API_FUNC switch(pname) { case AL_EVENT_CALLBACK_FUNCTION_SOFT: - *values = reinterpret_cast(context->mEventCb); + *values = al::bit_cast(context->mEventCb); break; case AL_EVENT_CALLBACK_USER_PARAM_SOFT: @@ -524,7 +525,7 @@ START_API_FUNC break; case AL_DEBUG_CALLBACK_FUNCTION_EXT: - *values = reinterpret_cast(context->mDebugCb); + *values = al::bit_cast(context->mDebugCb); break; case AL_DEBUG_CALLBACK_USER_PARAM_EXT: diff --git a/alc/alc.cpp b/alc/alc.cpp index 2da5c5db..149223f4 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -180,7 +180,7 @@ BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/) case DLL_PROCESS_ATTACH: /* Pin the DLL so we won't get unloaded until the process terminates */ GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - reinterpret_cast(module), &module); + al::bit_cast(module), &module); break; } return TRUE; diff --git a/alc/alconfig.cpp b/alc/alconfig.cpp index 56cad9e0..ceb7d97b 100644 --- a/alc/alconfig.cpp +++ b/alc/alconfig.cpp @@ -38,6 +38,7 @@ #include #include +#include "albit.h" #include "alfstream.h" #include "alstring.h" #include "core/helpers.h" @@ -418,7 +419,7 @@ void ReadALConfig() if((configURL=CFBundleCopyResourceURL(mainBundle, CFSTR(".alsoftrc"), CFSTR(""), nullptr)) && CFURLGetFileSystemRepresentation(configURL, true, fileName, sizeof(fileName))) { - f = al::ifstream{reinterpret_cast(fileName)}; + f = al::ifstream{al::bit_cast(fileName)}; if(f.is_open()) LoadConfigFromFile(f); } diff --git a/alc/backends/alsa.cpp b/alc/backends/alsa.cpp index 01021868..b162f84e 100644 --- a/alc/backends/alsa.cpp +++ b/alc/backends/alsa.cpp @@ -35,6 +35,7 @@ #include #include +#include "albit.h" #include "albyte.h" #include "alc/alconfig.h" #include "almalloc.h" @@ -1204,7 +1205,7 @@ bool AlsaBackendFactory::init() error = false; #define LOAD_FUNC(f) do { \ - p##f = reinterpret_cast(GetSymbol(alsa_handle, #f)); \ + p##f = al::bit_cast(GetSymbol(alsa_handle, #f)); \ if(p##f == nullptr) { \ error = true; \ missing_funcs += "\n" #f; \ diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index 51dc36f6..8b967c95 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -44,6 +44,7 @@ #include #include +#include "albit.h" #include "alnumeric.h" #include "comptr.h" #include "core/device.h" @@ -778,7 +779,7 @@ bool DSoundBackendFactory::init() } #define LOAD_FUNC(f) do { \ - p##f = reinterpret_cast(GetSymbol(ds_handle, #f)); \ + p##f = al::bit_cast(GetSymbol(ds_handle, #f)); \ if(!p##f) \ { \ CloseLib(ds_handle); \ diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp index 791002ca..dbc2b038 100644 --- a/alc/backends/jack.cpp +++ b/alc/backends/jack.cpp @@ -31,6 +31,7 @@ #include #include +#include "albit.h" #include "alc/alconfig.h" #include "alnumeric.h" #include "core/device.h" @@ -126,7 +127,7 @@ bool jack_load() error = false; #define LOAD_FUNC(f) do { \ - p##f = reinterpret_cast(GetSymbol(jack_handle, #f)); \ + p##f = al::bit_cast(GetSymbol(jack_handle, #f)); \ if(p##f == nullptr) { \ error = true; \ missing_funcs += "\n" #f; \ @@ -135,7 +136,7 @@ bool jack_load() JACK_FUNCS(LOAD_FUNC); #undef LOAD_FUNC /* Optional symbols. These don't exist in all versions of JACK. */ -#define LOAD_SYM(f) p##f = reinterpret_cast(GetSymbol(jack_handle, #f)) +#define LOAD_SYM(f) p##f = al::bit_cast(GetSymbol(jack_handle, #f)) LOAD_SYM(jack_error_callback); #undef LOAD_SYM diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index d3c8e77e..5b1596aa 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -37,6 +37,7 @@ #include #include +#include "albit.h" #include "albyte.h" #include "alc/alconfig.h" #include "almalloc.h" @@ -210,7 +211,7 @@ bool pwire_load() } #define LOAD_FUNC(f) do { \ - p##f = reinterpret_cast(GetSymbol(pwire_handle, #f)); \ + p##f = al::bit_cast(GetSymbol(pwire_handle, #f)); \ if(p##f == nullptr) missing_funcs += "\n" #f; \ } while(0); PWIRE_FUNCS(LOAD_FUNC) @@ -328,11 +329,11 @@ To as(From) noexcept = delete; * - pw_metadata */ template<> -pw_proxy* as(pw_registry *reg) noexcept { return reinterpret_cast(reg); } +pw_proxy* as(pw_registry *reg) noexcept { return al::bit_cast(reg); } template<> -pw_proxy* as(pw_node *node) noexcept { return reinterpret_cast(node); } +pw_proxy* as(pw_node *node) noexcept { return al::bit_cast(node); } template<> -pw_proxy* as(pw_metadata *mdata) noexcept { return reinterpret_cast(mdata); } +pw_proxy* as(pw_metadata *mdata) noexcept { return al::bit_cast(mdata); } struct PwContextDeleter { diff --git a/alc/backends/portaudio.cpp b/alc/backends/portaudio.cpp index 9c94587d..d652d4cd 100644 --- a/alc/backends/portaudio.cpp +++ b/alc/backends/portaudio.cpp @@ -26,6 +26,7 @@ #include #include +#include "albit.h" #include "alc/alconfig.h" #include "alnumeric.h" #include "core/device.h" @@ -376,7 +377,7 @@ bool PortBackendFactory::init() return false; #define LOAD_FUNC(f) do { \ - p##f = reinterpret_cast(GetSymbol(pa_handle, #f)); \ + p##f = al::bit_cast(GetSymbol(pa_handle, #f)); \ if(p##f == nullptr) \ { \ CloseLib(pa_handle); \ diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index 6f706c7f..6e8bfe1b 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -38,6 +38,7 @@ #include #include +#include "albit.h" #include "albyte.h" #include "alc/alconfig.h" #include "almalloc.h" @@ -1381,7 +1382,7 @@ bool PulseBackendFactory::init() } #define LOAD_FUNC(x) do { \ - p##x = reinterpret_cast(GetSymbol(pulse_handle, #x)); \ + p##x = al::bit_cast(GetSymbol(pulse_handle, #x)); \ if(!(p##x)) { \ ret = false; \ missing_funcs += "\n" #x; \ diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index e66656ce..ea6ecbe0 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -207,7 +207,7 @@ NameGUIDPair get_device_name_and_guid(IMMDevice *device) } PropVariant pvprop; - hr = ps->GetValue(reinterpret_cast(DEVPKEY_Device_FriendlyName), pvprop.get()); + hr = ps->GetValue(al::bit_cast(DEVPKEY_Device_FriendlyName), pvprop.get()); if(FAILED(hr)) { WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); @@ -222,7 +222,7 @@ NameGUIDPair get_device_name_and_guid(IMMDevice *device) } pvprop.clear(); - hr = ps->GetValue(reinterpret_cast(PKEY_AudioEndpoint_GUID), pvprop.get()); + hr = ps->GetValue(al::bit_cast(PKEY_AudioEndpoint_GUID), pvprop.get()); if(FAILED(hr)) { WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); diff --git a/common/albit.h b/common/albit.h index ad596208..a563a4e7 100644 --- a/common/albit.h +++ b/common/albit.h @@ -2,6 +2,7 @@ #define AL_BIT_H #include +#include #include #include #if !defined(__GNUC__) && (defined(_WIN32) || defined(_WIN64)) @@ -10,6 +11,16 @@ namespace al { +template +std::enable_if_t + && std::is_trivially_copyable_v, +To> bit_cast(const From &src) noexcept +{ + union { char c; To dst; } u; + std::memcpy(&u.dst, &src, sizeof(To)); + return u.dst; +} + #ifdef __BYTE_ORDER__ enum class endian { little = __ORDER_LITTLE_ENDIAN__, diff --git a/common/dynload.cpp b/common/dynload.cpp index f1c2a7eb..86c36e00 100644 --- a/common/dynload.cpp +++ b/common/dynload.cpp @@ -3,6 +3,7 @@ #include "dynload.h" +#include "albit.h" #include "strutils.h" #ifdef _WIN32 @@ -17,7 +18,7 @@ void *LoadLib(const char *name) void CloseLib(void *handle) { FreeLibrary(static_cast(handle)); } void *GetSymbol(void *handle, const char *name) -{ return reinterpret_cast(GetProcAddress(static_cast(handle), name)); } +{ return al::bit_cast(GetProcAddress(static_cast(handle), name)); } #elif defined(HAVE_DLFCN_H) diff --git a/core/dbus_wrap.cpp b/core/dbus_wrap.cpp index 7f221706..eaddce9f 100644 --- a/core/dbus_wrap.cpp +++ b/core/dbus_wrap.cpp @@ -8,6 +8,7 @@ #include #include +#include "albit.h" #include "logging.h" @@ -21,7 +22,7 @@ void PrepareDBus() static constexpr char libname[] = "libdbus-1.so.3"; auto load_func = [](auto &f, const char *name) -> void - { f = reinterpret_cast>(GetSymbol(dbus_handle, name)); }; + { f = al::bit_cast>(GetSymbol(dbus_handle, name)); }; #define LOAD_FUNC(x) do { \ load_func(p##x, #x); \ if(!p##x) \ -- cgit v1.2.3 From 7cbf3ba2e2bab5c3aecb001e1d387c89309dbec4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 4 May 2023 11:39:13 -0700 Subject: Use std::byte instead of a custom al::byte --- CMakeLists.txt | 1 - al/buffer.cpp | 14 ++++---- al/buffer.h | 4 +-- al/event.cpp | 1 - alc/alc.cpp | 4 +-- alc/backends/alsa.cpp | 15 ++++---- alc/backends/base.cpp | 2 +- alc/backends/base.h | 4 +-- alc/backends/coreaudio.cpp | 6 ++-- alc/backends/dsound.cpp | 4 +-- alc/backends/oboe.cpp | 4 +-- alc/backends/opensl.cpp | 6 ++-- alc/backends/oss.cpp | 9 +++-- alc/backends/pipewire.cpp | 10 +++--- alc/backends/portaudio.cpp | 4 +-- alc/backends/pulseaudio.cpp | 15 ++++---- alc/backends/sndio.cpp | 16 ++++----- alc/backends/solaris.cpp | 7 ++-- alc/backends/wasapi.cpp | 4 +-- alc/backends/wave.cpp | 3 +- alc/backends/winmm.cpp | 4 +-- alc/effects/convolution.cpp | 3 +- common/albyte.h | 17 --------- common/ringbuffer.cpp | 85 ++++++++++++++++++++++----------------------- common/ringbuffer.h | 39 ++++++++++----------- core/buffer_storage.h | 4 +-- core/converter.cpp | 10 +++--- core/effects/base.h | 1 - core/fmt_traits.h | 20 +++++------ core/hrtf.cpp | 6 ++-- core/voice.cpp | 35 +++++++++---------- core/voice.h | 5 ++- utils/uhjdecoder.cpp | 53 ++++++++++++++-------------- 33 files changed, 191 insertions(+), 224 deletions(-) delete mode 100644 common/albyte.h (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index 07377ddb..fe46a688 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -589,7 +589,6 @@ check_symbol_exists(getopt unistd.h HAVE_GETOPT) # router, and certain tools and examples. set(COMMON_OBJS common/albit.h - common/albyte.h common/alcomplex.cpp common/alcomplex.h common/aldeque.h diff --git a/al/buffer.cpp b/al/buffer.cpp index ad74a7f7..1a042f46 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,6 @@ #include "AL/alext.h" #include "albit.h" -#include "albyte.h" #include "alc/context.h" #include "alc/device.h" #include "alc/inprogext.h" @@ -277,7 +277,7 @@ ALuint SanitizeAlignment(FmtType type, ALuint align) /** Loads the specified data into the buffer, using the specified format. */ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, - const FmtChannels DstChannels, const FmtType DstType, const al::byte *SrcData, + const FmtChannels DstChannels, const FmtType DstType, const std::byte *SrcData, ALbitfieldSOFT access) { if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY @@ -343,7 +343,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, */ if(newsize != ALBuf->mDataStorage.size()) { - auto newdata = al::vector(newsize, al::byte{}); + auto newdata = al::vector(newsize, std::byte{}); if((access&AL_PRESERVE_DATA_BIT_SOFT)) { const size_t tocopy{minz(newdata.size(), ALBuf->mDataStorage.size())}; @@ -437,7 +437,7 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, /** Prepares the buffer to use caller-specified storage. */ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, - const FmtChannels DstChannels, const FmtType DstType, al::byte *sdata, const ALuint sdatalen) + const FmtChannels DstChannels, const FmtType DstType, std::byte *sdata, const ALuint sdatalen) { if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY return context->setError(AL_INVALID_OPERATION, "Modifying storage for in-use buffer %u", @@ -506,7 +506,7 @@ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, #endif decltype(ALBuf->mDataStorage){}.swap(ALBuf->mDataStorage); - ALBuf->mData = {static_cast(sdata), sdatalen}; + ALBuf->mData = {static_cast(sdata), sdatalen}; #ifdef ALSOFT_EAX eax_x_ram_clear(*context->mALDevice, *ALBuf); @@ -767,7 +767,7 @@ START_API_FUNC else { LoadData(context.get(), albuf, freq, static_cast(size), usrfmt->channels, - usrfmt->type, static_cast(data), flags); + usrfmt->type, static_cast(data), flags); } } } @@ -796,7 +796,7 @@ START_API_FUNC return context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); PrepareUserPtr(context.get(), albuf, freq, usrfmt->channels, usrfmt->type, - static_cast(data), static_cast(size)); + static_cast(data), static_cast(size)); } END_API_FUNC diff --git a/al/buffer.h b/al/buffer.h index 64ebe1f3..3df1fa4c 100644 --- a/al/buffer.h +++ b/al/buffer.h @@ -2,10 +2,10 @@ #define AL_BUFFER_H #include +#include #include "AL/al.h" -#include "albyte.h" #include "alc/inprogext.h" #include "almalloc.h" #include "atomic.h" @@ -26,7 +26,7 @@ enum class EaxStorage : uint8_t { struct ALbuffer : public BufferStorage { ALbitfieldSOFT Access{0u}; - al::vector mDataStorage; + al::vector mDataStorage; ALuint OriginalSize{0}; diff --git a/al/event.cpp b/al/event.cpp index 1bc39d1e..acb4958a 100644 --- a/al/event.cpp +++ b/al/event.cpp @@ -17,7 +17,6 @@ #include "AL/al.h" #include "AL/alc.h" -#include "albyte.h" #include "alc/context.h" #include "alc/effects/base.h" #include "alc/inprogext.h" diff --git a/alc/alc.cpp b/alc/alc.cpp index 149223f4..d226b39d 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -68,7 +69,6 @@ #include "al/listener.h" #include "al/source.h" #include "albit.h" -#include "albyte.h" #include "alconfig.h" #include "almalloc.h" #include "alnumeric.h" @@ -3883,7 +3883,7 @@ START_API_FUNC return; } - backend->captureSamples(static_cast(buffer), usamples); + backend->captureSamples(static_cast(buffer), usamples); } END_API_FUNC diff --git a/alc/backends/alsa.cpp b/alc/backends/alsa.cpp index b162f84e..74713590 100644 --- a/alc/backends/alsa.cpp +++ b/alc/backends/alsa.cpp @@ -36,7 +36,6 @@ #include #include "albit.h" -#include "albyte.h" #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" @@ -439,7 +438,7 @@ struct AlsaPlayback final : public BackendBase { std::mutex mMutex; uint mFrameStep{}; - al::vector mBuffer; + al::vector mBuffer; std::atomic mKillNow{true}; std::thread mThread; @@ -585,7 +584,7 @@ int AlsaPlayback::mixerNoMMapProc() continue; } - al::byte *WritePtr{mBuffer.data()}; + std::byte *WritePtr{mBuffer.data()}; avail = snd_pcm_bytes_to_frames(mPcmHandle, static_cast(mBuffer.size())); std::lock_guard _{mMutex}; mDevice->renderSamples(WritePtr, static_cast(avail), mFrameStep); @@ -874,13 +873,13 @@ struct AlsaCapture final : public BackendBase { void open(const char *name) override; void start() override; void stop() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; ClockLatency getClockLatency() override; snd_pcm_t *mPcmHandle{nullptr}; - al::vector mBuffer; + al::vector mBuffer; bool mDoCapture{false}; RingBufferPtr mRing{nullptr}; @@ -1024,7 +1023,7 @@ void AlsaCapture::stop() /* The ring buffer implicitly captures when checking availability. * Direct access needs to explicitly capture it into temp storage. */ - auto temp = al::vector( + auto temp = al::vector( static_cast(snd_pcm_frames_to_bytes(mPcmHandle, avail))); captureSamples(temp.data(), avail); mBuffer = std::move(temp); @@ -1035,7 +1034,7 @@ void AlsaCapture::stop() mDoCapture = false; } -void AlsaCapture::captureSamples(al::byte *buffer, uint samples) +void AlsaCapture::captureSamples(std::byte *buffer, uint samples) { if(mRing) { @@ -1093,7 +1092,7 @@ void AlsaCapture::captureSamples(al::byte *buffer, uint samples) } if(samples > 0) std::fill_n(buffer, snd_pcm_frames_to_bytes(mPcmHandle, samples), - al::byte((mDevice->FmtType == DevFmtUByte) ? 0x80 : 0)); + std::byte((mDevice->FmtType == DevFmtUByte) ? 0x80 : 0)); } uint AlsaCapture::availableSamples() diff --git a/alc/backends/base.cpp b/alc/backends/base.cpp index 45254c47..ab3ad028 100644 --- a/alc/backends/base.cpp +++ b/alc/backends/base.cpp @@ -37,7 +37,7 @@ backend_exception::~backend_exception() = default; bool BackendBase::reset() { throw al::backend_exception{al::backend_error::DeviceError, "Invalid BackendBase call"}; } -void BackendBase::captureSamples(al::byte*, uint) +void BackendBase::captureSamples(std::byte*, uint) { } uint BackendBase::availableSamples() diff --git a/alc/backends/base.h b/alc/backends/base.h index b6b3d922..07b430e0 100644 --- a/alc/backends/base.h +++ b/alc/backends/base.h @@ -3,11 +3,11 @@ #include #include +#include #include #include #include -#include "albyte.h" #include "core/device.h" #include "core/except.h" @@ -26,7 +26,7 @@ struct BackendBase { virtual void start() = 0; virtual void stop() = 0; - virtual void captureSamples(al::byte *buffer, uint samples); + virtual void captureSamples(std::byte *buffer, uint samples); virtual uint availableSamples(); virtual ClockLatency getClockLatency(); diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index ae220d7a..19a1f753 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -568,7 +568,7 @@ struct CoreAudioCapture final : public BackendBase { void open(const char *name) override; void start() override; void stop() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; AudioUnit mAudioUnit{0}; @@ -598,7 +598,7 @@ OSStatus CoreAudioCapture::RecordProc(AudioUnitRenderActionFlags *ioActionFlags, AudioBufferList*) noexcept { union { - al::byte _[maxz(sizeof(AudioBufferList), offsetof(AudioBufferList, mBuffers[1]))]; + std::byte _[maxz(sizeof(AudioBufferList), offsetof(AudioBufferList, mBuffers[1]))]; AudioBufferList list; } audiobuf{}; @@ -878,7 +878,7 @@ void CoreAudioCapture::stop() ERR("AudioOutputUnitStop failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); } -void CoreAudioCapture::captureSamples(al::byte *buffer, uint samples) +void CoreAudioCapture::captureSamples(std::byte *buffer, uint samples) { if(!mConverter) { diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index 8b967c95..05117781 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -551,7 +551,7 @@ struct DSoundCapture final : public BackendBase { void open(const char *name) override; void start() override; void stop() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; ComPtr mDSC; @@ -717,7 +717,7 @@ void DSoundCapture::stop() } } -void DSoundCapture::captureSamples(al::byte *buffer, uint samples) +void DSoundCapture::captureSamples(std::byte *buffer, uint samples) { mRing->read(buffer, samples); } uint DSoundCapture::availableSamples() diff --git a/alc/backends/oboe.cpp b/alc/backends/oboe.cpp index 461f5a6a..4c47190e 100644 --- a/alc/backends/oboe.cpp +++ b/alc/backends/oboe.cpp @@ -215,7 +215,7 @@ struct OboeCapture final : public BackendBase, public oboe::AudioStreamCallback void open(const char *name) override; void start() override; void stop() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; }; @@ -322,7 +322,7 @@ void OboeCapture::stop() uint OboeCapture::availableSamples() { return static_cast(mRing->readSpace()); } -void OboeCapture::captureSamples(al::byte *buffer, uint samples) +void OboeCapture::captureSamples(std::byte *buffer, uint samples) { mRing->read(buffer, samples); } } // namespace diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp index f5b98fb8..0c2936b2 100644 --- a/alc/backends/opensl.cpp +++ b/alc/backends/opensl.cpp @@ -648,7 +648,7 @@ struct OpenSLCapture final : public BackendBase { void open(const char *name) override; void start() override; void stop() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; /* engine interfaces */ @@ -819,7 +819,7 @@ void OpenSLCapture::open(const char* name) if(SL_RESULT_SUCCESS == result) { const uint chunk_size{mDevice->UpdateSize * mFrameSize}; - const auto silence = (mDevice->FmtType == DevFmtUByte) ? al::byte{0x80} : al::byte{0}; + const auto silence = (mDevice->FmtType == DevFmtUByte) ? std::byte{0x80} : std::byte{0}; auto data = mRing->getWriteVector(); std::fill_n(data.first.buf, data.first.len*chunk_size, silence); @@ -883,7 +883,7 @@ void OpenSLCapture::stop() } } -void OpenSLCapture::captureSamples(al::byte *buffer, uint samples) +void OpenSLCapture::captureSamples(std::byte *buffer, uint samples) { const uint update_size{mDevice->UpdateSize}; const uint chunk_size{update_size * mFrameSize}; diff --git a/alc/backends/oss.cpp b/alc/backends/oss.cpp index f76024f4..9e247be1 100644 --- a/alc/backends/oss.cpp +++ b/alc/backends/oss.cpp @@ -41,7 +41,6 @@ #include #include -#include "albyte.h" #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" @@ -237,7 +236,7 @@ struct OSSPlayback final : public BackendBase { int mFd{-1}; - al::vector mMixData; + al::vector mMixData; std::atomic mKillNow{true}; std::thread mThread; @@ -283,7 +282,7 @@ int OSSPlayback::mixerProc() continue; } - al::byte *write_ptr{mMixData.data()}; + std::byte *write_ptr{mMixData.data()}; size_t to_write{mMixData.size()}; mDevice->renderSamples(write_ptr, static_cast(to_write/frame_size), frame_step); while(to_write > 0 && !mKillNow.load(std::memory_order_acquire)) @@ -449,7 +448,7 @@ struct OSScapture final : public BackendBase { void open(const char *name) override; void start() override; void stop() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; int mFd{-1}; @@ -619,7 +618,7 @@ void OSScapture::stop() ERR("Error resetting device: %s\n", strerror(errno)); } -void OSScapture::captureSamples(al::byte *buffer, uint samples) +void OSScapture::captureSamples(std::byte *buffer, uint samples) { mRing->read(buffer, samples); } uint OSScapture::availableSamples() diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 5b1596aa..3f372a4a 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #include #include "albit.h" -#include "albyte.h" #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" @@ -1528,7 +1528,7 @@ bool PipeWirePlayback::reset() * magic value. */ constexpr uint32_t pod_buffer_size{1024}; - auto pod_buffer = std::make_unique(pod_buffer_size); + auto pod_buffer = std::make_unique(pod_buffer_size); spa_pod_builder b{make_pod_builder(pod_buffer.get(), pod_buffer_size)}; const spa_pod *params{spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &info)}; @@ -1793,7 +1793,7 @@ class PipeWireCapture final : public BackendBase { void open(const char *name) override; void start() override; void stop() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; uint64_t mTargetId{PwIdAny}; @@ -1954,7 +1954,7 @@ void PipeWireCapture::open(const char *name) spa_audio_info_raw info{make_spa_info(mDevice, is51rear, UseDevType)}; constexpr uint32_t pod_buffer_size{1024}; - auto pod_buffer = std::make_unique(pod_buffer_size); + auto pod_buffer = std::make_unique(pod_buffer_size); spa_pod_builder b{make_pod_builder(pod_buffer.get(), pod_buffer_size)}; const spa_pod *params[]{spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &info)}; @@ -2055,7 +2055,7 @@ void PipeWireCapture::stop() uint PipeWireCapture::availableSamples() { return static_cast(mRing->readSpace()); } -void PipeWireCapture::captureSamples(al::byte *buffer, uint samples) +void PipeWireCapture::captureSamples(std::byte *buffer, uint samples) { mRing->read(buffer, samples); } } // namespace diff --git a/alc/backends/portaudio.cpp b/alc/backends/portaudio.cpp index d652d4cd..2551f448 100644 --- a/alc/backends/portaudio.cpp +++ b/alc/backends/portaudio.cpp @@ -248,7 +248,7 @@ struct PortCapture final : public BackendBase { void open(const char *name) override; void start() override; void stop() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; PaStream *mStream{nullptr}; @@ -349,7 +349,7 @@ void PortCapture::stop() uint PortCapture::availableSamples() { return static_cast(mRing->readSpace()); } -void PortCapture::captureSamples(al::byte *buffer, uint samples) +void PortCapture::captureSamples(std::byte *buffer, uint samples) { mRing->read(buffer, samples); } } // namespace diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index 6e8bfe1b..e5696817 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -39,7 +39,6 @@ #include #include "albit.h" -#include "albyte.h" #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" @@ -1037,7 +1036,7 @@ struct PulseCapture final : public BackendBase { void open(const char *name) override; void start() override; void stop() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; ClockLatency getClockLatency() override; @@ -1045,12 +1044,12 @@ struct PulseCapture final : public BackendBase { std::optional mDeviceName{std::nullopt}; - al::span mCapBuffer; + al::span mCapBuffer; size_t mHoleLength{0}; size_t mPacketLength{0}; uint mLastReadable{0u}; - al::byte mSilentVal{}; + std::byte mSilentVal{}; pa_buffer_attr mAttr{}; pa_sample_spec mSpec{}; @@ -1159,7 +1158,7 @@ void PulseCapture::open(const char *name) switch(mDevice->FmtType) { case DevFmtUByte: - mSilentVal = al::byte(0x80); + mSilentVal = std::byte(0x80); mSpec.format = PA_SAMPLE_U8; break; case DevFmtShort: @@ -1231,9 +1230,9 @@ void PulseCapture::stop() plock.waitForOperation(op); } -void PulseCapture::captureSamples(al::byte *buffer, uint samples) +void PulseCapture::captureSamples(std::byte *buffer, uint samples) { - al::span dstbuf{buffer, samples * pa_frame_size(&mSpec)}; + al::span dstbuf{buffer, samples * pa_frame_size(&mSpec)}; /* Capture is done in fragment-sized chunks, so we loop until we get all * that's available. @@ -1291,7 +1290,7 @@ void PulseCapture::captureSamples(al::byte *buffer, uint samples) if(!capbuf) UNLIKELY mHoleLength = caplen; else - mCapBuffer = {static_cast(capbuf), caplen}; + mCapBuffer = {static_cast(capbuf), caplen}; mPacketLength = caplen; } if(!dstbuf.empty()) diff --git a/alc/backends/sndio.cpp b/alc/backends/sndio.cpp index 077e77f2..2040dd3a 100644 --- a/alc/backends/sndio.cpp +++ b/alc/backends/sndio.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include "alnumeric.h" #include "core/device.h" @@ -36,7 +37,6 @@ #include "core/logging.h" #include "ringbuffer.h" #include "threads.h" -#include "vector.h" #include @@ -65,7 +65,7 @@ struct SndioPlayback final : public BackendBase { sio_hdl *mSndHandle{nullptr}; uint mFrameStep{}; - al::vector mBuffer; + std::vector mBuffer; std::atomic mKillNow{true}; std::thread mThread; @@ -91,7 +91,7 @@ int SndioPlayback::mixerProc() while(!mKillNow.load(std::memory_order_acquire) && mDevice->Connected.load(std::memory_order_acquire)) { - al::span buffer{mBuffer}; + al::span buffer{mBuffer}; mDevice->renderSamples(buffer.data(), static_cast(buffer.size() / frameSize), frameStep); @@ -231,9 +231,9 @@ retry_params: mBuffer.resize(mDevice->UpdateSize * par.pchan*par.bps); if(par.sig == 1) - std::fill(mBuffer.begin(), mBuffer.end(), al::byte{}); + std::fill(mBuffer.begin(), mBuffer.end(), std::byte{}); else if(par.bits == 8) - std::fill_n(mBuffer.data(), mBuffer.size(), al::byte(0x80)); + std::fill_n(mBuffer.data(), mBuffer.size(), std::byte(0x80)); else if(par.bits == 16) std::fill_n(reinterpret_cast(mBuffer.data()), mBuffer.size()/2, 0x8000); else if(par.bits == 32) @@ -283,7 +283,7 @@ struct SndioCapture final : public BackendBase { void open(const char *name) override; void start() override; void stop() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; sio_hdl *mSndHandle{nullptr}; @@ -349,7 +349,7 @@ int SndioCapture::recordProc() continue; auto data = mRing->getWriteVector(); - al::span buffer{data.first.buf, data.first.len*frameSize}; + al::span buffer{data.first.buf, data.first.len*frameSize}; while(!buffer.empty()) { size_t got{sio_read(mSndHandle, buffer.data(), buffer.size())}; @@ -496,7 +496,7 @@ void SndioCapture::stop() ERR("Error stopping device\n"); } -void SndioCapture::captureSamples(al::byte *buffer, uint samples) +void SndioCapture::captureSamples(std::byte *buffer, uint samples) { mRing->read(buffer, samples); } uint SndioCapture::availableSamples() diff --git a/alc/backends/solaris.cpp b/alc/backends/solaris.cpp index 791609ce..4eeeafac 100644 --- a/alc/backends/solaris.cpp +++ b/alc/backends/solaris.cpp @@ -39,7 +39,6 @@ #include #include -#include "albyte.h" #include "alc/alconfig.h" #include "core/device.h" #include "core/helpers.h" @@ -71,7 +70,7 @@ struct SolarisBackend final : public BackendBase { int mFd{-1}; uint mFrameStep{}; - al::vector mBuffer; + al::vector mBuffer; std::atomic mKillNow{true}; std::thread mThread; @@ -116,7 +115,7 @@ int SolarisBackend::mixerProc() continue; } - al::byte *write_ptr{mBuffer.data()}; + std::byte *write_ptr{mBuffer.data()}; size_t to_write{mBuffer.size()}; mDevice->renderSamples(write_ptr, static_cast(to_write/frame_size), frame_step); while(to_write > 0 && !mKillNow.load(std::memory_order_acquire)) @@ -231,7 +230,7 @@ bool SolarisBackend::reset() setDefaultChannelOrder(); mBuffer.resize(mDevice->UpdateSize * size_t{frame_size}); - std::fill(mBuffer.begin(), mBuffer.end(), al::byte{}); + std::fill(mBuffer.begin(), mBuffer.end(), std::byte{}); return true; } diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index ea6ecbe0..16576733 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -1309,7 +1309,7 @@ struct WasapiCapture final : public BackendBase, WasapiProxy { void stop() override; void stopProxy() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; HRESULT mOpenStatus{E_FAIL}; @@ -1881,7 +1881,7 @@ void WasapiCapture::stopProxy() } -void WasapiCapture::captureSamples(al::byte *buffer, uint samples) +void WasapiCapture::captureSamples(std::byte *buffer, uint samples) { mRing->read(buffer, samples); } uint WasapiCapture::availableSamples() diff --git a/alc/backends/wave.cpp b/alc/backends/wave.cpp index 1b40640c..f8302f1e 100644 --- a/alc/backends/wave.cpp +++ b/alc/backends/wave.cpp @@ -34,7 +34,6 @@ #include #include "albit.h" -#include "albyte.h" #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" @@ -105,7 +104,7 @@ struct WaveBackend final : public BackendBase { FILE *mFile{nullptr}; long mDataStart{-1}; - al::vector mBuffer; + al::vector mBuffer; std::atomic mKillNow{true}; std::thread mThread; diff --git a/alc/backends/winmm.cpp b/alc/backends/winmm.cpp index 38e1193f..135b59df 100644 --- a/alc/backends/winmm.cpp +++ b/alc/backends/winmm.cpp @@ -372,7 +372,7 @@ struct WinMMCapture final : public BackendBase { void open(const char *name) override; void start() override; void stop() override; - void captureSamples(al::byte *buffer, uint samples) override; + void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; std::atomic mReadable{0u}; @@ -571,7 +571,7 @@ void WinMMCapture::stop() mIdx = 0; } -void WinMMCapture::captureSamples(al::byte *buffer, uint samples) +void WinMMCapture::captureSamples(std::byte *buffer, uint samples) { mRing->read(buffer, samples); } uint WinMMCapture::availableSamples() diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index 7f36c415..4ca31246 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -17,7 +17,6 @@ #include #endif -#include "albyte.h" #include "alcomplex.h" #include "almalloc.h" #include "alnumbers.h" @@ -72,7 +71,7 @@ namespace { */ -void LoadSamples(float *RESTRICT dst, const al::byte *src, const size_t srcstep, FmtType srctype, +void LoadSamples(float *RESTRICT dst, const std::byte *src, const size_t srcstep, FmtType srctype, const size_t samples) noexcept { #define HANDLE_FMT(T) case T: al::LoadSampleArray(dst, src, srcstep, samples); break diff --git a/common/albyte.h b/common/albyte.h deleted file mode 100644 index be586869..00000000 --- a/common/albyte.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef AL_BYTE_H -#define AL_BYTE_H - -#include -#include -#include -#include - -using uint = unsigned int; - -namespace al { - -using byte = unsigned char; - -} // namespace al - -#endif /* AL_BYTE_H */ diff --git a/common/ringbuffer.cpp b/common/ringbuffer.cpp index 0aec1d49..af1f3669 100644 --- a/common/ringbuffer.cpp +++ b/common/ringbuffer.cpp @@ -29,9 +29,9 @@ #include "almalloc.h" -RingBufferPtr RingBuffer::Create(size_t sz, size_t elem_sz, int limit_writes) +RingBufferPtr RingBuffer::Create(std::size_t sz, std::size_t elem_sz, int limit_writes) { - size_t power_of_two{0u}; + std::size_t power_of_two{0u}; if(sz > 0) { power_of_two = sz; @@ -40,15 +40,14 @@ RingBufferPtr RingBuffer::Create(size_t sz, size_t elem_sz, int limit_writes) power_of_two |= power_of_two>>4; power_of_two |= power_of_two>>8; power_of_two |= power_of_two>>16; -#if SIZE_MAX > UINT_MAX - power_of_two |= power_of_two>>32; -#endif + if constexpr(SIZE_MAX > UINT_MAX) + power_of_two |= power_of_two>>32; } ++power_of_two; - if(power_of_two <= sz || power_of_two > std::numeric_limits::max()/elem_sz) + if(power_of_two <= sz || power_of_two > std::numeric_limits::max()/elem_sz) throw std::overflow_error{"Ring buffer size overflow"}; - const size_t bufbytes{power_of_two * elem_sz}; + const std::size_t bufbytes{power_of_two * elem_sz}; RingBufferPtr rb{new(FamCount(bufbytes)) RingBuffer{bufbytes}}; rb->mWriteSize = limit_writes ? sz : (power_of_two-1); rb->mSizeMask = power_of_two - 1; @@ -61,20 +60,20 @@ void RingBuffer::reset() noexcept { mWritePtr.store(0, std::memory_order_relaxed); mReadPtr.store(0, std::memory_order_relaxed); - std::fill_n(mBuffer.begin(), (mSizeMask+1)*mElemSize, al::byte{}); + std::fill_n(mBuffer.begin(), (mSizeMask+1)*mElemSize, std::byte{}); } -size_t RingBuffer::read(void *dest, size_t cnt) noexcept +std::size_t RingBuffer::read(void *dest, std::size_t cnt) noexcept { - const size_t free_cnt{readSpace()}; + const std::size_t free_cnt{readSpace()}; if(free_cnt == 0) return 0; - const size_t to_read{std::min(cnt, free_cnt)}; - size_t read_ptr{mReadPtr.load(std::memory_order_relaxed) & mSizeMask}; + const std::size_t to_read{std::min(cnt, free_cnt)}; + std::size_t read_ptr{mReadPtr.load(std::memory_order_relaxed) & mSizeMask}; - size_t n1, n2; - const size_t cnt2{read_ptr + to_read}; + std::size_t n1, n2; + const std::size_t cnt2{read_ptr + to_read}; if(cnt2 > mSizeMask+1) { n1 = mSizeMask+1 - read_ptr; @@ -87,7 +86,7 @@ size_t RingBuffer::read(void *dest, size_t cnt) noexcept } auto outiter = std::copy_n(mBuffer.begin() + read_ptr*mElemSize, n1*mElemSize, - static_cast(dest)); + static_cast(dest)); read_ptr += n1; if(n2 > 0) { @@ -98,16 +97,16 @@ size_t RingBuffer::read(void *dest, size_t cnt) noexcept return to_read; } -size_t RingBuffer::peek(void *dest, size_t cnt) const noexcept +std::size_t RingBuffer::peek(void *dest, std::size_t cnt) const noexcept { - const size_t free_cnt{readSpace()}; + const std::size_t free_cnt{readSpace()}; if(free_cnt == 0) return 0; - const size_t to_read{std::min(cnt, free_cnt)}; - size_t read_ptr{mReadPtr.load(std::memory_order_relaxed) & mSizeMask}; + const std::size_t to_read{std::min(cnt, free_cnt)}; + std::size_t read_ptr{mReadPtr.load(std::memory_order_relaxed) & mSizeMask}; - size_t n1, n2; - const size_t cnt2{read_ptr + to_read}; + std::size_t n1, n2; + const std::size_t cnt2{read_ptr + to_read}; if(cnt2 > mSizeMask+1) { n1 = mSizeMask+1 - read_ptr; @@ -120,22 +119,22 @@ size_t RingBuffer::peek(void *dest, size_t cnt) const noexcept } auto outiter = std::copy_n(mBuffer.begin() + read_ptr*mElemSize, n1*mElemSize, - static_cast(dest)); + static_cast(dest)); if(n2 > 0) std::copy_n(mBuffer.begin(), n2*mElemSize, outiter); return to_read; } -size_t RingBuffer::write(const void *src, size_t cnt) noexcept +std::size_t RingBuffer::write(const void *src, std::size_t cnt) noexcept { - const size_t free_cnt{writeSpace()}; + const std::size_t free_cnt{writeSpace()}; if(free_cnt == 0) return 0; - const size_t to_write{std::min(cnt, free_cnt)}; - size_t write_ptr{mWritePtr.load(std::memory_order_relaxed) & mSizeMask}; + const std::size_t to_write{std::min(cnt, free_cnt)}; + std::size_t write_ptr{mWritePtr.load(std::memory_order_relaxed) & mSizeMask}; - size_t n1, n2; - const size_t cnt2{write_ptr + to_write}; + std::size_t n1, n2; + const std::size_t cnt2{write_ptr + to_write}; if(cnt2 > mSizeMask+1) { n1 = mSizeMask+1 - write_ptr; @@ -147,7 +146,7 @@ size_t RingBuffer::write(const void *src, size_t cnt) noexcept n2 = 0; } - auto srcbytes = static_cast(src); + auto srcbytes = static_cast(src); std::copy_n(srcbytes, n1*mElemSize, mBuffer.begin() + write_ptr*mElemSize); write_ptr += n1; if(n2 > 0) @@ -164,26 +163,26 @@ auto RingBuffer::getReadVector() const noexcept -> DataPair { DataPair ret; - size_t w{mWritePtr.load(std::memory_order_acquire)}; - size_t r{mReadPtr.load(std::memory_order_acquire)}; + std::size_t w{mWritePtr.load(std::memory_order_acquire)}; + std::size_t r{mReadPtr.load(std::memory_order_acquire)}; w &= mSizeMask; r &= mSizeMask; - const size_t free_cnt{(w-r) & mSizeMask}; + const std::size_t free_cnt{(w-r) & mSizeMask}; - const size_t cnt2{r + free_cnt}; + const std::size_t cnt2{r + free_cnt}; if(cnt2 > mSizeMask+1) { /* Two part vector: the rest of the buffer after the current read ptr, * plus some from the start of the buffer. */ - ret.first.buf = const_cast(mBuffer.data() + r*mElemSize); + ret.first.buf = const_cast(mBuffer.data() + r*mElemSize); ret.first.len = mSizeMask+1 - r; - ret.second.buf = const_cast(mBuffer.data()); + ret.second.buf = const_cast(mBuffer.data()); ret.second.len = cnt2 & mSizeMask; } else { /* Single part vector: just the rest of the buffer */ - ret.first.buf = const_cast(mBuffer.data() + r*mElemSize); + ret.first.buf = const_cast(mBuffer.data() + r*mElemSize); ret.first.len = free_cnt; ret.second.buf = nullptr; ret.second.len = 0; @@ -196,25 +195,25 @@ auto RingBuffer::getWriteVector() const noexcept -> DataPair { DataPair ret; - size_t w{mWritePtr.load(std::memory_order_acquire)}; - size_t r{mReadPtr.load(std::memory_order_acquire) + mWriteSize - mSizeMask}; + std::size_t w{mWritePtr.load(std::memory_order_acquire)}; + std::size_t r{mReadPtr.load(std::memory_order_acquire) + mWriteSize - mSizeMask}; w &= mSizeMask; r &= mSizeMask; - const size_t free_cnt{(r-w-1) & mSizeMask}; + const std::size_t free_cnt{(r-w-1) & mSizeMask}; - const size_t cnt2{w + free_cnt}; + const std::size_t cnt2{w + free_cnt}; if(cnt2 > mSizeMask+1) { /* Two part vector: the rest of the buffer after the current write ptr, * plus some from the start of the buffer. */ - ret.first.buf = const_cast(mBuffer.data() + w*mElemSize); + ret.first.buf = const_cast(mBuffer.data() + w*mElemSize); ret.first.len = mSizeMask+1 - w; - ret.second.buf = const_cast(mBuffer.data()); + ret.second.buf = const_cast(mBuffer.data()); ret.second.len = cnt2 & mSizeMask; } else { - ret.first.buf = const_cast(mBuffer.data() + w*mElemSize); + ret.first.buf = const_cast(mBuffer.data() + w*mElemSize); ret.first.len = free_cnt; ret.second.buf = nullptr; ret.second.len = 0; diff --git a/common/ringbuffer.h b/common/ringbuffer.h index 2a3797b0..8c65c3af 100644 --- a/common/ringbuffer.h +++ b/common/ringbuffer.h @@ -2,11 +2,10 @@ #define RINGBUFFER_H #include +#include #include -#include #include -#include "albyte.h" #include "almalloc.h" @@ -18,23 +17,23 @@ struct RingBuffer { private: - std::atomic mWritePtr{0u}; - std::atomic mReadPtr{0u}; - size_t mWriteSize{0u}; - size_t mSizeMask{0u}; - size_t mElemSize{0u}; + std::atomic mWritePtr{0u}; + std::atomic mReadPtr{0u}; + std::size_t mWriteSize{0u}; + std::size_t mSizeMask{0u}; + std::size_t mElemSize{0u}; - al::FlexArray mBuffer; + al::FlexArray mBuffer; public: struct Data { - al::byte *buf; - size_t len; + std::byte *buf; + std::size_t len; }; using DataPair = std::pair; - RingBuffer(const size_t count) : mBuffer{count} { } + RingBuffer(const std::size_t count) : mBuffer{count} { } /** Reset the read and write pointers to zero. This is not thread safe. */ void reset() noexcept; @@ -56,7 +55,7 @@ public: * Return the number of elements available for reading. This is the number * of elements in front of the read pointer and behind the write pointer. */ - size_t readSpace() const noexcept + std::size_t readSpace() const noexcept { const size_t w{mWritePtr.load(std::memory_order_acquire)}; const size_t r{mReadPtr.load(std::memory_order_acquire)}; @@ -67,14 +66,14 @@ public: * The copying data reader. Copy at most `cnt' elements into `dest'. * Returns the actual number of elements copied. */ - size_t read(void *dest, size_t cnt) noexcept; + std::size_t read(void *dest, std::size_t cnt) noexcept; /** * The copying data reader w/o read pointer advance. Copy at most `cnt' * elements into `dest'. Returns the actual number of elements copied. */ - size_t peek(void *dest, size_t cnt) const noexcept; + std::size_t peek(void *dest, std::size_t cnt) const noexcept; /** Advance the read pointer `cnt' places. */ - void readAdvance(size_t cnt) noexcept + void readAdvance(std::size_t cnt) noexcept { mReadPtr.fetch_add(cnt, std::memory_order_acq_rel); } @@ -82,7 +81,7 @@ public: * Return the number of elements available for writing. This is the number * of elements in front of the write pointer and behind the read pointer. */ - size_t writeSpace() const noexcept + std::size_t writeSpace() const noexcept { const size_t w{mWritePtr.load(std::memory_order_acquire)}; const size_t r{mReadPtr.load(std::memory_order_acquire) + mWriteSize - mSizeMask}; @@ -93,12 +92,12 @@ public: * The copying data writer. Copy at most `cnt' elements from `src'. Returns * the actual number of elements copied. */ - size_t write(const void *src, size_t cnt) noexcept; + std::size_t write(const void *src, std::size_t cnt) noexcept; /** Advance the write pointer `cnt' places. */ - void writeAdvance(size_t cnt) noexcept + void writeAdvance(std::size_t cnt) noexcept { mWritePtr.fetch_add(cnt, std::memory_order_acq_rel); } - size_t getElemSize() const noexcept { return mElemSize; } + std::size_t getElemSize() const noexcept { return mElemSize; } /** * Create a new ringbuffer to hold at least `sz' elements of `elem_sz' @@ -106,7 +105,7 @@ public: * (even if it is already a power of two, to ensure the requested amount * can be written). */ - static std::unique_ptr Create(size_t sz, size_t elem_sz, int limit_writes); + static std::unique_ptr Create(std::size_t sz, std::size_t elem_sz, int limit_writes); DEF_FAM_NEWDEL(RingBuffer, mBuffer) }; diff --git a/core/buffer_storage.h b/core/buffer_storage.h index 282d5b53..d8ab0b67 100644 --- a/core/buffer_storage.h +++ b/core/buffer_storage.h @@ -2,8 +2,8 @@ #define CORE_BUFFER_STORAGE_H #include +#include -#include "albyte.h" #include "alnumeric.h" #include "alspan.h" #include "ambidefs.h" @@ -85,7 +85,7 @@ struct BufferStorage { CallbackType mCallback{nullptr}; void *mUserData{nullptr}; - al::span mData; + al::span mData; uint mSampleRate{0u}; FmtChannels mChannels{FmtMono}; diff --git a/core/converter.cpp b/core/converter.cpp index a5141448..b3994d3f 100644 --- a/core/converter.cpp +++ b/core/converter.cpp @@ -6,12 +6,12 @@ #include #include #include +#include #include #include #include #include "albit.h" -#include "albyte.h" #include "alnumeric.h" #include "fpu_ctrl.h" @@ -219,7 +219,7 @@ uint SampleConverter::convert(const void **src, uint *srcframes, void *dst, uint const uint SrcFrameSize{static_cast(mChan.size()) * mSrcTypeSize}; const uint DstFrameSize{static_cast(mChan.size()) * mDstTypeSize}; const uint increment{mIncrement}; - auto SamplesIn = static_cast(*src); + auto SamplesIn = static_cast(*src); uint NumSrcSamples{*srcframes}; FPUCtl mixer_mode{}; @@ -265,8 +265,8 @@ uint SampleConverter::convert(const void **src, uint *srcframes, void *dst, uint for(size_t chan{0u};chan < mChan.size();chan++) { - const al::byte *SrcSamples{SamplesIn + mSrcTypeSize*chan}; - al::byte *DstSamples = static_cast(dst) + mDstTypeSize*chan; + const std::byte *SrcSamples{SamplesIn + mSrcTypeSize*chan}; + std::byte *DstSamples = static_cast(dst) + mDstTypeSize*chan; /* Load the previous samples into the source data first, then the * new samples from the input buffer. @@ -299,7 +299,7 @@ uint SampleConverter::convert(const void **src, uint *srcframes, void *dst, uint SamplesIn += SrcFrameSize*srcread; NumSrcSamples -= srcread; - dst = static_cast(dst) + DstFrameSize*DstSize; + dst = static_cast(dst) + DstFrameSize*DstSize; pos += DstSize; } diff --git a/core/effects/base.h b/core/effects/base.h index 4ee19f37..b02d33b7 100644 --- a/core/effects/base.h +++ b/core/effects/base.h @@ -3,7 +3,6 @@ #include -#include "albyte.h" #include "almalloc.h" #include "alspan.h" #include "atomic.h" diff --git a/core/fmt_traits.h b/core/fmt_traits.h index f797f836..1879c81b 100644 --- a/core/fmt_traits.h +++ b/core/fmt_traits.h @@ -1,10 +1,9 @@ #ifndef CORE_FMT_TRAITS_H #define CORE_FMT_TRAITS_H -#include +#include #include -#include "albyte.h" #include "buffer_storage.h" @@ -22,36 +21,35 @@ struct FmtTypeTraits { using Type = uint8_t; template - static constexpr inline OutT to(const Type val) noexcept - { return val*OutT{1.0/128.0} - OutT{1.0}; } + static constexpr OutT to(const Type val) noexcept { return val*OutT{1.0/128.0} - OutT{1.0}; } }; template<> struct FmtTypeTraits { using Type = int16_t; template - static constexpr inline OutT to(const Type val) noexcept { return val*OutT{1.0/32768.0}; } + static constexpr OutT to(const Type val) noexcept { return val*OutT{1.0/32768.0}; } }; template<> struct FmtTypeTraits { using Type = float; template - static constexpr inline OutT to(const Type val) noexcept { return val; } + static constexpr OutT to(const Type val) noexcept { return val; } }; template<> struct FmtTypeTraits { using Type = double; template - static constexpr inline OutT to(const Type val) noexcept { return static_cast(val); } + static constexpr OutT to(const Type val) noexcept { return static_cast(val); } }; template<> struct FmtTypeTraits { using Type = uint8_t; template - static constexpr inline OutT to(const Type val) noexcept + static constexpr OutT to(const Type val) noexcept { return muLawDecompressionTable[val] * OutT{1.0/32768.0}; } }; template<> @@ -59,14 +57,14 @@ struct FmtTypeTraits { using Type = uint8_t; template - static constexpr inline OutT to(const Type val) noexcept + static constexpr OutT to(const Type val) noexcept { return aLawDecompressionTable[val] * OutT{1.0/32768.0}; } }; template -inline void LoadSampleArray(DstT *RESTRICT dst, const al::byte *src, const size_t srcstep, - const size_t samples) noexcept +inline void LoadSampleArray(DstT *RESTRICT dst, const std::byte *src, const std::size_t srcstep, + const std::size_t samples) noexcept { using TypeTraits = FmtTypeTraits; using SampleType = typename TypeTraits::Type; diff --git a/core/hrtf.cpp b/core/hrtf.cpp index c54d96d1..1d9bc368 100644 --- a/core/hrtf.cpp +++ b/core/hrtf.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -21,7 +22,6 @@ #include #include "albit.h" -#include "albyte.h" #include "alfstream.h" #include "almalloc.h" #include "alnumbers.h" @@ -492,10 +492,10 @@ T> readle(std::istream &data) static_assert(num_bits <= sizeof(T)*8, "num_bits is too large for the type"); T ret{}; - al::byte b[sizeof(T)]{}; + std::byte b[sizeof(T)]{}; if(!data.read(reinterpret_cast(b), num_bits/8)) return static_cast(EOF); - std::reverse_copy(std::begin(b), std::end(b), reinterpret_cast(&ret)); + std::reverse_copy(std::begin(b), std::end(b), reinterpret_cast(&ret)); return fixsign(ret); } diff --git a/core/voice.cpp b/core/voice.cpp index 090b10a3..cbf84c2a 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -17,7 +17,6 @@ #include #include -#include "albyte.h" #include "alnumeric.h" #include "alspan.h" #include "alstring.h" @@ -264,7 +263,7 @@ const float *DoFilters(BiquadFilter &lpfilter, BiquadFilter &hpfilter, float *ds template -inline void LoadSamples(float *RESTRICT dstSamples, const al::byte *src, const size_t srcChan, +inline void LoadSamples(float *RESTRICT dstSamples, const std::byte *src, const size_t srcChan, const size_t srcOffset, const size_t srcStep, const size_t /*samplesPerBlock*/, const size_t samplesToLoad) noexcept { @@ -275,7 +274,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const al::byte *src, const s } template<> -inline void LoadSamples(float *RESTRICT dstSamples, const al::byte *src, +inline void LoadSamples(float *RESTRICT dstSamples, const std::byte *src, const size_t srcChan, const size_t srcOffset, const size_t srcStep, const size_t samplesPerBlock, const size_t samplesToLoad) noexcept { @@ -293,8 +292,8 @@ inline void LoadSamples(float *RESTRICT dstSamples, const al::byte *src /* Each IMA4 block starts with a signed 16-bit sample, and a signed * 16-bit table index. The table index needs to be clamped. */ - int sample{src[srcChan*4] | (src[srcChan*4 + 1] << 8)}; - int index{src[srcChan*4 + 2] | (src[srcChan*4 + 3] << 8)}; + int sample{int(src[srcChan*4]) | (int(src[srcChan*4 + 1]) << 8)}; + int index{int(src[srcChan*4 + 2]) | (int(src[srcChan*4 + 3]) << 8)}; sample = (sample^0x8000) - 32768; index = clampi((index^0x8000) - 32768, 0, MaxStepIndex); @@ -326,7 +325,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const al::byte *src * always be less than the block size). They need to be decoded despite * being ignored for proper state on the remaining samples. */ - const al::byte *nibbleData{src + (srcStep+srcChan)*4}; + const std::byte *nibbleData{src + (srcStep+srcChan)*4}; size_t nibbleOffset{0}; const size_t startOffset{skip + 1}; for(;skip;--skip) @@ -336,7 +335,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const al::byte *src const size_t byteOffset{wordOffset*srcStep + ((nibbleOffset>>1)&3u)}; ++nibbleOffset; - std::ignore = decode_sample((nibbleData[byteOffset]>>byteShift) & 15u); + std::ignore = decode_sample(uint(nibbleData[byteOffset]>>byteShift) & 15u); } /* Second, decode the rest of the block and write to the output, until @@ -350,7 +349,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const al::byte *src const size_t byteOffset{wordOffset*srcStep + ((nibbleOffset>>1)&3u)}; ++nibbleOffset; - const int result{decode_sample((nibbleData[byteOffset]>>byteShift) & 15u)}; + const int result{decode_sample(uint(nibbleData[byteOffset]>>byteShift) & 15u)}; dstSamples[wrote++] = static_cast(result) / 32768.0f; } if(wrote == samplesToLoad) @@ -361,7 +360,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const al::byte *src } template<> -inline void LoadSamples(float *RESTRICT dstSamples, const al::byte *src, +inline void LoadSamples(float *RESTRICT dstSamples, const std::byte *src, const size_t srcChan, const size_t srcOffset, const size_t srcStep, const size_t samplesPerBlock, const size_t samplesToLoad) noexcept { @@ -378,16 +377,16 @@ inline void LoadSamples(float *RESTRICT dstSamples, const al::byte * * nibble sample value. This is followed by the two initial 16-bit * sample history values. */ - const al::byte *input{src}; - const uint8_t blockpred{std::min(input[srcChan], uint8_t{6})}; + const std::byte *input{src}; + const uint8_t blockpred{std::min(uint8_t(input[srcChan]), uint8_t{6})}; input += srcStep; - int delta{input[2*srcChan + 0] | (input[2*srcChan + 1] << 8)}; + int delta{int(input[2*srcChan + 0]) | (int(input[2*srcChan + 1]) << 8)}; input += srcStep*2; int sampleHistory[2]{}; - sampleHistory[0] = input[2*srcChan + 0] | (input[2*srcChan + 1]<<8); + sampleHistory[0] = int(input[2*srcChan + 0]) | (int(input[2*srcChan + 1])<<8); input += srcStep*2; - sampleHistory[1] = input[2*srcChan + 0] | (input[2*srcChan + 1]<<8); + sampleHistory[1] = int(input[2*srcChan + 0]) | (int(input[2*srcChan + 1])<<8); input += srcStep*2; const auto coeffs = al::as_span(MSADPCMAdaptionCoeff[blockpred]); @@ -440,7 +439,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const al::byte * const size_t byteShift{((nibbleOffset&1)^1) * 4}; nibbleOffset += srcStep; - std::ignore = decode_sample((input[byteOffset]>>byteShift) & 15); + std::ignore = decode_sample(int(input[byteOffset]>>byteShift) & 15); } /* Now decode the rest of the block, until the end of the block or the @@ -453,7 +452,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const al::byte * const size_t byteShift{((nibbleOffset&1)^1) * 4}; nibbleOffset += srcStep; - const int sample{decode_sample((input[byteOffset]>>byteShift) & 15)}; + const int sample{decode_sample(int(input[byteOffset]>>byteShift) & 15)}; dstSamples[wrote++] = static_cast(sample) / 32768.0f; } if(wrote == samplesToLoad) @@ -463,7 +462,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const al::byte * } while(true); } -void LoadSamples(float *dstSamples, const al::byte *src, const size_t srcChan, +void LoadSamples(float *dstSamples, const std::byte *src, const size_t srcChan, const size_t srcOffset, const FmtType srcType, const size_t srcStep, const size_t samplesPerBlock, const size_t samplesToLoad) noexcept { @@ -1102,7 +1101,7 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi { const size_t byteOffset{blocksDone*mBytesPerBlock}; const size_t byteEnd{mNumCallbackBlocks*mBytesPerBlock}; - al::byte *data{BufferListItem->mSamples}; + std::byte *data{BufferListItem->mSamples}; std::copy(data+byteOffset, data+byteEnd, data); mNumCallbackBlocks -= blocksDone; mCallbackBlockBase += blocksDone; diff --git a/core/voice.h b/core/voice.h index 9d74ff6b..a599eda8 100644 --- a/core/voice.h +++ b/core/voice.h @@ -5,12 +5,11 @@ #include #include #include +#include #include #include -#include #include -#include "albyte.h" #include "almalloc.h" #include "alspan.h" #include "bufferline.h" @@ -100,7 +99,7 @@ struct VoiceBufferItem { uint mLoopStart{0u}; uint mLoopEnd{0u}; - al::byte *mSamples{nullptr}; + std::byte *mSamples{nullptr}; }; diff --git a/utils/uhjdecoder.cpp b/utils/uhjdecoder.cpp index 6d992e30..c7efa376 100644 --- a/utils/uhjdecoder.cpp +++ b/utils/uhjdecoder.cpp @@ -26,15 +26,14 @@ #include #include +#include #include #include -#include #include #include #include #include "albit.h" -#include "albyte.h" #include "alcomplex.h" #include "almalloc.h" #include "alnumbers.h" @@ -64,7 +63,7 @@ using ushort = unsigned short; using uint = unsigned int; using complex_d = std::complex; -using byte4 = std::array; +using byte4 = std::array; constexpr ubyte SUBTYPE_BFORMAT_FLOAT[]{ @@ -113,7 +112,7 @@ using FloatBufferSpan = al::span; struct UhjDecoder { - constexpr static size_t sFilterDelay{1024}; + constexpr static std::size_t sFilterDelay{1024}; alignas(16) std::array mS{}; alignas(16) std::array mD{}; @@ -126,10 +125,10 @@ struct UhjDecoder { alignas(16) std::array mTemp{}; - void decode(const float *RESTRICT InSamples, const size_t InChannels, - const al::span OutSamples, const size_t SamplesToDo); + void decode(const float *RESTRICT InSamples, const std::size_t InChannels, + const al::span OutSamples, const std::size_t SamplesToDo); void decode2(const float *RESTRICT InSamples, const al::span OutSamples, - const size_t SamplesToDo); + const std::size_t SamplesToDo); DEF_NEWDEL(UhjDecoder) }; @@ -210,8 +209,8 @@ const PhaseShifterT PShift{}; * * Not halving produces a result matching the original input. */ -void UhjDecoder::decode(const float *RESTRICT InSamples, const size_t InChannels, - const al::span OutSamples, const size_t SamplesToDo) +void UhjDecoder::decode(const float *RESTRICT InSamples, const std::size_t InChannels, + const al::span OutSamples, const std::size_t SamplesToDo) { ASSUME(SamplesToDo > 0); @@ -224,23 +223,23 @@ void UhjDecoder::decode(const float *RESTRICT InSamples, const size_t InChannels */ /* S = Left + Right */ - for(size_t i{0};i < SamplesToDo;++i) + for(std::size_t i{0};i < SamplesToDo;++i) mS[sFilterDelay+i] = InSamples[i*InChannels + 0] + InSamples[i*InChannels + 1]; /* D = Left - Right */ - for(size_t i{0};i < SamplesToDo;++i) + for(std::size_t i{0};i < SamplesToDo;++i) mD[sFilterDelay+i] = InSamples[i*InChannels + 0] - InSamples[i*InChannels + 1]; if(InChannels > 2) { /* T */ - for(size_t i{0};i < SamplesToDo;++i) + for(std::size_t i{0};i < SamplesToDo;++i) mT[sFilterDelay+i] = InSamples[i*InChannels + 2]; } if(InChannels > 3) { /* Q */ - for(size_t i{0};i < SamplesToDo;++i) + for(std::size_t i{0};i < SamplesToDo;++i) mQ[sFilterDelay+i] = InSamples[i*InChannels + 3]; } @@ -251,7 +250,7 @@ void UhjDecoder::decode(const float *RESTRICT InSamples, const size_t InChannels std::copy_n(mTemp.cbegin()+SamplesToDo, mDTHistory.size(), mDTHistory.begin()); PShift.process({xoutput, SamplesToDo}, mTemp.data()); - for(size_t i{0};i < SamplesToDo;++i) + for(std::size_t i{0};i < SamplesToDo;++i) { /* W = 0.981532*S + 0.197484*j(0.828331*D + 0.767820*T) */ woutput[i] = 0.981532f*mS[i] + 0.197484f*xoutput[i]; @@ -265,7 +264,7 @@ void UhjDecoder::decode(const float *RESTRICT InSamples, const size_t InChannels std::copy_n(mTemp.cbegin()+SamplesToDo, mSHistory.size(), mSHistory.begin()); PShift.process({youtput, SamplesToDo}, mTemp.data()); - for(size_t i{0};i < SamplesToDo;++i) + for(std::size_t i{0};i < SamplesToDo;++i) { /* Y = 0.795968*D - 0.676392*T + j(0.186633*S) */ youtput[i] = 0.795968f*mD[i] - 0.676392f*mT[i] + 0.186633f*youtput[i]; @@ -275,7 +274,7 @@ void UhjDecoder::decode(const float *RESTRICT InSamples, const size_t InChannels { float *zoutput{OutSamples[3].data()}; /* Z = 1.023332*Q */ - for(size_t i{0};i < SamplesToDo;++i) + for(std::size_t i{0};i < SamplesToDo;++i) zoutput[i] = 1.023332f*mQ[i]; } @@ -305,7 +304,7 @@ void UhjDecoder::decode(const float *RESTRICT InSamples, const size_t InChannels * halving here is merely a -6dB reduction in output, but it's still incorrect. */ void UhjDecoder::decode2(const float *RESTRICT InSamples, - const al::span OutSamples, const size_t SamplesToDo) + const al::span OutSamples, const std::size_t SamplesToDo) { ASSUME(SamplesToDo > 0); @@ -314,11 +313,11 @@ void UhjDecoder::decode2(const float *RESTRICT InSamples, float *youtput{OutSamples[2].data()}; /* S = Left + Right */ - for(size_t i{0};i < SamplesToDo;++i) + for(std::size_t i{0};i < SamplesToDo;++i) mS[sFilterDelay+i] = InSamples[i*2 + 0] + InSamples[i*2 + 1]; /* D = Left - Right */ - for(size_t i{0};i < SamplesToDo;++i) + for(std::size_t i{0};i < SamplesToDo;++i) mD[sFilterDelay+i] = InSamples[i*2 + 0] - InSamples[i*2 + 1]; /* Precompute j*D and store in xoutput. */ @@ -327,7 +326,7 @@ void UhjDecoder::decode2(const float *RESTRICT InSamples, std::copy_n(mTemp.cbegin()+SamplesToDo, mDTHistory.size(), mDTHistory.begin()); PShift.process({xoutput, SamplesToDo}, mTemp.data()); - for(size_t i{0};i < SamplesToDo;++i) + for(std::size_t i{0};i < SamplesToDo;++i) { /* W = 0.981530*S + j*0.163585*D */ woutput[i] = 0.981530f*mS[i] + 0.163585f*xoutput[i]; @@ -341,7 +340,7 @@ void UhjDecoder::decode2(const float *RESTRICT InSamples, std::copy_n(mTemp.cbegin()+SamplesToDo, mSHistory.size(), mSHistory.begin()); PShift.process({youtput, SamplesToDo}, mTemp.data()); - for(size_t i{0};i < SamplesToDo;++i) + for(std::size_t i{0};i < SamplesToDo;++i) { /* Y = 0.762956*D + j*0.384230*S */ youtput[i] = 0.762956f*mD[i] + 0.384230f*youtput[i]; @@ -368,7 +367,7 @@ int main(int argc, char **argv) return 1; } - size_t num_files{0}, num_decoded{0}; + std::size_t num_files{0}, num_decoded{0}; bool use_general{true}; for(int fidx{1};fidx < argc;++fidx) { @@ -473,7 +472,7 @@ int main(int argc, char **argv) * be fed through the decoder after reaching the end of the input file * to ensure none of the original input is lost. */ - size_t LeadIn{UhjDecoder::sFilterDelay}; + std::size_t LeadIn{UhjDecoder::sFilterDelay}; sf_count_t LeadOut{UhjDecoder::sFilterDelay}; while(LeadOut > 0) { @@ -487,7 +486,7 @@ int main(int argc, char **argv) LeadOut -= remaining; } - auto got = static_cast(sgot); + auto got = static_cast(sgot); if(ininfo.channels > 2 || use_general) decoder->decode(inmem.get(), static_cast(ininfo.channels), decmem, got); else @@ -499,16 +498,16 @@ int main(int argc, char **argv) } got -= LeadIn; - for(size_t i{0};i < got;++i) + for(std::size_t i{0};i < got;++i) { /* Attenuate by -3dB for FuMa output levels. */ constexpr auto inv_sqrt2 = static_cast(1.0/al::numbers::sqrt2); - for(size_t j{0};j < outchans;++j) + for(std::size_t j{0};j < outchans;++j) outmem[i*outchans + j] = f32AsLEBytes(decmem[j][LeadIn+i] * inv_sqrt2); } LeadIn = 0; - size_t wrote{fwrite(outmem.get(), sizeof(byte4)*outchans, got, outfile.get())}; + std::size_t wrote{fwrite(outmem.get(), sizeof(byte4)*outchans, got, outfile.get())}; if(wrote < got) { fprintf(stderr, "Error writing wave data: %s (%d)\n", strerror(errno), errno); -- cgit v1.2.3 From 95b0c59adef778b30dfbe68af70b92d55801fd89 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 4 May 2023 12:26:57 -0700 Subject: Avoid defining separate wrapper functions --- alc/backends/pipewire.cpp | 48 ++++++++++++++++------------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) (limited to 'alc') diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 3f372a4a..9fccf58d 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -815,8 +815,10 @@ struct NodeProxy { { pw_node_events ret{}; ret.version = PW_VERSION_NODE_EVENTS; - ret.info = &NodeProxy::infoCallbackC; - ret.param = &NodeProxy::paramCallbackC; + ret.info = [](void *object, const pw_node_info *info) + { static_cast(object)->infoCallback(info); }; + ret.param = [](void *object, int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) + { static_cast(object)->paramCallback(seq, id, index, next, param); }; return ret; } @@ -842,13 +844,8 @@ struct NodeProxy { void infoCallback(const pw_node_info *info); - static void infoCallbackC(void *object, const pw_node_info *info) - { static_cast(object)->infoCallback(info); } void paramCallback(int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param); - static void paramCallbackC(void *object, int seq, uint32_t id, uint32_t index, uint32_t next, - const spa_pod *param) - { static_cast(object)->paramCallback(seq, id, index, next, param); } }; void NodeProxy::infoCallback(const pw_node_info *info) @@ -939,7 +936,8 @@ struct MetadataProxy { { pw_metadata_events ret{}; ret.version = PW_VERSION_METADATA_EVENTS; - ret.property = &MetadataProxy::propertyCallbackC; + ret.property = [](void *object, uint32_t id, const char *key, const char *type, const char *value) + { return static_cast(object)->propertyCallback(id, key, type, value); }; return ret; } @@ -957,11 +955,7 @@ struct MetadataProxy { ~MetadataProxy() { spa_hook_remove(&mListener); } - int propertyCallback(uint32_t id, const char *key, const char *type, const char *value); - static int propertyCallbackC(void *object, uint32_t id, const char *key, const char *type, - const char *value) - { return static_cast(object)->propertyCallback(id, key, type, value); } }; int MetadataProxy::propertyCallback(uint32_t id, const char *key, const char *type, @@ -1277,17 +1271,8 @@ spa_audio_info_raw make_spa_info(DeviceBase *device, bool is51rear, use_f32p_e u class PipeWirePlayback final : public BackendBase { void stateChangedCallback(pw_stream_state old, pw_stream_state state, const char *error); - static void stateChangedCallbackC(void *data, pw_stream_state old, pw_stream_state state, - const char *error) - { static_cast(data)->stateChangedCallback(old, state, error); } - void ioChangedCallback(uint32_t id, void *area, uint32_t size); - static void ioChangedCallbackC(void *data, uint32_t id, void *area, uint32_t size) - { static_cast(data)->ioChangedCallback(id, area, size); } - void outputCallback(); - static void outputCallbackC(void *data) - { static_cast(data)->outputCallback(); } void open(const char *name) override; bool reset() override; @@ -1310,9 +1295,12 @@ class PipeWirePlayback final : public BackendBase { { pw_stream_events ret{}; ret.version = PW_VERSION_STREAM_EVENTS; - ret.state_changed = &PipeWirePlayback::stateChangedCallbackC; - ret.io_changed = &PipeWirePlayback::ioChangedCallbackC; - ret.process = &PipeWirePlayback::outputCallbackC; + ret.state_changed = [](void *data, pw_stream_state old, pw_stream_state state, const char *error) + { static_cast(data)->stateChangedCallback(old, state, error); }; + ret.io_changed = [](void *data, uint32_t id, void *area, uint32_t size) + { static_cast(data)->ioChangedCallback(id, area, size); }; + ret.process = [](void *data) + { static_cast(data)->outputCallback(); }; return ret; } @@ -1782,13 +1770,7 @@ ClockLatency PipeWirePlayback::getClockLatency() class PipeWireCapture final : public BackendBase { void stateChangedCallback(pw_stream_state old, pw_stream_state state, const char *error); - static void stateChangedCallbackC(void *data, pw_stream_state old, pw_stream_state state, - const char *error) - { static_cast(data)->stateChangedCallback(old, state, error); } - void inputCallback(); - static void inputCallbackC(void *data) - { static_cast(data)->inputCallback(); } void open(const char *name) override; void start() override; @@ -1809,8 +1791,10 @@ class PipeWireCapture final : public BackendBase { { pw_stream_events ret{}; ret.version = PW_VERSION_STREAM_EVENTS; - ret.state_changed = &PipeWireCapture::stateChangedCallbackC; - ret.process = &PipeWireCapture::inputCallbackC; + ret.state_changed = [](void *data, pw_stream_state old, pw_stream_state state, const char *error) + { static_cast(data)->stateChangedCallback(old, state, error); }; + ret.process = [](void *data) + { static_cast(data)->inputCallback(); }; return ret; } -- cgit v1.2.3 From c14ca5f3aa6da354440a60656062f6bc68d6fca6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 4 May 2023 18:42:27 -0700 Subject: Remove custom stuff for standard --- alc/alc.cpp | 2 +- alc/backends/jack.cpp | 2 +- alc/backends/pipewire.cpp | 4 +-- alc/backends/wasapi.cpp | 4 +-- alc/panning.cpp | 10 +++---- common/alcomplex.cpp | 2 +- common/alnumbers.h | 16 +++++------ common/alspan.h | 69 +++++++++++++++-------------------------------- core/ambdec.cpp | 2 +- core/voice.cpp | 2 +- 10 files changed, 44 insertions(+), 69 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index d226b39d..290cc3d1 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -1093,7 +1093,7 @@ void alc_initconfig(void) ALSOFT_GIT_BRANCH); { std::string names; - if(al::size(BackendList) < 1) + if(std::size(BackendList) < 1) names = "(none)"; else { diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp index dbc2b038..7e1e8fc7 100644 --- a/alc/backends/jack.cpp +++ b/alc/backends/jack.cpp @@ -587,7 +587,7 @@ void JackPlayback::start() throw al::backend_exception{al::backend_error::DeviceError, "No playback ports found"}; } - for(size_t i{0};i < al::size(mPort) && mPort[i];++i) + for(size_t i{0};i < std::size(mPort) && mPort[i];++i) { if(!pnames[i]) { diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 9fccf58d..dc52a44d 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -800,7 +800,7 @@ void DeviceNode::parseChannelCount(const spa_pod *value) noexcept constexpr char MonitorPrefix[]{"Monitor of "}; -constexpr auto MonitorPrefixLen = al::size(MonitorPrefix) - 1; +constexpr auto MonitorPrefixLen = std::size(MonitorPrefix) - 1; constexpr char AudioSinkClass[]{"Audio/Sink"}; constexpr char AudioSourceClass[]{"Audio/Source"}; constexpr char AudioSourceVirtualClass[]{"Audio/Source/Virtual"}; @@ -837,7 +837,7 @@ struct NodeProxy { * format, which is what we're interested in). */ uint32_t fmtids[]{SPA_PARAM_EnumFormat}; - ppw_node_subscribe_params(mNode.get(), al::data(fmtids), al::size(fmtids)); + ppw_node_subscribe_params(mNode.get(), std::data(fmtids), std::size(fmtids)); } ~NodeProxy() { spa_hook_remove(&mListener); } diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 16576733..97f0a291 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -125,7 +125,7 @@ constexpr DWORD X71Mask{MaskFromTopBits(X7DOT1)}; constexpr DWORD X714Mask{MaskFromTopBits(X7DOT1DOT4)}; constexpr char DevNameHead[] = "OpenAL Soft on "; -constexpr size_t DevNameHeadLen{al::size(DevNameHead) - 1}; +constexpr size_t DevNameHeadLen{std::size(DevNameHead) - 1}; /* Scales the given reftime value, rounding the result. */ @@ -142,7 +142,7 @@ class GuidPrinter { public: GuidPrinter(const GUID &guid) { - std::snprintf(mMsg, al::size(mMsg), "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + std::snprintf(mMsg, std::size(mMsg), "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", DWORD{guid.Data1}, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); } diff --git a/alc/panning.cpp b/alc/panning.cpp index a3d639fc..60ce7ca4 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -346,10 +346,10 @@ DecoderView MakeDecoderView(ALCdevice *device, const AmbDecConf *conf, } std::copy_n(std::begin(conf->HFOrderGain), - std::min(al::size(conf->HFOrderGain), al::size(decoder.mOrderGain)), + std::min(std::size(conf->HFOrderGain), std::size(decoder.mOrderGain)), std::begin(decoder.mOrderGain)); std::copy_n(std::begin(conf->LFOrderGain), - std::min(al::size(conf->LFOrderGain), al::size(decoder.mOrderGainLF)), + std::min(std::size(conf->LFOrderGain), std::size(decoder.mOrderGainLF)), std::begin(decoder.mOrderGainLF)); const auto num_coeffs = decoder.mIs3D ? AmbiChannelsFromOrder(decoder.mOrder) @@ -818,9 +818,9 @@ void InitHrtfPanning(ALCdevice *device) /*RMS 8.340921354e-01f, 7.182670250e-01f, 5.107426573e-01f, 2.541870634e-01f*/ }; - static_assert(al::size(AmbiPoints1O) == al::size(AmbiMatrix1O), "First-Order Ambisonic HRTF mismatch"); - static_assert(al::size(AmbiPoints2O) == al::size(AmbiMatrix2O), "Second-Order Ambisonic HRTF mismatch"); - static_assert(al::size(AmbiPoints3O) == al::size(AmbiMatrix3O), "Third-Order Ambisonic HRTF mismatch"); + static_assert(std::size(AmbiPoints1O) == std::size(AmbiMatrix1O), "First-Order Ambisonic HRTF mismatch"); + static_assert(std::size(AmbiPoints2O) == std::size(AmbiMatrix2O), "Second-Order Ambisonic HRTF mismatch"); + static_assert(std::size(AmbiPoints3O) == std::size(AmbiMatrix3O), "Third-Order Ambisonic HRTF mismatch"); /* A 700hz crossover frequency provides tighter sound imaging at the sweet * spot with ambisonic decoding, as the distance between the ears is closer diff --git a/common/alcomplex.cpp b/common/alcomplex.cpp index 4420a1bb..a1ca822d 100644 --- a/common/alcomplex.cpp +++ b/common/alcomplex.cpp @@ -58,7 +58,7 @@ struct BitReverser { ++ret_i; } } - assert(ret_i == al::size(mData)); + assert(ret_i == std::size(mData)); } }; diff --git a/common/alnumbers.h b/common/alnumbers.h index 37a55410..800b1f2a 100644 --- a/common/alnumbers.h +++ b/common/alnumbers.h @@ -13,21 +13,21 @@ namespace detail_ { } // detail_ template -static constexpr auto pi_v = detail_::as_fp(3.141592653589793238462643383279502884L); +constexpr auto pi_v = detail_::as_fp(3.141592653589793238462643383279502884L); template -static constexpr auto inv_pi_v = detail_::as_fp(0.318309886183790671537767526745028724L); +constexpr auto inv_pi_v = detail_::as_fp(0.318309886183790671537767526745028724L); template -static constexpr auto sqrt2_v = detail_::as_fp(1.414213562373095048801688724209698079L); +constexpr auto sqrt2_v = detail_::as_fp(1.414213562373095048801688724209698079L); template -static constexpr auto sqrt3_v = detail_::as_fp(1.732050807568877293527446341505872367L); +constexpr auto sqrt3_v = detail_::as_fp(1.732050807568877293527446341505872367L); -static constexpr auto pi = pi_v; -static constexpr auto inv_pi = inv_pi_v; -static constexpr auto sqrt2 = sqrt2_v; -static constexpr auto sqrt3 = sqrt3_v; +constexpr auto pi = pi_v; +constexpr auto inv_pi = inv_pi_v; +constexpr auto sqrt2 = sqrt2_v; +constexpr auto sqrt3 = sqrt3_v; } // namespace numbers diff --git a/common/alspan.h b/common/alspan.h index 1d6cdfe5..42b3e057 100644 --- a/common/alspan.h +++ b/common/alspan.h @@ -12,41 +12,12 @@ namespace al { -template -constexpr auto size(const T &cont) noexcept(noexcept(cont.size())) -> decltype(cont.size()) -{ return cont.size(); } - -template -constexpr size_t size(const T (&)[N]) noexcept -{ return N; } - - -template -constexpr auto data(T &cont) noexcept(noexcept(cont.data())) -> decltype(cont.data()) -{ return cont.data(); } - -template -constexpr auto data(const T &cont) noexcept(noexcept(cont.data())) -> decltype(cont.data()) -{ return cont.data(); } - -template -constexpr T* data(T (&arr)[N]) noexcept -{ return arr; } - -template -constexpr const T* data(std::initializer_list list) noexcept -{ return list.begin(); } - - constexpr size_t dynamic_extent{static_cast(-1)}; template class span; namespace detail_ { - template - using void_t = void; - template struct is_span_ : std::false_type { }; template @@ -65,7 +36,7 @@ namespace detail_ { constexpr bool has_size_and_data = false; template constexpr bool has_size_and_data())), decltype(al::data(std::declval()))>> + std::void_t())),decltype(std::data(std::declval()))>> = true; template @@ -74,7 +45,7 @@ namespace detail_ { template constexpr bool is_valid_container = !is_span_v && !is_std_array_v && !std::is_array::value && has_size_and_data - && is_array_compatible()))>,T>; + && is_array_compatible()))>,T>; } // namespace detail_ #define REQUIRES(...) std::enable_if_t<(__VA_ARGS__),bool> = true @@ -107,25 +78,27 @@ public: constexpr explicit span(U first, V) : mData{to_address(first)} { } constexpr span(type_identity_t (&arr)[E]) noexcept - : span{al::data(arr), al::size(arr)} + : span{std::data(arr), std::size(arr)} + { } + constexpr span(std::array &arr) noexcept + : span{std::data(arr), std::size(arr)} { } - constexpr span(std::array &arr) noexcept : span{al::data(arr), al::size(arr)} { } template::value)> constexpr span(const std::array &arr) noexcept - : span{al::data(arr), al::size(arr)} + : span{std::data(arr), std::size(arr)} { } template)> - constexpr explicit span(U&& cont) : span{al::data(cont), al::size(cont)} { } + constexpr explicit span(U&& cont) : span{std::data(cont), std::size(cont)} { } template::value && detail_::is_array_compatible && N == dynamic_extent)> constexpr explicit span(const span &span_) noexcept - : span{al::data(span_), al::size(span_)} + : span{std::data(span_), std::size(span_)} { } template::value && detail_::is_array_compatible && N == extent)> - constexpr span(const span &span_) noexcept : span{al::data(span_), al::size(span_)} { } + constexpr span(const span &span_) noexcept : span{std::data(span_), std::size(span_)} { } constexpr span(const span&) noexcept = default; constexpr span& operator=(const span &rhs) noexcept = default; @@ -224,21 +197,23 @@ public: template constexpr span(type_identity_t (&arr)[N]) noexcept - : span{al::data(arr), al::size(arr)} + : span{std::data(arr), std::size(arr)} { } template - constexpr span(std::array &arr) noexcept : span{al::data(arr), al::size(arr)} { } + constexpr span(std::array &arr) noexcept + : span{std::data(arr), std::size(arr)} + { } template::value)> constexpr span(const std::array &arr) noexcept - : span{al::data(arr), al::size(arr)} + : span{std::data(arr), std::size(arr)} { } template)> - constexpr span(U&& cont) : span{al::data(cont), al::size(cont)} { } + constexpr span(U&& cont) : span{std::data(cont), std::size(cont)} { } template::value || extent != N) && detail_::is_array_compatible)> - constexpr span(const span &span_) noexcept : span{al::data(span_), al::size(span_)} { } + constexpr span(const span &span_) noexcept : span{std::data(span_), std::size(span_)} { } constexpr span(const span&) noexcept = default; constexpr span& operator=(const span &rhs) noexcept = default; @@ -330,19 +305,19 @@ constexpr auto as_span(T ptr, U count_or_end) return span{ptr, count_or_end}; } template -constexpr auto as_span(T (&arr)[N]) noexcept { return span{al::data(arr), al::size(arr)}; } +constexpr auto as_span(T (&arr)[N]) noexcept { return span{std::data(arr), std::size(arr)}; } template constexpr auto as_span(std::array &arr) noexcept -{ return span{al::data(arr), al::size(arr)}; } +{ return span{std::data(arr), std::size(arr)}; } template constexpr auto as_span(const std::array &arr) noexcept -{ return span,N>{al::data(arr), al::size(arr)}; } +{ return span,N>{std::data(arr), std::size(arr)}; } template && !detail_::is_std_array_v && !std::is_array::value && detail_::has_size_and_data)> constexpr auto as_span(U&& cont) { - using value_type = std::remove_pointer_t()))>; - return span{al::data(cont), al::size(cont)}; + using value_type = std::remove_pointer_t()))>; + return span{std::data(cont), std::size(cont)}; } template constexpr auto as_span(span span_) noexcept { return span_; } diff --git a/core/ambdec.cpp b/core/ambdec.cpp index a056e63f..f98e1098 100644 --- a/core/ambdec.cpp +++ b/core/ambdec.cpp @@ -139,7 +139,7 @@ std::optional AmbDecConf::load(const char *fname) noexcept { --toread; istr >> value; - if(curgain < al::size(gains)) + if(curgain < std::size(gains)) gains[curgain++] = value; } } diff --git a/core/voice.cpp b/core/voice.cpp index cbf84c2a..db6b6d27 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -288,7 +288,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const std::byte *sr /* NOTE: This could probably be optimized better. */ size_t wrote{0}; do { - static constexpr int MaxStepIndex{static_cast(al::size(IMAStep_size)) - 1}; + static constexpr int MaxStepIndex{static_cast(std::size(IMAStep_size)) - 1}; /* Each IMA4 block starts with a signed 16-bit sample, and a signed * 16-bit table index. The table index needs to be clamped. */ -- cgit v1.2.3 From 3ec03cadd2b5059e54e5e9b8f4d506b4c6ce727d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 5 May 2023 06:46:00 -0700 Subject: Use deduction guides instead of helper functions for spans --- al/debug.cpp | 8 ++++---- al/eax/call.h | 2 +- alc/effects/convolution.cpp | 6 +++--- alc/effects/pshifter.cpp | 4 ++-- common/alspan.h | 46 ++++++++++++++++++++------------------------- common/phase_shifter.h | 4 ++-- core/cubic_tables.cpp | 2 +- core/hrtf.cpp | 2 +- core/logging.cpp | 8 ++++---- core/voice.cpp | 4 ++-- utils/makemhr/loaddef.cpp | 2 +- utils/makemhr/loadsofa.cpp | 2 +- utils/makemhr/makemhr.h | 4 ++-- 13 files changed, 44 insertions(+), 50 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index 3df85d62..a4b66ffb 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -311,7 +311,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type static constexpr size_t ElemCount{DebugSourceCount + DebugTypeCount + DebugSeverityCount}; static constexpr auto Values = make_array(); - al::span srcIndices{al::as_span(Values).subspan()}; + al::span srcIndices{al::span{Values}.subspan()}; if(source != AL_DONT_CARE_EXT) { auto dsource = GetDebugSource(source); @@ -320,7 +320,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type srcIndices = srcIndices.subspan(al::to_underlying(*dsource), 1); } - al::span typeIndices{al::as_span(Values).subspan()}; + al::span typeIndices{al::span{Values}.subspan()}; if(type != AL_DONT_CARE_EXT) { auto dtype = GetDebugType(type); @@ -329,7 +329,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type typeIndices = typeIndices.subspan(al::to_underlying(*dtype), 1); } - al::span svrIndices{al::as_span(Values).subspan()}; + al::span svrIndices{al::span{Values}.subspan()}; if(severity != AL_DONT_CARE_EXT) { auto dseverity = GetDebugSeverity(severity); @@ -344,7 +344,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type { const uint filterbase{(1u<(count))) + for(const uint id : al::span{ids, static_cast(count)}) { const uint64_t filter{filterbase | (uint64_t{id} << 32)}; diff --git a/al/eax/call.h b/al/eax/call.h index 5ec33b0f..f2ad529e 100644 --- a/al/eax/call.h +++ b/al/eax/call.h @@ -55,7 +55,7 @@ public: fail_too_small(); const auto count = minz(mPropertyBufferSize / sizeof(TValue), max_count); - return al::as_span(static_cast(mPropertyBuffer), count); + return {static_cast(mPropertyBuffer), count}; } template diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index 4ca31246..04b88f66 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -360,7 +360,7 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag done += todo; std::fill(iter, fftbuffer.end(), std::complex{}); - forward_fft(al::as_span(fftbuffer)); + forward_fft(al::span{fftbuffer}); filteriter = std::copy_n(fftbuffer.cbegin(), m, filteriter); } } @@ -562,7 +562,7 @@ void ConvolutionState::process(const size_t samplesToDo, */ auto fftiter = std::copy_n(mInput.cbegin(), ConvolveUpdateSamples, mFftBuffer.begin()); std::fill(fftiter, mFftBuffer.end(), complex_f{}); - forward_fft(al::as_span(mFftBuffer)); + forward_fft(al::span{mFftBuffer}); std::copy_n(mFftBuffer.cbegin(), m, &mComplexData[curseg*m]); @@ -598,7 +598,7 @@ void ConvolutionState::process(const size_t samplesToDo, * second-half samples (and this output's second half is * subsequently saved for next time). */ - inverse_fft(al::as_span(mFftBuffer)); + inverse_fft(al::span{mFftBuffer}); /* The iFFT'd response is scaled up by the number of bins, so apply * the inverse to normalize the output. diff --git a/alc/effects/pshifter.cpp b/alc/effects/pshifter.cpp index 426a2264..3cec1df9 100644 --- a/alc/effects/pshifter.cpp +++ b/alc/effects/pshifter.cpp @@ -186,7 +186,7 @@ void PshifterState::process(const size_t samplesToDo, mFftBuffer[k] = mFIFO[src] * gWindow.mData[k]; for(size_t src{0u}, k{StftSize-mPos};src < mPos;++src,++k) mFftBuffer[k] = mFIFO[src] * gWindow.mData[k]; - forward_fft(al::as_span(mFftBuffer)); + forward_fft(al::span{mFftBuffer}); /* Analyze the obtained data. Since the real FFT is symmetric, only * StftHalfSize+1 samples are needed. @@ -274,7 +274,7 @@ void PshifterState::process(const size_t samplesToDo, /* Apply an inverse FFT to get the time-domain signal, and accumulate * for the output with windowing. */ - inverse_fft(al::as_span(mFftBuffer)); + inverse_fft(al::span{mFftBuffer}); static constexpr float scale{3.0f / OversampleFactor / StftSize}; for(size_t dst{mPos}, k{0u};dst < StftSize;++dst,++k) diff --git a/common/alspan.h b/common/alspan.h index 42b3e057..f75bc84f 100644 --- a/common/alspan.h +++ b/common/alspan.h @@ -39,12 +39,15 @@ namespace detail_ { std::void_t())),decltype(std::data(std::declval()))>> = true; + template + constexpr bool is_valid_container_type = !is_span_v && !is_std_array_v + && !std::is_array::value && has_size_and_data; + template constexpr bool is_array_compatible = std::is_convertible::value; template - constexpr bool is_valid_container = !is_span_v && !is_std_array_v - && !std::is_array::value && has_size_and_data + constexpr bool is_valid_container = is_valid_container_type && is_array_compatible()))>,T>; } // namespace detail_ @@ -297,30 +300,21 @@ constexpr inline auto span::subspan(size_t offset, size_t count) const span{mData+offset, mData+offset+count}; } -/* Helpers to deal with the lack of user-defined deduction guides (C++17). */ -template -constexpr auto as_span(T ptr, U count_or_end) -{ - using value_type = typename std::pointer_traits::element_type; - return span{ptr, count_or_end}; -} -template -constexpr auto as_span(T (&arr)[N]) noexcept { return span{std::data(arr), std::size(arr)}; } -template -constexpr auto as_span(std::array &arr) noexcept -{ return span{std::data(arr), std::size(arr)}; } -template -constexpr auto as_span(const std::array &arr) noexcept -{ return span,N>{std::data(arr), std::size(arr)}; } -template && !detail_::is_std_array_v - && !std::is_array::value && detail_::has_size_and_data)> -constexpr auto as_span(U&& cont) -{ - using value_type = std::remove_pointer_t()))>; - return span{std::data(cont), std::size(cont)}; -} -template -constexpr auto as_span(span span_) noexcept { return span_; } + +template +span(T, EndOrSize) -> span())>>; + +template +span(T (&)[N]) -> span; + +template +span(std::array&) -> span; + +template +span(const std::array&) -> span; + +template)> +span(C&&) -> span()))>>; #undef REQUIRES diff --git a/common/phase_shifter.h b/common/phase_shifter.h index 0d4166bc..061e9176 100644 --- a/common/phase_shifter.h +++ b/common/phase_shifter.h @@ -53,12 +53,12 @@ struct PhaseShifterT { std::fill_n(fftBuffer.get(), fft_size, complex_d{}); fftBuffer[half_size] = 1.0; - forward_fft(al::as_span(fftBuffer.get(), fft_size)); + forward_fft(al::span{fftBuffer.get(), fft_size}); for(size_t i{0};i < half_size+1;++i) fftBuffer[i] = complex_d{-fftBuffer[i].imag(), fftBuffer[i].real()}; for(size_t i{half_size+1};i < fft_size;++i) fftBuffer[i] = std::conj(fftBuffer[fft_size - i]); - inverse_fft(al::as_span(fftBuffer.get(), fft_size)); + inverse_fft(al::span{fftBuffer.get(), fft_size}); auto fftiter = fftBuffer.get() + half_size + (FilterSize/2 - 1); for(float &coeff : mCoeffs) diff --git a/core/cubic_tables.cpp b/core/cubic_tables.cpp index 73ec6b3f..66958735 100644 --- a/core/cubic_tables.cpp +++ b/core/cubic_tables.cpp @@ -49,7 +49,7 @@ struct SplineFilterArray { mTable[pi].mDeltas[3] = -mTable[pi].mCoeffs[3]; } - constexpr auto getTable() const noexcept { return al::as_span(mTable); } + constexpr auto& getTable() const noexcept { return mTable; } }; constexpr SplineFilterArray SplineFilter{}; diff --git a/core/hrtf.cpp b/core/hrtf.cpp index 1d9bc368..607e3d3d 100644 --- a/core/hrtf.cpp +++ b/core/hrtf.cpp @@ -425,7 +425,7 @@ std::unique_ptr CreateHrtfStore(uint rate, uint8_t irSize, std::uninitialized_copy_n(delays, irCount, delays_); /* Finally, assign the storage pointers. */ - Hrtf->mFields = al::as_span(field_, fields.size()); + Hrtf->mFields = {field_, fields.size()}; Hrtf->mElev = elev_; Hrtf->mCoeffs = coeffs_; Hrtf->mDelays = delays_; diff --git a/core/logging.cpp b/core/logging.cpp index 34a95e5a..8e0116ea 100644 --- a/core/logging.cpp +++ b/core/logging.cpp @@ -25,13 +25,13 @@ void al_print(LogLevel level, FILE *logfile, const char *fmt, ...) * that includes the null terminator, which we want to exclude from the * span. */ - auto prefix = al::as_span("[ALSOFT] (--) ").first<14>(); + auto prefix = al::span{"[ALSOFT] (--) "}.first<14>(); switch(level) { case LogLevel::Disable: break; - case LogLevel::Error: prefix = al::as_span("[ALSOFT] (EE) ").first<14>(); break; - case LogLevel::Warning: prefix = al::as_span("[ALSOFT] (WW) ").first<14>(); break; - case LogLevel::Trace: prefix = al::as_span("[ALSOFT] (II) ").first<14>(); break; + case LogLevel::Error: prefix = al::span{"[ALSOFT] (EE) "}.first<14>(); break; + case LogLevel::Warning: prefix = al::span{"[ALSOFT] (WW) "}.first<14>(); break; + case LogLevel::Trace: prefix = al::span{"[ALSOFT] (II) "}.first<14>(); break; } al::vector dynmsg; diff --git a/core/voice.cpp b/core/voice.cpp index db6b6d27..478ea81f 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -389,7 +389,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const std::byte sampleHistory[1] = int(input[2*srcChan + 0]) | (int(input[2*srcChan + 1])<<8); input += srcStep*2; - const auto coeffs = al::as_span(MSADPCMAdaptionCoeff[blockpred]); + const al::span coeffs{MSADPCMAdaptionCoeff[blockpred]}; delta = (delta^0x8000) - 32768; sampleHistory[0] = (sampleHistory[0]^0x8000) - 32768; sampleHistory[1] = (sampleHistory[1]^0x8000) - 32768; @@ -798,7 +798,7 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi using ResBufType = decltype(DeviceBase::mResampleData); static constexpr uint srcSizeMax{static_cast(ResBufType{}.size()-MaxResamplerEdge)}; - const auto prevSamples = al::as_span(mPrevSamples[chan]); + const al::span prevSamples{mPrevSamples[chan]}; const auto resampleBuffer = std::copy(prevSamples.cbegin(), prevSamples.cend(), Device->mResampleData.begin()) - MaxResamplerEdge; int intPos{DataPosInt}; diff --git a/utils/makemhr/loaddef.cpp b/utils/makemhr/loaddef.cpp index 84fbb48b..c8a98511 100644 --- a/utils/makemhr/loaddef.cpp +++ b/utils/makemhr/loaddef.cpp @@ -1450,7 +1450,7 @@ static int ProcessMetrics(TokenReaderT *tr, const uint fftSize, const uint trunc } if(hData->mChannelType == CT_NONE) hData->mChannelType = CT_MONO; - const auto azs = al::as_span(azCounts).first(); + const auto azs = al::span{azCounts}.first(); if(!PrepareHrirData({distances, fdCount}, evCounts, azs, hData)) { fprintf(stderr, "Error: Out of memory.\n"); diff --git a/utils/makemhr/loadsofa.cpp b/utils/makemhr/loadsofa.cpp index 9e661839..9bcfc38d 100644 --- a/utils/makemhr/loadsofa.cpp +++ b/utils/makemhr/loadsofa.cpp @@ -87,7 +87,7 @@ static bool PrepareLayout(const uint m, const float *xyzs, HrirDataT *hData) ++fi; } fprintf(stdout, "Using %u of %u IRs.\n", ir_total, m); - const auto azs = al::as_span(azCounts).first(); + const auto azs = al::span{azCounts}.first(); return PrepareHrirData({distances, fi}, evCounts, azs, hData); } diff --git a/utils/makemhr/makemhr.h b/utils/makemhr/makemhr.h index 13b5b2d1..aa18134d 100644 --- a/utils/makemhr/makemhr.h +++ b/utils/makemhr/makemhr.h @@ -113,12 +113,12 @@ void MagnitudeResponse(const uint n, const complex_d *in, double *out); // Performs a forward FFT. inline void FftForward(const uint n, complex_d *inout) -{ forward_fft(al::as_span(inout, n)); } +{ forward_fft(al::span{inout, n}); } // Performs an inverse FFT. inline void FftInverse(const uint n, complex_d *inout) { - inverse_fft(al::as_span(inout, n)); + inverse_fft(al::span{inout, n}); double f{1.0 / n}; for(uint i{0};i < n;i++) inout[i] *= f; -- cgit v1.2.3 From 09b153b85c9f6c75a6361ab2ecb0ed81e8920ff3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 5 May 2023 07:48:43 -0700 Subject: Don't bit_cast an array to a pointer --- alc/alconfig.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'alc') diff --git a/alc/alconfig.cpp b/alc/alconfig.cpp index ceb7d97b..56cad9e0 100644 --- a/alc/alconfig.cpp +++ b/alc/alconfig.cpp @@ -38,7 +38,6 @@ #include #include -#include "albit.h" #include "alfstream.h" #include "alstring.h" #include "core/helpers.h" @@ -419,7 +418,7 @@ void ReadALConfig() if((configURL=CFBundleCopyResourceURL(mainBundle, CFSTR(".alsoftrc"), CFSTR(""), nullptr)) && CFURLGetFileSystemRepresentation(configURL, true, fileName, sizeof(fileName))) { - f = al::ifstream{al::bit_cast(fileName)}; + f = al::ifstream{reinterpret_cast(fileName)}; if(f.is_open()) LoadConfigFromFile(f); } -- cgit v1.2.3 From bfe766cd574985465fe1a9f4cffa388ca9ca1f9b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 5 May 2023 13:37:50 -0700 Subject: Use some more standard functions --- al/auxeffectslot.cpp | 10 +++---- al/buffer.cpp | 4 +-- al/effect.cpp | 4 +-- al/effects/reverb.cpp | 24 ++++++++-------- al/event.cpp | 2 +- al/filter.cpp | 4 +-- al/source.cpp | 8 +++--- alc/backends/pipewire.cpp | 12 ++++---- common/almalloc.h | 71 ++--------------------------------------------- common/alnumeric.h | 6 ---- core/context.cpp | 6 ++-- core/mastering.cpp | 4 +-- utils/uhjencoder.cpp | 6 ++-- 13 files changed, 44 insertions(+), 117 deletions(-) (limited to 'alc') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 571eb717..c69990fe 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -165,7 +165,7 @@ void AddActiveEffectSlots(const al::span auxslots, ALCcontext *co curarray = context->mActiveAuxSlots.exchange(newarray, std::memory_order_acq_rel); context->mDevice->waitForMix(); - al::destroy_n(curarray->end(), curarray->size()); + std::destroy_n(curarray->end(), curarray->size()); delete curarray; } @@ -204,7 +204,7 @@ void RemoveActiveEffectSlots(const al::span auxslots, ALCcontext curarray = context->mActiveAuxSlots.exchange(newarray, std::memory_order_acq_rel); context->mDevice->waitForMix(); - al::destroy_n(curarray->end(), curarray->size()); + std::destroy_n(curarray->end(), curarray->size()); delete curarray; } @@ -289,7 +289,7 @@ void FreeEffectSlot(ALCcontext *context, ALeffectslot *slot) const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; - al::destroy_at(slot); + std::destroy_at(slot); context->mEffectSlotList[lidx].FreeMask |= 1_u64 << slidx; context->mNumEffectSlots--; @@ -1030,7 +1030,7 @@ EffectSlotSubList::~EffectSlotSubList() while(usemask) { const int idx{al::countr_zero(usemask)}; - al::destroy_at(EffectSlots+idx); + std::destroy_at(EffectSlots+idx); usemask &= ~(1_u64 << idx); } FreeMask = ~usemask; @@ -1275,7 +1275,7 @@ void ALeffectslot::eax_fx_slot_load_effect(int version, ALenum altype) void ALeffectslot::eax_fx_slot_set_volume() { - const auto volume = clamp(eax_.lVolume, EAXFXSLOT_MINVOLUME, EAXFXSLOT_MAXVOLUME); + const auto volume = std::clamp(eax_.lVolume, EAXFXSLOT_MINVOLUME, EAXFXSLOT_MAXVOLUME); const auto gain = level_mb_to_gain(static_cast(volume)); eax_set_efx_slot_gain(gain); } diff --git a/al/buffer.cpp b/al/buffer.cpp index 1a042f46..371e586c 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -222,7 +222,7 @@ void FreeBuffer(ALCdevice *device, ALbuffer *buffer) const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; - al::destroy_at(buffer); + std::destroy_at(buffer); device->BufferList[lidx].FreeMask |= 1_u64 << slidx; } @@ -1533,7 +1533,7 @@ BufferSubList::~BufferSubList() while(usemask) { const int idx{al::countr_zero(usemask)}; - al::destroy_at(Buffers+idx); + std::destroy_at(Buffers+idx); usemask &= ~(1_u64 << idx); } FreeMask = ~usemask; diff --git a/al/effect.cpp b/al/effect.cpp index 28f5e967..3d91139a 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -210,7 +210,7 @@ void FreeEffect(ALCdevice *device, ALeffect *effect) const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; - al::destroy_at(effect); + std::destroy_at(effect); device->EffectList[lidx].FreeMask |= 1_u64 << slidx; } @@ -555,7 +555,7 @@ EffectSubList::~EffectSubList() while(usemask) { const int idx{al::countr_zero(usemask)}; - al::destroy_at(Effects+idx); + std::destroy_at(Effects+idx); usemask &= ~(1_u64 << idx); } FreeMask = ~usemask; diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index 440d7b4e..d93602cd 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -945,7 +945,7 @@ struct EnvironmentSizeDeferrer2 { if ((props.dwFlags & EAX2LISTENERFLAGS_DECAYTIMESCALE) != 0) { - props.flDecayTime = clamp( + props.flDecayTime = std::clamp( props.flDecayTime * scale, EAXREVERB_MINDECAYTIME, EAXREVERB_MAXDECAYTIME); @@ -954,7 +954,7 @@ struct EnvironmentSizeDeferrer2 { if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSSCALE) != 0 && (props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0) { - props.lReflections = clamp( + props.lReflections = std::clamp( props.lReflections - static_cast(gain_to_level_mb(scale)), EAXREVERB_MINREFLECTIONS, EAXREVERB_MAXREFLECTIONS); @@ -962,7 +962,7 @@ struct EnvironmentSizeDeferrer2 { if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0) { - props.flReflectionsDelay = clamp( + props.flReflectionsDelay = std::clamp( props.flReflectionsDelay * scale, EAXREVERB_MINREFLECTIONSDELAY, EAXREVERB_MAXREFLECTIONSDELAY); @@ -972,7 +972,7 @@ struct EnvironmentSizeDeferrer2 { { const auto log_scalar = ((props.dwFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F; - props.lReverb = clamp( + props.lReverb = std::clamp( props.lReverb - static_cast(std::log10(scale) * log_scalar), EAXREVERB_MINREVERB, EAXREVERB_MAXREVERB); @@ -980,7 +980,7 @@ struct EnvironmentSizeDeferrer2 { if ((props.dwFlags & EAX2LISTENERFLAGS_REVERBDELAYSCALE) != 0) { - props.flReverbDelay = clamp( + props.flReverbDelay = std::clamp( props.flReverbDelay * scale, EAXREVERB_MINREVERBDELAY, EAXREVERB_MAXREVERBDELAY); @@ -1015,7 +1015,7 @@ struct EnvironmentSizeDeferrer3 { if ((props.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) { - props.flDecayTime = clamp( + props.flDecayTime = std::clamp( props.flDecayTime * scale, EAXREVERB_MINDECAYTIME, EAXREVERB_MAXDECAYTIME); @@ -1024,7 +1024,7 @@ struct EnvironmentSizeDeferrer3 { if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSSCALE) != 0 && (props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0) { - props.lReflections = clamp( + props.lReflections = std::clamp( props.lReflections - static_cast(gain_to_level_mb(scale)), EAXREVERB_MINREFLECTIONS, EAXREVERB_MAXREFLECTIONS); @@ -1032,7 +1032,7 @@ struct EnvironmentSizeDeferrer3 { if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0) { - props.flReflectionsDelay = clamp( + props.flReflectionsDelay = std::clamp( props.flReflectionsDelay * scale, EAXREVERB_MINREFLECTIONSDELAY, EAXREVERB_MAXREFLECTIONSDELAY); @@ -1041,7 +1041,7 @@ struct EnvironmentSizeDeferrer3 { if ((props.ulFlags & EAXREVERBFLAGS_REVERBSCALE) != 0) { const auto log_scalar = ((props.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F; - props.lReverb = clamp( + props.lReverb = std::clamp( props.lReverb - static_cast(std::log10(scale) * log_scalar), EAXREVERB_MINREVERB, EAXREVERB_MAXREVERB); @@ -1049,7 +1049,7 @@ struct EnvironmentSizeDeferrer3 { if ((props.ulFlags & EAXREVERBFLAGS_REVERBDELAYSCALE) != 0) { - props.flReverbDelay = clamp( + props.flReverbDelay = std::clamp( props.flReverbDelay * scale, EAXREVERB_MINREVERBDELAY, EAXREVERB_MAXREVERBDELAY); @@ -1057,7 +1057,7 @@ struct EnvironmentSizeDeferrer3 { if ((props.ulFlags & EAXREVERBFLAGS_ECHOTIMESCALE) != 0) { - props.flEchoTime = clamp( + props.flEchoTime = std::clamp( props.flEchoTime * scale, EAXREVERB_MINECHOTIME, EAXREVERB_MAXECHOTIME); @@ -1065,7 +1065,7 @@ struct EnvironmentSizeDeferrer3 { if ((props.ulFlags & EAXREVERBFLAGS_MODULATIONTIMESCALE) != 0) { - props.flModulationTime = clamp( + props.flModulationTime = std::clamp( props.flModulationTime * scale, EAXREVERB_MINMODULATIONTIME, EAXREVERB_MAXMODULATIONTIME); diff --git a/al/event.cpp b/al/event.cpp index acb4958a..33e28412 100644 --- a/al/event.cpp +++ b/al/event.cpp @@ -50,7 +50,7 @@ static int EventThread(ALCcontext *context) evt_data.len -= 1; AsyncEvent evt{*evt_ptr}; - al::destroy_at(evt_ptr); + std::destroy_at(evt_ptr); ring->readAdvance(1); quitnow = evt.EnumType == AsyncEvent::KillThread; diff --git a/al/filter.cpp b/al/filter.cpp index c5d1b2a1..0fd8eaa8 100644 --- a/al/filter.cpp +++ b/al/filter.cpp @@ -380,7 +380,7 @@ void FreeFilter(ALCdevice *device, ALfilter *filter) const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; - al::destroy_at(filter); + std::destroy_at(filter); device->FilterList[lidx].FreeMask |= 1_u64 << slidx; } @@ -716,7 +716,7 @@ FilterSubList::~FilterSubList() while(usemask) { const int idx{al::countr_zero(usemask)}; - al::destroy_at(Filters+idx); + std::destroy_at(Filters+idx); usemask &= ~(1_u64 << idx); } FreeMask = ~usemask; diff --git a/al/source.cpp b/al/source.cpp index 2b0540b4..b8feb0c3 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -738,7 +738,7 @@ void FreeSource(ALCcontext *context, ALsource *source) SendVoiceChanges(context, vchg); } - al::destroy_at(source); + std::destroy_at(source); context->mSourceList[lidx].FreeMask |= 1_u64 << slidx; context->mNumSources--; @@ -4041,7 +4041,7 @@ SourceSubList::~SourceSubList() { const int idx{al::countr_zero(usemask)}; usemask &= ~(1_u64 << idx); - al::destroy_at(Sources+idx); + std::destroy_at(Sources+idx); } FreeMask = ~usemask; al_free(Sources); @@ -4257,7 +4257,7 @@ void ALsource::eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept else { dst.source.ulFlags &= ~EAXSOURCEFLAGS_ROOMAUTO; - dst.sends[0].lSend = clamp(static_cast(gain_to_level_mb(src.fMix)), + dst.sends[0].lSend = std::clamp(static_cast(gain_to_level_mb(src.fMix)), EAXSOURCE_MINSEND, EAXSOURCE_MAXSEND); } } @@ -4492,7 +4492,7 @@ void ALsource::eax_update_room_filters() void ALsource::eax_set_efx_outer_gain_hf() { - OuterGainHF = clamp( + OuterGainHF = std::clamp( level_mb_to_gain(static_cast(mEax.source.lOutsideVolumeHF)), AL_MIN_CONE_OUTER_GAINHF, AL_MAX_CONE_OUTER_GAINHF); diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index dc52a44d..bb7fc2f2 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -1085,9 +1085,9 @@ EventManager::~EventManager() if(mLoop) mLoop.stop(); for(NodeProxy *node : mNodeList) - al::destroy_at(node); + std::destroy_at(node); if(mDefaultMetadata) - al::destroy_at(mDefaultMetadata); + std::destroy_at(mDefaultMetadata); } void EventManager::kill() @@ -1095,10 +1095,10 @@ void EventManager::kill() if(mLoop) mLoop.stop(); for(NodeProxy *node : mNodeList) - al::destroy_at(node); + std::destroy_at(node); mNodeList.clear(); if(mDefaultMetadata) - al::destroy_at(mDefaultMetadata); + std::destroy_at(mDefaultMetadata); mDefaultMetadata = nullptr; mRegistry = nullptr; @@ -1191,7 +1191,7 @@ void EventManager::removeCallback(uint32_t id) { if(node->mId != id) return false; - al::destroy_at(node); + std::destroy_at(node); return true; }; auto node_end = std::remove_if(mNodeList.begin(), mNodeList.end(), clear_node); @@ -1199,7 +1199,7 @@ void EventManager::removeCallback(uint32_t id) if(mDefaultMetadata && mDefaultMetadata->mId == id) { - al::destroy_at(mDefaultMetadata); + std::destroy_at(mDefaultMetadata); mDefaultMetadata = nullptr; } } diff --git a/common/almalloc.h b/common/almalloc.h index a795fc3b..bd2e085b 100644 --- a/common/almalloc.h +++ b/common/almalloc.h @@ -125,71 +125,6 @@ constexpr T* construct_at(T *ptr, Args&& ...args) noexcept(std::is_nothrow_constructible::value) { return ::new(static_cast(ptr)) T{std::forward(args)...}; } -/* At least VS 2015 complains that 'ptr' is unused when the given type's - * destructor is trivial (a no-op). So disable that warning for this call. - */ -DIAGNOSTIC_PUSH -msc_pragma(warning(disable : 4100)) -template -constexpr std::enable_if_t::value> -destroy_at(T *ptr) noexcept(std::is_nothrow_destructible::value) -{ ptr->~T(); } -DIAGNOSTIC_POP -template -constexpr std::enable_if_t::value> -destroy_at(T *ptr) noexcept(std::is_nothrow_destructible>::value) -{ - for(auto &elem : *ptr) - al::destroy_at(std::addressof(elem)); -} - -template -constexpr void destroy(T first, T end) noexcept(noexcept(al::destroy_at(std::addressof(*first)))) -{ - while(first != end) - { - al::destroy_at(std::addressof(*first)); - ++first; - } -} - -template -constexpr std::enable_if_t::value,T> -destroy_n(T first, N count) noexcept(noexcept(al::destroy_at(std::addressof(*first)))) -{ - if(count != 0) - { - do { - al::destroy_at(std::addressof(*first)); - ++first; - } while(--count); - } - return first; -} - - -template -inline std::enable_if_t::value, -T> uninitialized_default_construct_n(T first, N count) -{ - using ValueT = typename std::iterator_traits::value_type; - T current{first}; - if(count != 0) - { - try { - do { - ::new(static_cast(std::addressof(*current))) ValueT; - ++current; - } while(--count); - } - catch(...) { - al::destroy(first, current); - throw; - } - } - return current; -} - /* Storage for flexible array data. This is trivially destructible if type T is * trivially destructible. @@ -209,7 +144,7 @@ struct FlexArrayStorage { } FlexArrayStorage(size_t size) : mSize{size} - { al::uninitialized_default_construct_n(mArray, mSize); } + { std::uninitialized_default_construct_n(mArray, mSize); } ~FlexArrayStorage() = default; FlexArrayStorage(const FlexArrayStorage&) = delete; @@ -231,8 +166,8 @@ struct FlexArrayStorage { } FlexArrayStorage(size_t size) : mSize{size} - { al::uninitialized_default_construct_n(mArray, mSize); } - ~FlexArrayStorage() { al::destroy_n(mArray, mSize); } + { std::uninitialized_default_construct_n(mArray, mSize); } + ~FlexArrayStorage() { std::destroy_n(mArray, mSize); } FlexArrayStorage(const FlexArrayStorage&) = delete; FlexArrayStorage& operator=(const FlexArrayStorage&) = delete; diff --git a/common/alnumeric.h b/common/alnumeric.h index d6919e40..8220d3e5 100644 --- a/common/alnumeric.h +++ b/common/alnumeric.h @@ -283,12 +283,6 @@ inline float fast_roundf(float f) noexcept } -template -constexpr const T& clamp(const T& value, const T& min_value, const T& max_value) noexcept -{ - return std::min(std::max(value, min_value), max_value); -} - // Converts level (mB) to gain. inline float level_mb_to_gain(float x) { diff --git a/core/context.cpp b/core/context.cpp index d68d8327..d94daf16 100644 --- a/core/context.cpp +++ b/core/context.cpp @@ -51,7 +51,7 @@ ContextBase::~ContextBase() if(EffectSlotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)}) { - al::destroy_n(curarray->end(), curarray->size()); + std::destroy_n(curarray->end(), curarray->size()); delete curarray; } @@ -63,12 +63,12 @@ ContextBase::~ContextBase() auto evt_vec = mAsyncEvents->getReadVector(); if(evt_vec.first.len > 0) { - al::destroy_n(reinterpret_cast(evt_vec.first.buf), evt_vec.first.len); + std::destroy_n(reinterpret_cast(evt_vec.first.buf), evt_vec.first.len); count += evt_vec.first.len; } if(evt_vec.second.len > 0) { - al::destroy_n(reinterpret_cast(evt_vec.second.buf), evt_vec.second.len); + std::destroy_n(reinterpret_cast(evt_vec.second.buf), evt_vec.second.len); count += evt_vec.second.len; } if(count > 0) diff --git a/core/mastering.cpp b/core/mastering.cpp index 97a4008e..4445719b 100644 --- a/core/mastering.cpp +++ b/core/mastering.cpp @@ -382,10 +382,10 @@ std::unique_ptr Compressor::Create(const size_t NumChans, const floa Compressor::~Compressor() { if(mHold) - al::destroy_at(mHold); + std::destroy_at(mHold); mHold = nullptr; if(mDelay) - al::destroy_n(mDelay, mNumChans); + std::destroy_n(mDelay, mNumChans); mDelay = nullptr; } diff --git a/utils/uhjencoder.cpp b/utils/uhjencoder.cpp index 34698993..c381d1b9 100644 --- a/utils/uhjencoder.cpp +++ b/utils/uhjencoder.cpp @@ -502,11 +502,9 @@ int main(int argc, char **argv) got -= LeadIn; for(size_t c{0};c < uhjchans;++c) { - constexpr float max_val{8388607.0f / 8388608.0f}; - auto clamp = [](float v, float mn, float mx) noexcept - { return std::min(std::max(v, mn), mx); }; + static constexpr float max_val{8388607.0f / 8388608.0f}; for(size_t i{0};i < got;++i) - outmem[i*uhjchans + c] = clamp(encmem[c][LeadIn+i], -1.0f, max_val); + outmem[i*uhjchans + c] = std::clamp(encmem[c][LeadIn+i], -1.0f, max_val); } LeadIn = 0; -- cgit v1.2.3 From 92046ee22ff8a80a1a5b463165a840078fad8caa Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 6 May 2023 12:08:15 -0700 Subject: Use more appropriate types for some enums --- alc/alu.h | 3 ++- core/device.h | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'alc') diff --git a/alc/alu.h b/alc/alu.h index 253940cf..33453487 100644 --- a/alc/alu.h +++ b/alc/alu.h @@ -3,12 +3,13 @@ #include #include +#include struct ALCcontext; struct ALCdevice; struct EffectSlot; -enum class StereoEncoding : unsigned char; +enum class StereoEncoding : uint8_t; constexpr float GainMixMax{1000.0f}; /* +60dB */ diff --git a/core/device.h b/core/device.h index 9aaf7adb..bc180582 100644 --- a/core/device.h +++ b/core/device.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "almalloc.h" @@ -43,20 +44,20 @@ using uint = unsigned int; #define DEFAULT_NUM_UPDATES 3 -enum class DeviceType : unsigned char { +enum class DeviceType : uint8_t { Playback, Capture, Loopback }; -enum class RenderMode : unsigned char { +enum class RenderMode : uint8_t { Normal, Pairwise, Hrtf }; -enum class StereoEncoding : unsigned char { +enum class StereoEncoding : uint8_t { Basic, Uhj, Hrtf, -- cgit v1.2.3 From e42681c4472b8a149a8f1e68614e4f5ee5d04fb0 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 8 May 2023 14:47:19 -0700 Subject: Store extension strings individually And dynamically build the full AL_EXTENSIONS string --- al/extension.cpp | 12 +--- al/state.cpp | 2 +- alc/context.cpp | 166 ++++++++++++++++++++++++++----------------------------- alc/context.h | 7 +-- 4 files changed, 85 insertions(+), 102 deletions(-) (limited to 'alc') diff --git a/al/extension.cpp b/al/extension.cpp index 3ead0af8..dbaf4d5f 100644 --- a/al/extension.cpp +++ b/al/extension.cpp @@ -46,18 +46,10 @@ START_API_FUNC } size_t len{strlen(extName)}; - const char *ptr{context->mExtensionList}; - while(ptr && *ptr) + for(std::string_view ext : context->mExtensions) { - if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len]))) + if(len == ext.length() && al::strncasecmp(ext.data(), extName, len) == 0) return AL_TRUE; - - if((ptr=strchr(ptr, ' ')) != nullptr) - { - do { - ++ptr; - } while(isspace(*ptr)); - } } return AL_FALSE; diff --git a/al/state.cpp b/al/state.cpp index fb3186c7..cb2afd6c 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -560,7 +560,7 @@ START_API_FUNC break; case AL_EXTENSIONS: - value = context->mExtensionList; + value = context->mExtensionsString.c_str(); break; case AL_NO_ERROR: diff --git a/alc/context.cpp b/alc/context.cpp index 2fbf67af..d920d4b6 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "AL/efx.h" @@ -48,48 +49,52 @@ using namespace std::placeholders; using voidp = void*; /* Default context extensions */ -constexpr ALchar alExtList[] = - "AL_EXT_ALAW " - "AL_EXT_BFORMAT " - "AL_EXTX_debug " - "AL_EXT_DOUBLE " - "AL_EXT_EXPONENT_DISTANCE " - "AL_EXT_FLOAT32 " - "AL_EXT_IMA4 " - "AL_EXT_LINEAR_DISTANCE " - "AL_EXT_MCFORMATS " - "AL_EXT_MULAW " - "AL_EXT_MULAW_BFORMAT " - "AL_EXT_MULAW_MCFORMATS " - "AL_EXT_OFFSET " - "AL_EXT_source_distance_model " - "AL_EXT_SOURCE_RADIUS " - "AL_EXT_STATIC_BUFFER " - "AL_EXT_STEREO_ANGLES " - "AL_LOKI_quadriphonic " - "AL_SOFT_bformat_ex " - "AL_SOFTX_bformat_hoa " - "AL_SOFT_block_alignment " - "AL_SOFT_buffer_length_query " - "AL_SOFT_callback_buffer " - "AL_SOFTX_convolution_reverb " - "AL_SOFT_deferred_updates " - "AL_SOFT_direct_channels " - "AL_SOFT_direct_channels_remix " - "AL_SOFT_effect_target " - "AL_SOFT_events " - "AL_SOFT_gain_clamp_ex " - "AL_SOFTX_hold_on_disconnect " - "AL_SOFT_loop_points " - "AL_SOFTX_map_buffer " - "AL_SOFT_MSADPCM " - "AL_SOFT_source_latency " - "AL_SOFT_source_length " - "AL_SOFT_source_resampler " - "AL_SOFT_source_spatialize " - "AL_SOFT_source_start_delay " - "AL_SOFT_UHJ " - "AL_SOFT_UHJ_ex"; +std::vector getContextExtensions() noexcept +{ + return std::vector{ + "AL_EXT_ALAW", + "AL_EXT_BFORMAT", + "AL_EXTX_debug", + "AL_EXT_DOUBLE", + "AL_EXT_EXPONENT_DISTANCE", + "AL_EXT_FLOAT32", + "AL_EXT_IMA4", + "AL_EXT_LINEAR_DISTANCE", + "AL_EXT_MCFORMATS", + "AL_EXT_MULAW", + "AL_EXT_MULAW_BFORMAT", + "AL_EXT_MULAW_MCFORMATS", + "AL_EXT_OFFSET", + "AL_EXT_source_distance_model", + "AL_EXT_SOURCE_RADIUS", + "AL_EXT_STATIC_BUFFER", + "AL_EXT_STEREO_ANGLES", + "AL_LOKI_quadriphonic", + "AL_SOFT_bformat_ex", + "AL_SOFTX_bformat_hoa", + "AL_SOFT_block_alignment", + "AL_SOFT_buffer_length_query", + "AL_SOFT_callback_buffer", + "AL_SOFTX_convolution_reverb", + "AL_SOFT_deferred_updates", + "AL_SOFT_direct_channels", + "AL_SOFT_direct_channels_remix", + "AL_SOFT_effect_target", + "AL_SOFT_events", + "AL_SOFT_gain_clamp_ex", + "AL_SOFTX_hold_on_disconnect", + "AL_SOFT_loop_points", + "AL_SOFTX_map_buffer", + "AL_SOFT_MSADPCM", + "AL_SOFT_source_latency", + "AL_SOFT_source_length", + "AL_SOFT_source_resampler", + "AL_SOFT_source_spatialize", + "AL_SOFT_source_start_delay", + "AL_SOFT_UHJ", + "AL_SOFT_UHJ_ex", + }; +} } // namespace @@ -179,26 +184,41 @@ void ALCcontext::init() mCurrentVoiceChange.store(cur, std::memory_order_relaxed); } - mExtensionList = alExtList; + mExtensions = getContextExtensions(); if(sBufferSubDataCompat) { - std::string extlist{mExtensionList}; - - const auto pos = extlist.find("AL_EXT_SOURCE_RADIUS "); - if(pos != std::string::npos) - extlist.replace(pos, 20, "AL_SOFT_buffer_sub_data"); - else - extlist += " AL_SOFT_buffer_sub_data"; - - mExtensionListOverride = std::move(extlist); - mExtensionList = mExtensionListOverride.c_str(); + auto iter = std::find(mExtensions.begin(), mExtensions.end(), "AL_EXT_SOURCE_RADIUS"); + if(iter != mExtensions.end()) mExtensions.erase(iter); + /* TODO: Would be nice to sort this alphabetically. Needs case- + * insensitive searching. + */ + mExtensions.emplace_back("AL_SOFT_buffer_sub_data"); } #ifdef ALSOFT_EAX eax_initialize_extensions(); #endif // ALSOFT_EAX + if(!mExtensions.empty()) + { + const size_t len{std::accumulate(mExtensions.cbegin()+1, mExtensions.cend(), + mExtensions.front().length(), + [](size_t current, std::string_view ext) noexcept + { return current + ext.length() + 1; })}; + + std::string extensions; + extensions.reserve(len); + extensions += mExtensions.front(); + for(std::string_view ext : al::span{mExtensions}.subspan<1>()) + { + extensions += ' '; + extensions += ext; + } + + mExtensionsString = std::move(extensions); + } + mParams.Position = alu::Vector{0.0f, 0.0f, 0.0f, 1.0f}; mParams.Matrix = alu::Matrix::Identity(); mParams.Velocity = alu::Vector{}; @@ -457,43 +477,15 @@ void ALCcontext::eax_initialize_extensions() if(!eax_g_is_enabled) return; - const auto string_max_capacity = - std::strlen(mExtensionList) + 1 + - std::strlen(eax1_ext_name) + 1 + - std::strlen(eax2_ext_name) + 1 + - std::strlen(eax3_ext_name) + 1 + - std::strlen(eax4_ext_name) + 1 + - std::strlen(eax5_ext_name) + 1 + - std::strlen(eax_x_ram_ext_name) + 1; - - std::string extlist; - extlist.reserve(string_max_capacity); - + mExtensions.emplace(mExtensions.begin(), eax_x_ram_ext_name); if(eaxIsCapable()) { - extlist += eax1_ext_name; - extlist += ' '; - - extlist += eax2_ext_name; - extlist += ' '; - - extlist += eax3_ext_name; - extlist += ' '; - - extlist += eax4_ext_name; - extlist += ' '; - - extlist += eax5_ext_name; - extlist += ' '; + mExtensions.emplace(mExtensions.begin(), eax5_ext_name); + mExtensions.emplace(mExtensions.begin(), eax4_ext_name); + mExtensions.emplace(mExtensions.begin(), eax3_ext_name); + mExtensions.emplace(mExtensions.begin(), eax2_ext_name); + mExtensions.emplace(mExtensions.begin(), eax1_ext_name); } - - extlist += eax_x_ram_ext_name; - extlist += ' '; - - extlist += mExtensionList; - - mExtensionListOverride = std::move(extlist); - mExtensionList = mExtensionListOverride.c_str(); } void ALCcontext::eax_initialize() diff --git a/alc/context.h b/alc/context.h index 402794eb..acbb3788 100644 --- a/alc/context.h +++ b/alc/context.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include "AL/al.h" @@ -143,9 +143,8 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { /* Default effect slot */ std::unique_ptr mDefaultSlot; - const char *mExtensionList{nullptr}; - - std::string mExtensionListOverride{}; + std::vector mExtensions; + std::string mExtensionsString{}; ALCcontext(al::intrusive_ptr device, ContextFlagBitset flags); -- cgit v1.2.3 From e1e375e5238282c36ab7dddf148461c4370de39d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 8 May 2023 17:22:24 -0700 Subject: Send a debug message when disconnecting --- al/event.cpp | 23 ++++++++++++++++++----- alc/alu.cpp | 15 ++++++--------- 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'alc') diff --git a/al/event.cpp b/al/event.cpp index 33e28412..4fa1bf56 100644 --- a/al/event.cpp +++ b/al/event.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,7 @@ #include "core/except.h" #include "core/logging.h" #include "core/voice_change.h" +#include "debug.h" #include "opthelpers.h" #include "ringbuffer.h" #include "threads.h" @@ -63,11 +65,13 @@ static int EventThread(ALCcontext *context) } auto enabledevts = context->mEnabledEvts.load(std::memory_order_acquire); - if(!context->mEventCb || !enabledevts.test(evt.EnumType)) - continue; + if(!context->mEventCb) continue; if(evt.EnumType == AsyncEvent::SourceStateChange) { + if(!enabledevts.test(AsyncEvent::SourceStateChange)) + continue; + ALuint state{}; std::string msg{"Source ID " + std::to_string(evt.u.srcstate.id)}; msg += " state has changed to "; @@ -95,6 +99,9 @@ static int EventThread(ALCcontext *context) } else if(evt.EnumType == AsyncEvent::BufferCompleted) { + if(!enabledevts.test(AsyncEvent::BufferCompleted)) + continue; + std::string msg{std::to_string(evt.u.bufcomp.count)}; if(evt.u.bufcomp.count == 1) msg += " buffer completed"; else msg += " buffers completed"; @@ -104,9 +111,15 @@ static int EventThread(ALCcontext *context) } else if(evt.EnumType == AsyncEvent::Disconnected) { - context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0, - static_cast(strlen(evt.u.disconnect.msg)), evt.u.disconnect.msg, - context->mEventParam); + const std::string_view message{evt.u.disconnect.msg}; + + context->debugMessage(DebugSource::System, DebugType::Error, 0, + DebugSeverity::High, static_cast(message.length()), message.data()); + + if(enabledevts.test(AsyncEvent::Disconnected)) + context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0, + static_cast(message.length()), message.data(), + context->mEventParam); } } while(evt_data.len != 0); } diff --git a/alc/alu.cpp b/alc/alu.cpp index fc22febb..1157aca3 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -2178,16 +2178,13 @@ void DeviceBase::handleDisconnect(const char *msg, ...) for(ContextBase *ctx : *mContexts.load()) { - if(ctx->mEnabledEvts.load(std::memory_order_acquire).test(AsyncEvent::Disconnected)) + RingBuffer *ring{ctx->mAsyncEvents.get()}; + auto evt_data = ring->getWriteVector().first; + if(evt_data.len > 0) { - RingBuffer *ring{ctx->mAsyncEvents.get()}; - auto evt_data = ring->getWriteVector().first; - if(evt_data.len > 0) - { - al::construct_at(reinterpret_cast(evt_data.buf), evt); - ring->writeAdvance(1); - ctx->mEventSem.post(); - } + al::construct_at(reinterpret_cast(evt_data.buf), evt); + ring->writeAdvance(1); + ctx->mEventSem.post(); } if(!ctx->mStopVoicesOnDisconnect) -- cgit v1.2.3 From d2b000c7602bcc337a4f4e5590ef65c1cfcb4cb2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 8 May 2023 20:01:14 -0700 Subject: Use a variant for AsyncEvent --- al/event.cpp | 94 +++++++++++++++++++++++++++++++----------------------- alc/alu.cpp | 31 +++++++++--------- core/async_event.h | 89 +++++++++++++++++++++++++++------------------------ core/context.h | 3 +- core/voice.cpp | 20 ++++++------ 5 files changed, 129 insertions(+), 108 deletions(-) (limited to 'alc') diff --git a/al/event.cpp b/al/event.cpp index 4fa1bf56..eb6af45c 100644 --- a/al/event.cpp +++ b/al/event.cpp @@ -32,7 +32,15 @@ #include "threads.h" -static int EventThread(ALCcontext *context) +namespace { + +template +struct overloaded : Ts... { using Ts::operator()...; }; + +template +overloaded(Ts...) -> overloaded; + +int EventThread(ALCcontext *context) { RingBuffer *ring{context->mAsyncEvents.get()}; bool quitnow{false}; @@ -51,81 +59,87 @@ static int EventThread(ALCcontext *context) evt_data.buf += sizeof(AsyncEvent); evt_data.len -= 1; - AsyncEvent evt{*evt_ptr}; + AsyncEvent event{std::move(*evt_ptr)}; std::destroy_at(evt_ptr); ring->readAdvance(1); - quitnow = evt.EnumType == AsyncEvent::KillThread; + quitnow = std::holds_alternative(event); if(quitnow) UNLIKELY break; - if(evt.EnumType == AsyncEvent::ReleaseEffectState) - { - al::intrusive_ptr{evt.u.mEffectState}; - continue; - } - auto enabledevts = context->mEnabledEvts.load(std::memory_order_acquire); - if(!context->mEventCb) continue; - - if(evt.EnumType == AsyncEvent::SourceStateChange) + auto proc_killthread = [](AsyncKillThread&) { }; + auto proc_release = [](AsyncEffectReleaseEvent &evt) + { + al::intrusive_ptr{evt.mEffectState}; + }; + auto proc_srcstate = [context,enabledevts](AsyncSourceStateEvent &evt) { - if(!enabledevts.test(AsyncEvent::SourceStateChange)) - continue; + if(!context->mEventCb + || !enabledevts.test(al::to_underlying(AsyncEnableBits::SourceState))) + return; ALuint state{}; - std::string msg{"Source ID " + std::to_string(evt.u.srcstate.id)}; + std::string msg{"Source ID " + std::to_string(evt.mId)}; msg += " state has changed to "; - switch(evt.u.srcstate.state) + switch(evt.mState) { - case AsyncEvent::SrcState::Reset: + case AsyncSrcState::Reset: msg += "AL_INITIAL"; state = AL_INITIAL; break; - case AsyncEvent::SrcState::Stop: + case AsyncSrcState::Stop: msg += "AL_STOPPED"; state = AL_STOPPED; break; - case AsyncEvent::SrcState::Play: + case AsyncSrcState::Play: msg += "AL_PLAYING"; state = AL_PLAYING; break; - case AsyncEvent::SrcState::Pause: + case AsyncSrcState::Pause: msg += "AL_PAUSED"; state = AL_PAUSED; break; } - context->mEventCb(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT, evt.u.srcstate.id, - state, static_cast(msg.length()), msg.c_str(), context->mEventParam); - } - else if(evt.EnumType == AsyncEvent::BufferCompleted) + context->mEventCb(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT, evt.mId, state, + static_cast(msg.length()), msg.c_str(), context->mEventParam); + }; + auto proc_buffercomp = [context,enabledevts](AsyncBufferCompleteEvent &evt) { - if(!enabledevts.test(AsyncEvent::BufferCompleted)) - continue; + if(!context->mEventCb + || !enabledevts.test(al::to_underlying(AsyncEnableBits::BufferCompleted))) + return; - std::string msg{std::to_string(evt.u.bufcomp.count)}; - if(evt.u.bufcomp.count == 1) msg += " buffer completed"; + std::string msg{std::to_string(evt.mCount)}; + if(evt.mCount == 1) msg += " buffer completed"; else msg += " buffers completed"; - context->mEventCb(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT, evt.u.bufcomp.id, - evt.u.bufcomp.count, static_cast(msg.length()), msg.c_str(), - context->mEventParam); - } - else if(evt.EnumType == AsyncEvent::Disconnected) + context->mEventCb(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT, evt.mId, evt.mCount, + static_cast(msg.length()), msg.c_str(), context->mEventParam); + }; + auto proc_disconnect = [context,enabledevts](AsyncDisconnectEvent &evt) { - const std::string_view message{evt.u.disconnect.msg}; + const std::string_view message{evt.msg}; context->debugMessage(DebugSource::System, DebugType::Error, 0, DebugSeverity::High, static_cast(message.length()), message.data()); - if(enabledevts.test(AsyncEvent::Disconnected)) + if(context->mEventCb + && enabledevts.test(al::to_underlying(AsyncEnableBits::Disconnected))) context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0, static_cast(message.length()), message.data(), context->mEventParam); - } + }; + + std::visit(overloaded + {proc_srcstate, proc_buffercomp, proc_release, proc_disconnect, proc_killthread}, + event); } while(evt_data.len != 0); } return 0; } +} // namespace + + void StartEventThrd(ALCcontext *ctx) { try { @@ -150,7 +164,7 @@ void StopEventThrd(ALCcontext *ctx) evt_data = ring->getWriteVector().first; } while(evt_data.len == 0); } - al::construct_at(reinterpret_cast(evt_data.buf), AsyncEvent::KillThread); + std::ignore = InitAsyncEvent(reinterpret_cast(evt_data.buf)); ring->writeAdvance(1); ctx->mEventSem.post(); @@ -174,11 +188,11 @@ START_API_FUNC [&flags](ALenum type) noexcept -> bool { if(type == AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT) - flags.set(AsyncEvent::BufferCompleted); + flags.set(al::to_underlying(AsyncEnableBits::BufferCompleted)); else if(type == AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT) - flags.set(AsyncEvent::SourceStateChange); + flags.set(al::to_underlying(AsyncEnableBits::SourceState)); else if(type == AL_EVENT_TYPE_DISCONNECTED_SOFT) - flags.set(AsyncEvent::Disconnected); + flags.set(al::to_underlying(AsyncEnableBits::Disconnected)); else return false; return true; diff --git a/alc/alu.cpp b/alc/alu.cpp index 1157aca3..cf250988 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -491,9 +491,9 @@ bool CalcEffectSlotParams(EffectSlot *slot, EffectSlot **sorted_slots, ContextBa auto evt_vec = ring->getWriteVector(); if(evt_vec.first.len > 0) LIKELY { - AsyncEvent *evt{al::construct_at(reinterpret_cast(evt_vec.first.buf), - AsyncEvent::ReleaseEffectState)}; - evt->u.mEffectState = oldstate; + AsyncEffectReleaseEvent &evt = InitAsyncEvent( + reinterpret_cast(evt_vec.first.buf)); + evt.mEffectState = oldstate; ring->writeAdvance(1); } else @@ -1701,22 +1701,22 @@ void SendSourceStateEvent(ContextBase *context, uint id, VChangeState state) auto evt_vec = ring->getWriteVector(); if(evt_vec.first.len < 1) return; - AsyncEvent *evt{al::construct_at(reinterpret_cast(evt_vec.first.buf), - AsyncEvent::SourceStateChange)}; - evt->u.srcstate.id = id; + AsyncSourceStateEvent &evt = InitAsyncEvent( + reinterpret_cast(evt_vec.first.buf)); + evt.mId = id; switch(state) { case VChangeState::Reset: - evt->u.srcstate.state = AsyncEvent::SrcState::Reset; + evt.mState = AsyncSrcState::Reset; break; case VChangeState::Stop: - evt->u.srcstate.state = AsyncEvent::SrcState::Stop; + evt.mState = AsyncSrcState::Stop; break; case VChangeState::Play: - evt->u.srcstate.state = AsyncEvent::SrcState::Play; + evt.mState = AsyncSrcState::Play; break; case VChangeState::Pause: - evt->u.srcstate.state = AsyncEvent::SrcState::Pause; + evt.mState = AsyncSrcState::Pause; break; /* Shouldn't happen. */ case VChangeState::Restart: @@ -1813,7 +1813,7 @@ void ProcessVoiceChanges(ContextBase *ctx) } oldvoice->mPendingChange.store(false, std::memory_order_release); } - if(sendevt && enabledevt.test(AsyncEvent::SourceStateChange)) + if(sendevt && enabledevt.test(al::to_underlying(AsyncEnableBits::SourceState))) SendSourceStateEvent(ctx, cur->mSourceID, cur->mState); next = cur->mNext.load(std::memory_order_acquire); @@ -2166,15 +2166,16 @@ void DeviceBase::handleDisconnect(const char *msg, ...) IncrementRef(MixCount); if(Connected.exchange(false, std::memory_order_acq_rel)) { - AsyncEvent evt{AsyncEvent::Disconnected}; + AsyncEvent evt{std::in_place_type}; + auto &disconnect = std::get(evt); va_list args; va_start(args, msg); - int msglen{vsnprintf(evt.u.disconnect.msg, sizeof(evt.u.disconnect.msg), msg, args)}; + int msglen{vsnprintf(disconnect.msg, sizeof(disconnect.msg), msg, args)}; va_end(args); - if(msglen < 0 || static_cast(msglen) >= sizeof(evt.u.disconnect.msg)) - evt.u.disconnect.msg[sizeof(evt.u.disconnect.msg)-1] = 0; + if(msglen < 0 || static_cast(msglen) >= sizeof(disconnect.msg)) + disconnect.msg[sizeof(disconnect.msg)-1] = 0; for(ContextBase *ctx : *mContexts.load()) { diff --git a/core/async_event.h b/core/async_event.h index 5a2f5f91..9e2d1193 100644 --- a/core/async_event.h +++ b/core/async_event.h @@ -1,6 +1,9 @@ #ifndef CORE_EVENT_H #define CORE_EVENT_H +#include +#include + #include "almalloc.h" struct EffectState; @@ -8,48 +11,50 @@ struct EffectState; using uint = unsigned int; -struct AsyncEvent { - enum : uint { - /* User event types. */ - SourceStateChange, - BufferCompleted, - Disconnected, - UserEventCount, - - /* Internal events, always processed. */ - ReleaseEffectState = 128, - - /* End event thread processing. */ - KillThread, - }; - - enum class SrcState { - Reset, - Stop, - Play, - Pause - }; - - const uint EnumType; - union { - char dummy; - struct { - uint id; - SrcState state; - } srcstate; - struct { - uint id; - uint count; - } bufcomp; - struct { - char msg[244]; - } disconnect; - EffectState *mEffectState; - } u{}; - - constexpr AsyncEvent(uint type) noexcept : EnumType{type} { } - - DISABLE_ALLOC() +enum class AsyncEnableBits : uint8_t { + SourceState, + BufferCompleted, + Disconnected, + + Count +}; + + +enum class AsyncSrcState : uint8_t { + Reset, + Stop, + Play, + Pause +}; + +using AsyncKillThread = std::monostate; + +struct AsyncSourceStateEvent { + uint mId; + AsyncSrcState mState; }; +struct AsyncBufferCompleteEvent { + uint mId; + uint mCount; +}; + +struct AsyncDisconnectEvent { + char msg[244]; +}; + +struct AsyncEffectReleaseEvent { + EffectState *mEffectState; +}; + +using AsyncEvent = std::variant; + +template +auto &InitAsyncEvent(AsyncEvent *evt, Args&& ...args) +{ return std::get(*al::construct_at(evt, std::in_place_type, std::forward(args)...)); } + #endif diff --git a/core/context.h b/core/context.h index 9723eac3..4febd38d 100644 --- a/core/context.h +++ b/core/context.h @@ -13,6 +13,7 @@ #include "async_event.h" #include "atomic.h" #include "bufferline.h" +#include "opthelpers.h" #include "threads.h" #include "vecmat.h" #include "vector.h" @@ -137,7 +138,7 @@ struct ContextBase { std::thread mEventThread; al::semaphore mEventSem; std::unique_ptr mAsyncEvents; - using AsyncEventBitset = std::bitset; + using AsyncEventBitset = std::bitset; std::atomic mEnabledEvts{0u}; /* Asynchronous voice change actions are processed as a linked list of diff --git a/core/voice.cpp b/core/voice.cpp index 478ea81f..3e78b176 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -226,10 +226,10 @@ void SendSourceStoppedEvent(ContextBase *context, uint id) auto evt_vec = ring->getWriteVector(); if(evt_vec.first.len < 1) return; - AsyncEvent *evt{al::construct_at(reinterpret_cast(evt_vec.first.buf), - AsyncEvent::SourceStateChange)}; - evt->u.srcstate.id = id; - evt->u.srcstate.state = AsyncEvent::SrcState::Stop; + AsyncSourceStateEvent &evt = InitAsyncEvent( + reinterpret_cast(evt_vec.first.buf)); + evt.mId = id; + evt.mState = AsyncSrcState::Stop; ring->writeAdvance(1); } @@ -1145,16 +1145,16 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi /* Send any events now, after the position/buffer info was updated. */ const auto enabledevt = Context->mEnabledEvts.load(std::memory_order_acquire); - if(buffers_done > 0 && enabledevt.test(AsyncEvent::BufferCompleted)) + if(buffers_done > 0 && enabledevt.test(al::to_underlying(AsyncEnableBits::BufferCompleted))) { RingBuffer *ring{Context->mAsyncEvents.get()}; auto evt_vec = ring->getWriteVector(); if(evt_vec.first.len > 0) { - AsyncEvent *evt{al::construct_at(reinterpret_cast(evt_vec.first.buf), - AsyncEvent::BufferCompleted)}; - evt->u.bufcomp.id = SourceID; - evt->u.bufcomp.count = buffers_done; + AsyncBufferCompleteEvent &evt = InitAsyncEvent( + reinterpret_cast(evt_vec.first.buf)); + evt.mId = SourceID; + evt.mCount = buffers_done; ring->writeAdvance(1); } } @@ -1165,7 +1165,7 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi * ensures any residual noise fades to 0 amplitude. */ mPlayState.store(Stopping, std::memory_order_release); - if(enabledevt.test(AsyncEvent::SourceStateChange)) + if(enabledevt.test(al::to_underlying(AsyncEnableBits::SourceState))) SendSourceStoppedEvent(Context, SourceID); } } -- cgit v1.2.3 From 72f02418e505a192c0cc7b27cd7b3aa28a7a03ec Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 12 May 2023 16:01:06 -0700 Subject: Clean up some more includes --- alc/backends/alsa.cpp | 1 + alc/backends/coreaudio.cpp | 8 ++++---- alc/backends/dsound.cpp | 14 +++++++------- alc/backends/jack.cpp | 4 ++-- alc/backends/oboe.cpp | 1 + alc/backends/opensl.cpp | 3 ++- alc/backends/oss.cpp | 2 -- alc/backends/winmm.cpp | 4 ++-- core/context.cpp | 3 +++ core/context.h | 13 +++++-------- core/device.h | 4 +--- 11 files changed, 28 insertions(+), 29 deletions(-) (limited to 'alc') diff --git a/alc/backends/alsa.cpp b/alc/backends/alsa.cpp index 74713590..c1690867 100644 --- a/alc/backends/alsa.cpp +++ b/alc/backends/alsa.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index 19a1f753..c2a79815 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -22,17 +22,17 @@ #include "coreaudio.h" +#include #include +#include +#include #include #include #include +#include #include #include -#include -#include -#include - #include "alnumeric.h" #include "core/converter.h" #include "core/device.h" diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index 05117781..ffcd8430 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -25,10 +25,6 @@ #define WIN32_LEAN_AND_MEAN #include -#include -#include -#include - #include #include #ifndef _WAVEFORMATEXTENSIBLE_ @@ -36,13 +32,17 @@ #include #endif +#include #include #include -#include +#include +#include +#include +#include +#include #include +#include #include -#include -#include #include "albit.h" #include "alnumeric.h" diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp index 7e1e8fc7..b12edf9f 100644 --- a/alc/backends/jack.cpp +++ b/alc/backends/jack.cpp @@ -22,12 +22,12 @@ #include "jack.h" +#include #include #include #include #include - -#include +#include #include #include diff --git a/alc/backends/oboe.cpp b/alc/backends/oboe.cpp index 4c47190e..c74b0180 100644 --- a/alc/backends/oboe.cpp +++ b/alc/backends/oboe.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include "alnumeric.h" diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp index 0c2936b2..c9053816 100644 --- a/alc/backends/opensl.cpp +++ b/alc/backends/opensl.cpp @@ -26,9 +26,10 @@ #include #include -#include #include #include +#include +#include #include #include diff --git a/alc/backends/oss.cpp b/alc/backends/oss.cpp index 9e247be1..1fdee701 100644 --- a/alc/backends/oss.cpp +++ b/alc/backends/oss.cpp @@ -31,12 +31,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/alc/backends/winmm.cpp b/alc/backends/winmm.cpp index 135b59df..edb875a0 100644 --- a/alc/backends/winmm.cpp +++ b/alc/backends/winmm.cpp @@ -55,8 +55,8 @@ namespace { #define DEVNAME_HEAD "OpenAL Soft on " -al::vector PlaybackDevices; -al::vector CaptureDevices; +std::vector PlaybackDevices; +std::vector CaptureDevices; bool checkName(const al::vector &list, const std::string &name) { return std::find(list.cbegin(), list.cend(), name) != list.cend(); } diff --git a/core/context.cpp b/core/context.cpp index d94daf16..145ce349 100644 --- a/core/context.cpp +++ b/core/context.cpp @@ -2,7 +2,10 @@ #include "config.h" #include +#include #include +#include +#include #include "async_event.h" #include "context.h" diff --git a/core/context.h b/core/context.h index 4febd38d..629e67a5 100644 --- a/core/context.h +++ b/core/context.h @@ -7,16 +7,15 @@ #include #include #include +#include #include "almalloc.h" #include "alspan.h" #include "async_event.h" #include "atomic.h" -#include "bufferline.h" #include "opthelpers.h" #include "threads.h" #include "vecmat.h" -#include "vector.h" struct DeviceBase; struct EffectSlot; @@ -26,8 +25,6 @@ struct Voice; struct VoiceChange; struct VoicePropsItem; -using uint = unsigned int; - constexpr float SpeedOfSoundMetersPerSec{343.3f}; @@ -147,20 +144,20 @@ struct ContextBase { * in clusters that are stored in a vector for easy automatic cleanup. */ using VoiceChangeCluster = std::unique_ptr; - al::vector mVoiceChangeClusters; + std::vector mVoiceChangeClusters; using VoiceCluster = std::unique_ptr; - al::vector mVoiceClusters; + std::vector mVoiceClusters; using VoicePropsCluster = std::unique_ptr; - al::vector mVoicePropClusters; + std::vector mVoicePropClusters; static constexpr size_t EffectSlotClusterSize{4}; EffectSlot *getEffectSlot(); using EffectSlotCluster = std::unique_ptr; - al::vector mEffectSlotClusters; + std::vector mEffectSlotClusters; ContextBase(DeviceBase *device); diff --git a/core/device.h b/core/device.h index bc180582..33cdfe89 100644 --- a/core/device.h +++ b/core/device.h @@ -1,14 +1,12 @@ #ifndef CORE_DEVICE_H #define CORE_DEVICE_H -#include - #include #include #include #include #include -#include +#include #include #include -- cgit v1.2.3 From e7ea579ca5f3c0da6cfe80ec9a7295bca60198aa Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 12 May 2023 18:02:12 -0700 Subject: Avoid using al::vector unnecessarily --- al/auxeffectslot.cpp | 8 +++---- al/buffer.cpp | 5 +++-- al/effect.cpp | 4 ++-- al/error.cpp | 4 ++-- al/filter.cpp | 4 ++-- al/source.cpp | 13 ++++++------ alc/alc.cpp | 12 +++++------ alc/backends/alsa.cpp | 16 +++++++------- alc/backends/coreaudio.cpp | 4 ++-- alc/backends/dsound.cpp | 9 ++++---- alc/backends/jack.cpp | 5 +++-- alc/backends/oss.cpp | 14 ++++++------ alc/backends/pulseaudio.cpp | 6 +++--- alc/backends/solaris.cpp | 4 ++-- alc/backends/wasapi.cpp | 18 ++++++++-------- alc/backends/wave.cpp | 4 ++-- alc/backends/winmm.cpp | 2 +- alc/context.h | 6 +++--- alc/device.h | 10 ++++----- alc/effects/chorus.cpp | 4 ++-- alc/effects/echo.cpp | 6 +++--- alc/panning.cpp | 3 ++- core/bformatdec.h | 4 ++-- core/hrtf.cpp | 52 ++++++++++++++++++++++----------------------- core/hrtf.h | 4 ++-- core/logging.cpp | 4 ++-- 26 files changed, 115 insertions(+), 110 deletions(-) (limited to 'alc') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index c69990fe..3a3222b8 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -341,7 +341,7 @@ START_API_FUNC } else { - al::vector ids; + std::vector ids; ALsizei count{n}; ids.reserve(static_cast(count)); do { @@ -383,7 +383,7 @@ START_API_FUNC } else { - auto slots = al::vector(static_cast(n)); + auto slots = std::vector(static_cast(n)); for(size_t i{0};i < slots.size();++i) { ALeffectslot *slot{LookupEffectSlot(context.get(), effectslots[i])}; @@ -466,7 +466,7 @@ START_API_FUNC context->setError(AL_INVALID_VALUE, "Playing %d effect slots", n); if(n <= 0) UNLIKELY return; - auto slots = al::vector(static_cast(n)); + auto slots = std::vector(static_cast(n)); std::lock_guard _{context->mEffectSlotLock}; for(size_t i{0};i < slots.size();++i) { @@ -520,7 +520,7 @@ START_API_FUNC context->setError(AL_INVALID_VALUE, "Stopping %d effect slots", n); if(n <= 0) UNLIKELY return; - auto slots = al::vector(static_cast(n)); + auto slots = std::vector(static_cast(n)); std::lock_guard _{context->mEffectSlotLock}; for(size_t i{0};i < slots.size();++i) { diff --git a/al/buffer.cpp b/al/buffer.cpp index 1f008c8e..bfc10906 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include "AL/al.h" #include "AL/alc.h" @@ -345,7 +346,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, */ if(newsize != ALBuf->mDataStorage.size()) { - auto newdata = al::vector(newsize, std::byte{}); + auto newdata = decltype(ALBuf->mDataStorage)(newsize, std::byte{}); if((access&AL_PRESERVE_DATA_BIT_SOFT)) { const size_t tocopy{minz(newdata.size(), ALBuf->mDataStorage.size())}; @@ -663,7 +664,7 @@ START_API_FUNC /* Store the allocated buffer IDs in a separate local list, to avoid * modifying the user storage in case of failure. */ - al::vector ids; + std::vector ids; ids.reserve(static_cast(n)); do { ALbuffer *buffer{AllocBuffer(device)}; diff --git a/al/effect.cpp b/al/effect.cpp index 3d91139a..3ca7c37e 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "AL/al.h" #include "AL/alc.h" @@ -49,7 +50,6 @@ #include "core/except.h" #include "core/logging.h" #include "opthelpers.h" -#include "vector.h" #ifdef ALSOFT_EAX #include @@ -259,7 +259,7 @@ START_API_FUNC /* Store the allocated buffer IDs in a separate local list, to avoid * modifying the user storage in case of failure. */ - al::vector ids; + std::vector ids; ids.reserve(static_cast(n)); do { ALeffect *effect{AllocEffect(device)}; diff --git a/al/error.cpp b/al/error.cpp index 39fd9f0a..b0607d66 100644 --- a/al/error.cpp +++ b/al/error.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "AL/al.h" #include "AL/alc.h" @@ -41,14 +42,13 @@ #include "core/except.h" #include "core/logging.h" #include "opthelpers.h" -#include "vector.h" bool TrapALError{false}; void ALCcontext::setError(ALenum errorCode, const char *msg, ...) { - auto message = al::vector(256); + auto message = std::vector(256); va_list args, args2; va_start(args, msg); diff --git a/al/filter.cpp b/al/filter.cpp index 0fd8eaa8..11d71179 100644 --- a/al/filter.cpp +++ b/al/filter.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "AL/al.h" #include "AL/alc.h" @@ -43,7 +44,6 @@ #include "alnumeric.h" #include "core/except.h" #include "opthelpers.h" -#include "vector.h" namespace { @@ -430,7 +430,7 @@ START_API_FUNC /* Store the allocated buffer IDs in a separate local list, to avoid * modifying the user storage in case of failure. */ - al::vector ids; + std::vector ids; ids.reserve(static_cast(n)); do { ALfilter *filter{AllocFilter(device)}; diff --git a/al/source.cpp b/al/source.cpp index efe65332..1bfd5a94 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include "AL/al.h" #include "AL/alc.h" @@ -2659,7 +2660,7 @@ START_API_FUNC } else { - al::vector ids; + std::vector ids; ids.reserve(static_cast(n)); do { ALsource *source{AllocSource(context.get())}; @@ -3223,7 +3224,7 @@ START_API_FUNC context->setError(AL_INVALID_VALUE, "Playing %d sources", n); if(n <= 0) UNLIKELY return; - al::vector extra_sources; + std::vector extra_sources; std::array source_storage; al::span srchandles; if(static_cast(n) <= source_storage.size()) LIKELY @@ -3261,7 +3262,7 @@ START_API_FUNC if(start_time < 0) UNLIKELY return context->setError(AL_INVALID_VALUE, "Invalid time point %" PRId64, start_time); - al::vector extra_sources; + std::vector extra_sources; std::array source_storage; al::span srchandles; if(static_cast(n) <= source_storage.size()) LIKELY @@ -3301,7 +3302,7 @@ START_API_FUNC context->setError(AL_INVALID_VALUE, "Pausing %d sources", n); if(n <= 0) UNLIKELY return; - al::vector extra_sources; + std::vector extra_sources; std::array source_storage; al::span srchandles; if(static_cast(n) <= source_storage.size()) LIKELY @@ -3377,7 +3378,7 @@ START_API_FUNC context->setError(AL_INVALID_VALUE, "Stopping %d sources", n); if(n <= 0) UNLIKELY return; - al::vector extra_sources; + std::vector extra_sources; std::array source_storage; al::span srchandles; if(static_cast(n) <= source_storage.size()) LIKELY @@ -3440,7 +3441,7 @@ START_API_FUNC context->setError(AL_INVALID_VALUE, "Rewinding %d sources", n); if(n <= 0) UNLIKELY return; - al::vector extra_sources; + std::vector extra_sources; std::array source_storage; al::span srchandles; if(static_cast(n) <= source_storage.size()) LIKELY diff --git a/alc/alc.cpp b/alc/alc.cpp index 290cc3d1..9fedee0b 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include "AL/al.h" #include "AL/alc.h" @@ -102,7 +103,6 @@ #include "opthelpers.h" #include "strutils.h" #include "threads.h" -#include "vector.h" #include "backends/base.h" #include "backends/null.h" @@ -1050,8 +1050,8 @@ using DeviceRef = al::intrusive_ptr; /************************************************ * Device lists ************************************************/ -al::vector DeviceList; -al::vector ContextList; +std::vector DeviceList; +std::vector ContextList; std::recursive_mutex ListLock; @@ -3130,7 +3130,7 @@ START_API_FUNC } if(!dev || dev->Type == DeviceType::Capture) { - auto ivals = al::vector(static_cast(size)); + auto ivals = std::vector(static_cast(size)); if(size_t got{GetIntegerv(dev.get(), pname, ivals)}) std::copy_n(ivals.begin(), got, values); return; @@ -3249,7 +3249,7 @@ START_API_FUNC break; default: - auto ivals = al::vector(static_cast(size)); + auto ivals = std::vector(static_cast(size)); if(size_t got{GetIntegerv(dev.get(), pname, ivals)}) std::copy_n(ivals.begin(), got, values); break; @@ -3676,7 +3676,7 @@ START_API_FUNC DeviceList.erase(iter); std::unique_lock statelock{dev->StateLock}; - al::vector orphanctxs; + std::vector orphanctxs; for(ContextBase *ctx : *dev->mContexts.load()) { auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx); diff --git a/alc/backends/alsa.cpp b/alc/backends/alsa.cpp index c1690867..ce368f5e 100644 --- a/alc/backends/alsa.cpp +++ b/alc/backends/alsa.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "albit.h" #include "alc/alconfig.h" @@ -46,7 +47,6 @@ #include "dynload.h" #include "ringbuffer.h" #include "threads.h" -#include "vector.h" #include @@ -248,8 +248,8 @@ struct DevMap { { } }; -al::vector PlaybackDevices; -al::vector CaptureDevices; +std::vector PlaybackDevices; +std::vector CaptureDevices; const char *prefix_name(snd_pcm_stream_t stream) @@ -258,9 +258,9 @@ const char *prefix_name(snd_pcm_stream_t stream) return (stream==SND_PCM_STREAM_PLAYBACK) ? "device-prefix" : "capture-prefix"; } -al::vector probe_devices(snd_pcm_stream_t stream) +std::vector probe_devices(snd_pcm_stream_t stream) { - al::vector devlist; + std::vector devlist; snd_ctl_card_info_t *info; snd_ctl_card_info_malloc(&info); @@ -439,7 +439,7 @@ struct AlsaPlayback final : public BackendBase { std::mutex mMutex; uint mFrameStep{}; - al::vector mBuffer; + std::vector mBuffer; std::atomic mKillNow{true}; std::thread mThread; @@ -880,7 +880,7 @@ struct AlsaCapture final : public BackendBase { snd_pcm_t *mPcmHandle{nullptr}; - al::vector mBuffer; + std::vector mBuffer; bool mDoCapture{false}; RingBufferPtr mRing{nullptr}; @@ -1024,7 +1024,7 @@ void AlsaCapture::stop() /* The ring buffer implicitly captures when checking availability. * Direct access needs to explicitly capture it into temp storage. */ - auto temp = al::vector( + auto temp = std::vector( static_cast(snd_pcm_frames_to_bytes(mPcmHandle, avail))); captureSamples(temp.data(), avail); mBuffer = std::move(temp); diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index c2a79815..521f085d 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -25,13 +25,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include "alnumeric.h" #include "core/converter.h" @@ -578,7 +578,7 @@ struct CoreAudioCapture final : public BackendBase { SampleConverterPtr mConverter; - al::vector mCaptureData; + std::vector mCaptureData; RingBufferPtr mRing{nullptr}; diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index ffcd8430..5fc8a1c7 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -46,6 +46,7 @@ #include "albit.h" #include "alnumeric.h" +#include "alspan.h" #include "comptr.h" #include "core/device.h" #include "core/helpers.h" @@ -130,10 +131,10 @@ struct DevMap { { } }; -al::vector PlaybackDevices; -al::vector CaptureDevices; +std::vector PlaybackDevices; +std::vector CaptureDevices; -bool checkName(const al::vector &list, const std::string &name) +bool checkName(const al::span list, const std::string &name) { auto match_name = [&name](const DevMap &entry) -> bool { return entry.name == name; }; @@ -145,7 +146,7 @@ BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR*, voi if(!guid) return TRUE; - auto& devices = *static_cast*>(data); + auto& devices = *static_cast*>(data); const std::string basename{DEVNAME_HEAD + wstr_to_utf8(desc)}; int count{1}; diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp index b12edf9f..9e023e21 100644 --- a/alc/backends/jack.cpp +++ b/alc/backends/jack.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "albit.h" #include "alc/alconfig.h" @@ -168,10 +169,10 @@ struct DeviceEntry { { } }; -al::vector PlaybackList; +std::vector PlaybackList; -void EnumerateDevices(jack_client_t *client, al::vector &list) +void EnumerateDevices(jack_client_t *client, std::vector &list) { std::remove_reference_t{}.swap(list); diff --git a/alc/backends/oss.cpp b/alc/backends/oss.cpp index 1fdee701..dc18c4c3 100644 --- a/alc/backends/oss.cpp +++ b/alc/backends/oss.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include "alc/alconfig.h" #include "almalloc.h" @@ -47,7 +48,6 @@ #include "core/logging.h" #include "ringbuffer.h" #include "threads.h" -#include "vector.h" #include @@ -88,22 +88,22 @@ struct DevMap { std::string device_name; }; -al::vector PlaybackDevices; -al::vector CaptureDevices; +std::vector PlaybackDevices; +std::vector CaptureDevices; #ifdef ALC_OSS_COMPAT #define DSP_CAP_OUTPUT 0x00020000 #define DSP_CAP_INPUT 0x00010000 -void ALCossListPopulate(al::vector &devlist, int type) +void ALCossListPopulate(std::vector &devlist, int type) { devlist.emplace_back(DevMap{DefaultName, (type==DSP_CAP_INPUT) ? DefaultCapture : DefaultPlayback}); } #else -void ALCossListAppend(al::vector &list, al::span handle, al::span path) +void ALCossListAppend(std::vector &list, al::span handle, al::span path) { #ifdef ALC_OSS_DEVNODE_TRUC for(size_t i{0};i < path.size();++i) @@ -148,7 +148,7 @@ void ALCossListAppend(al::vector &list, al::span handle, al: TRACE("Got device \"%s\", \"%s\"\n", entry.name.c_str(), entry.device_name.c_str()); } -void ALCossListPopulate(al::vector &devlist, int type_flag) +void ALCossListPopulate(std::vector &devlist, int type_flag) { int fd{open("/dev/mixer", O_RDONLY)}; if(fd < 0) @@ -234,7 +234,7 @@ struct OSSPlayback final : public BackendBase { int mFd{-1}; - al::vector mMixData; + std::vector mMixData; std::atomic mKillNow{true}; std::thread mThread; diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index e5696817..d2883f5c 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include "albit.h" #include "alc/alconfig.h" @@ -49,7 +50,6 @@ #include "dynload.h" #include "opthelpers.h" #include "strutils.h" -#include "vector.h" #include @@ -282,8 +282,8 @@ bool checkName(const al::span list, const std::string &name) return std::find_if(list.cbegin(), list.cend(), match_name) != list.cend(); } -al::vector PlaybackDevices; -al::vector CaptureDevices; +std::vector PlaybackDevices; +std::vector CaptureDevices; /* Global flags and properties */ diff --git a/alc/backends/solaris.cpp b/alc/backends/solaris.cpp index 4eeeafac..ae87e7eb 100644 --- a/alc/backends/solaris.cpp +++ b/alc/backends/solaris.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,6 @@ #include "core/helpers.h" #include "core/logging.h" #include "threads.h" -#include "vector.h" #include @@ -70,7 +70,7 @@ struct SolarisBackend final : public BackendBase { int mFd{-1}; uint mFrameStep{}; - al::vector mBuffer; + std::vector mBuffer; std::atomic mKillNow{true}; std::thread mThread; diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 97f0a291..d4ad38e2 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -59,6 +59,7 @@ #include "albit.h" #include "alc/alconfig.h" #include "alnumeric.h" +#include "alspan.h" #include "comptr.h" #include "core/converter.h" #include "core/device.h" @@ -180,15 +181,14 @@ struct DevMap { { } }; -bool checkName(const al::vector &list, const std::string &name) +bool checkName(const al::span list, const std::string &name) { - auto match_name = [&name](const DevMap &entry) -> bool - { return entry.name == name; }; + auto match_name = [&name](const DevMap &entry) -> bool { return entry.name == name; }; return std::find_if(list.cbegin(), list.cend(), match_name) != list.cend(); } -al::vector PlaybackDevices; -al::vector CaptureDevices; +std::vector PlaybackDevices; +std::vector CaptureDevices; using NameGUIDPair = std::pair; @@ -262,7 +262,7 @@ EndpointFormFactor get_device_formfactor(IMMDevice *device) } -void add_device(IMMDevice *device, const WCHAR *devid, al::vector &list) +void add_device(IMMDevice *device, const WCHAR *devid, std::vector &list) { for(auto &entry : list) { @@ -301,9 +301,9 @@ WCHAR *get_device_id(IMMDevice *device) return devid; } -void probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, al::vector &list) +void probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, std::vector &list) { - al::vector{}.swap(list); + std::vector{}.swap(list); ComPtr coll; HRESULT hr{devenum->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, al::out_ptr(coll))}; @@ -1355,7 +1355,7 @@ FORCE_ALIGN int WasapiCapture::recordProc() althrd_setname(RECORD_THREAD_NAME); - al::vector samples; + std::vector samples; while(!mKillNow.load(std::memory_order_relaxed)) { UINT32 avail; diff --git a/alc/backends/wave.cpp b/alc/backends/wave.cpp index f8302f1e..1ee2fe51 100644 --- a/alc/backends/wave.cpp +++ b/alc/backends/wave.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "albit.h" #include "alc/alconfig.h" @@ -43,7 +44,6 @@ #include "opthelpers.h" #include "strutils.h" #include "threads.h" -#include "vector.h" namespace { @@ -104,7 +104,7 @@ struct WaveBackend final : public BackendBase { FILE *mFile{nullptr}; long mDataStart{-1}; - al::vector mBuffer; + std::vector mBuffer; std::atomic mKillNow{true}; std::thread mThread; diff --git a/alc/backends/winmm.cpp b/alc/backends/winmm.cpp index edb875a0..0345fe10 100644 --- a/alc/backends/winmm.cpp +++ b/alc/backends/winmm.cpp @@ -58,7 +58,7 @@ namespace { std::vector PlaybackDevices; std::vector CaptureDevices; -bool checkName(const al::vector &list, const std::string &name) +bool checkName(const std::vector &list, const std::string &name) { return std::find(list.cbegin(), list.cend(), name) != list.cend(); } void ProbePlaybackDevices(void) diff --git a/alc/context.h b/alc/context.h index acbb3788..779be113 100644 --- a/alc/context.h +++ b/alc/context.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "AL/al.h" #include "AL/alc.h" @@ -21,7 +22,6 @@ #include "core/context.h" #include "inprogext.h" #include "intrusive_ptr.h" -#include "vector.h" #ifdef ALSOFT_EAX #include "al/eax/call.h" @@ -132,11 +132,11 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { ALlistener mListener{}; - al::vector mSourceList; + std::vector mSourceList; ALuint mNumSources{0}; std::mutex mSourceLock; - al::vector mEffectSlotList; + std::vector mEffectSlotList; ALuint mNumEffectSlots{0u}; std::mutex mEffectSlotLock; diff --git a/alc/device.h b/alc/device.h index d5e82ce3..1274e287 100644 --- a/alc/device.h +++ b/alc/device.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "AL/alc.h" #include "AL/alext.h" @@ -18,7 +19,6 @@ #include "core/device.h" #include "inprogext.h" #include "intrusive_ptr.h" -#include "vector.h" #ifdef ALSOFT_EAX #include "al/eax/x_ram.h" @@ -95,7 +95,7 @@ struct ALCdevice : public al::intrusive_ref, DeviceBase { uint AuxiliaryEffectSlotMax{}; std::string mHrtfName; - al::vector mHrtfList; + std::vector mHrtfList; ALCenum mHrtfStatus{ALC_FALSE}; enum class OutputMode1 : ALCenum { @@ -118,15 +118,15 @@ struct ALCdevice : public al::intrusive_ref, DeviceBase { // Map of Buffers for this device std::mutex BufferLock; - al::vector BufferList; + std::vector BufferList; // Map of Effects for this device std::mutex EffectLock; - al::vector EffectList; + std::vector EffectList; // Map of Filters for this device std::mutex FilterLock; - al::vector FilterList; + std::vector FilterList; #ifdef ALSOFT_EAX ALuint eax_x_ram_free_size{eax_x_ram_max_size}; diff --git a/alc/effects/chorus.cpp b/alc/effects/chorus.cpp index 10ccf9f6..7c281aa5 100644 --- a/alc/effects/chorus.cpp +++ b/alc/effects/chorus.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "alc/effects/base.h" #include "almalloc.h" @@ -41,7 +42,6 @@ #include "core/resampler_limits.h" #include "intrusive_ptr.h" #include "opthelpers.h" -#include "vector.h" namespace { @@ -49,7 +49,7 @@ namespace { using uint = unsigned int; struct ChorusState final : public EffectState { - al::vector mDelayBuffer; + std::vector mDelayBuffer; uint mOffset{0}; uint mLfoOffset{0}; diff --git a/alc/effects/echo.cpp b/alc/effects/echo.cpp index a69529dc..7824c246 100644 --- a/alc/effects/echo.cpp +++ b/alc/effects/echo.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "alc/effects/base.h" #include "almalloc.h" @@ -39,7 +40,6 @@ #include "core/mixer.h" #include "intrusive_ptr.h" #include "opthelpers.h" -#include "vector.h" namespace { @@ -49,7 +49,7 @@ using uint = unsigned int; constexpr float LowpassFreqRef{5000.0f}; struct EchoState final : public EffectState { - al::vector mSampleBuffer; + std::vector mSampleBuffer; // The echo is two tap. The delay is the number of samples from before the // current offset @@ -87,7 +87,7 @@ void EchoState::deviceUpdate(const DeviceBase *Device, const BufferStorage*) const uint maxlen{NextPowerOf2(float2uint(EchoMaxDelay*frequency + 0.5f) + float2uint(EchoMaxLRDelay*frequency + 0.5f))}; if(maxlen != mSampleBuffer.size()) - al::vector(maxlen).swap(mSampleBuffer); + decltype(mSampleBuffer)(maxlen).swap(mSampleBuffer); std::fill(mSampleBuffer.begin(), mSampleBuffer.end(), 0.0f); for(auto &e : mGains) diff --git a/alc/panning.cpp b/alc/panning.cpp index 60ce7ca4..6fc955ee 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include "AL/al.h" #include "AL/alc.h" @@ -628,7 +629,7 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= const size_t ambicount{decoder.mIs3D ? AmbiChannelsFromOrder(decoder.mOrder) : Ambi2DChannelsFromOrder(decoder.mOrder)}; const bool dual_band{hqdec && !decoder.mCoeffsLF.empty()}; - al::vector chancoeffs, chancoeffslf; + std::vector chancoeffs, chancoeffslf; for(size_t i{0u};i < decoder.mChannels.size();++i) { const uint idx{device->channelIdxByName(decoder.mChannels[i])}; diff --git a/core/bformatdec.h b/core/bformatdec.h index 7a27a5a4..42024bd9 100644 --- a/core/bformatdec.h +++ b/core/bformatdec.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "almalloc.h" #include "alspan.h" @@ -11,7 +12,6 @@ #include "bufferline.h" #include "devformat.h" #include "filters/splitter.h" -#include "vector.h" struct FrontStablizer; @@ -43,7 +43,7 @@ class BFormatDec { * only be used in a standard layout struct, and a std::unique_ptr member * (mStablizer) causes GCC and Clang to warn it's not. */ - al::vector mChannelDec; + std::vector mChannelDec; public: BFormatDec(const size_t inchans, const al::span coeffs, diff --git a/core/hrtf.cpp b/core/hrtf.cpp index 607e3d3d..7d11ee19 100644 --- a/core/hrtf.cpp +++ b/core/hrtf.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "albit.h" #include "alfstream.h" @@ -34,7 +35,6 @@ #include "mixer/hrtfdefs.h" #include "opthelpers.h" #include "polyphase_resampler.h" -#include "vector.h" namespace { @@ -98,10 +98,10 @@ constexpr char magicMarker03[8]{'M','i','n','P','H','R','0','3'}; constexpr auto PassthruCoeff = static_cast(1.0/al::numbers::sqrt2); std::mutex LoadedHrtfLock; -al::vector LoadedHrtfs; +std::vector LoadedHrtfs; std::mutex EnumeratedHrtfLock; -al::vector EnumeratedHrtfs; +std::vector EnumeratedHrtfs; class databuf final : public std::streambuf { @@ -295,7 +295,7 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const uint irSize, const bool } uint min_delay{HrtfHistoryLength*HrirDelayFracOne}, max_delay{0}; - al::vector impres; impres.reserve(AmbiPoints.size()); + std::vector impres; impres.reserve(AmbiPoints.size()); auto calc_res = [Hrtf,&max_delay,&min_delay](const AngularPoint &pt) -> ImpulseResponse { auto &field = Hrtf->mFields[0]; @@ -331,7 +331,7 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const uint irSize, const bool TRACE("Min delay: %.2f, max delay: %.2f, FIR length: %u\n", min_delay/double{HrirDelayFracOne}, max_delay/double{HrirDelayFracOne}, irSize); - auto tmpres = al::vector>(mChannels.size()); + auto tmpres = std::vector>(mChannels.size()); max_delay = 0; for(size_t c{0u};c < AmbiPoints.size();++c) { @@ -529,7 +529,7 @@ std::unique_ptr LoadHrtf00(std::istream &data, const char *filename) return nullptr; } - auto elevs = al::vector(evCount); + auto elevs = std::vector(evCount); for(auto &elev : elevs) elev.irOffset = readle(data); if(!data || data.eof()) @@ -571,8 +571,8 @@ std::unique_ptr LoadHrtf00(std::istream &data, const char *filename) return nullptr; } - auto coeffs = al::vector(irCount, HrirArray{}); - auto delays = al::vector(irCount); + auto coeffs = std::vector(irCount, HrirArray{}); + auto delays = std::vector(irCount); for(auto &hrir : coeffs) { for(auto &val : al::span{hrir.data(), irSize}) @@ -626,7 +626,7 @@ std::unique_ptr LoadHrtf01(std::istream &data, const char *filename) return nullptr; } - auto elevs = al::vector(evCount); + auto elevs = std::vector(evCount); for(auto &elev : elevs) elev.azCount = readle(data); if(!data || data.eof()) @@ -649,8 +649,8 @@ std::unique_ptr LoadHrtf01(std::istream &data, const char *filename) elevs[i].irOffset = static_cast(elevs[i-1].irOffset + elevs[i-1].azCount); const ushort irCount{static_cast(elevs.back().irOffset + elevs.back().azCount)}; - auto coeffs = al::vector(irCount, HrirArray{}); - auto delays = al::vector(irCount); + auto coeffs = std::vector(irCount, HrirArray{}); + auto delays = std::vector(irCount); for(auto &hrir : coeffs) { for(auto &val : al::span{hrir.data(), irSize}) @@ -722,8 +722,8 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) return nullptr; } - auto fields = al::vector(fdCount); - auto elevs = al::vector{}; + auto fields = std::vector(fdCount); + auto elevs = std::vector{}; for(size_t f{0};f < fdCount;f++) { const ushort distance{readle(data)}; @@ -787,8 +787,8 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) }); const auto irTotal = static_cast(elevs.back().azCount + elevs.back().irOffset); - auto coeffs = al::vector(irTotal, HrirArray{}); - auto delays = al::vector(irTotal); + auto coeffs = std::vector(irTotal, HrirArray{}); + auto delays = std::vector(irTotal); if(channelType == ChanType_LeftOnly) { if(sampleType == SampleType_S16) @@ -881,10 +881,10 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) if(fdCount > 1) { - auto fields_ = al::vector(fields.size()); - auto elevs_ = al::vector(elevs.size()); - auto coeffs_ = al::vector(coeffs.size()); - auto delays_ = al::vector(delays.size()); + auto fields_ = std::vector(fields.size()); + auto elevs_ = std::vector(elevs.size()); + auto coeffs_ = std::vector(coeffs.size()); + auto delays_ = std::vector(delays.size()); /* Simple reverse for the per-field elements. */ std::reverse_copy(fields.cbegin(), fields.cend(), fields_.begin()); @@ -983,8 +983,8 @@ std::unique_ptr LoadHrtf03(std::istream &data, const char *filename) return nullptr; } - auto fields = al::vector(fdCount); - auto elevs = al::vector{}; + auto fields = std::vector(fdCount); + auto elevs = std::vector{}; for(size_t f{0};f < fdCount;f++) { const ushort distance{readle(data)}; @@ -1048,8 +1048,8 @@ std::unique_ptr LoadHrtf03(std::istream &data, const char *filename) }); const auto irTotal = static_cast(elevs.back().azCount + elevs.back().irOffset); - auto coeffs = al::vector(irTotal, HrirArray{}); - auto delays = al::vector(irTotal); + auto coeffs = std::vector(irTotal, HrirArray{}); + auto delays = std::vector(irTotal); if(channelType == ChanType_LeftOnly) { for(auto &hrir : coeffs) @@ -1221,7 +1221,7 @@ al::span GetResource(int name) } // namespace -al::vector EnumerateHrtf(std::optional pathopt) +std::vector EnumerateHrtf(std::optional pathopt) { std::lock_guard _{EnumeratedHrtfLock}; EnumeratedHrtfs.clear(); @@ -1270,7 +1270,7 @@ al::vector EnumerateHrtf(std::optional pathopt) AddBuiltInEntry("Built-In HRTF", IDR_DEFAULT_HRTF_MHR); } - al::vector list; + std::vector list; list.reserve(EnumeratedHrtfs.size()); for(auto &entry : EnumeratedHrtfs) list.emplace_back(entry.mDispName); @@ -1394,7 +1394,7 @@ HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate) /* Scale the delays for the new sample rate. */ float max_delay{0.0f}; - auto new_delays = al::vector(irCount); + auto new_delays = std::vector(irCount); const float rate_scale{static_cast(devrate)/static_cast(hrtf->mSampleRate)}; for(size_t i{0};i < irCount;++i) { diff --git a/core/hrtf.h b/core/hrtf.h index 7215711b..5e6e09a8 100644 --- a/core/hrtf.h +++ b/core/hrtf.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "almalloc.h" #include "alspan.h" @@ -14,7 +15,6 @@ #include "bufferline.h" #include "mixer/hrtfdefs.h" #include "intrusive_ptr.h" -#include "vector.h" struct HrtfStore { @@ -83,7 +83,7 @@ struct DirectHrtfState { }; -al::vector EnumerateHrtf(std::optional pathopt); +std::vector EnumerateHrtf(std::optional pathopt); HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate); #endif /* CORE_HRTF_H */ diff --git a/core/logging.cpp b/core/logging.cpp index 8e0116ea..34385cf4 100644 --- a/core/logging.cpp +++ b/core/logging.cpp @@ -6,10 +6,10 @@ #include #include #include +#include #include "alspan.h" #include "strutils.h" -#include "vector.h" #if defined(_WIN32) @@ -34,7 +34,7 @@ void al_print(LogLevel level, FILE *logfile, const char *fmt, ...) case LogLevel::Trace: prefix = al::span{"[ALSOFT] (II) "}.first<14>(); break; } - al::vector dynmsg; + std::vector dynmsg; std::array stcmsg{}; char *str{stcmsg.data()}; -- cgit v1.2.3 From 54ce34ba9901b3d7ad231a49587f60918e45ac90 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 13 May 2023 22:33:19 -0700 Subject: Declare "direct" context functions for a future extension These functions will allow making AL calls using the specified context, rather than having to set a "current" context for subsequent AL calls to use. --- alc/inprogext.h | 315 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) (limited to 'alc') diff --git a/alc/inprogext.h b/alc/inprogext.h index b39eaa58..2d7da9b2 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -111,6 +111,321 @@ ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALe #endif +#ifndef AL_EXT_direct_context +#define AL_EXT_direct_context +typedef void (AL_APIENTRY *LPALENABLEDIRECT)(ALCcontext *context, ALenum capability); +typedef void (AL_APIENTRY *LPALDISABLEDIRECT)(ALCcontext *context, ALenum capability); +typedef ALboolean (AL_APIENTRY *LPALISENABLEDDIRECT)(ALCcontext *context, ALenum capability); +typedef void (AL_APIENTRY *LPALDOPPLERFACTORDIRECT)(ALCcontext *context, ALfloat value); +typedef void (AL_APIENTRY *LPALSPEEDOFSOUNDDIRECT)(ALCcontext *context, ALfloat value); +typedef void (AL_APIENTRY *LPALDISTANCEMODELDIRECT)(ALCcontext *context, ALenum distanceModel); +typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGDIRECT)(ALCcontext *context, ALenum param); +typedef void (AL_APIENTRY *LPALGETBOOLEANVDIRECT)(ALCcontext *context, ALenum param, ALboolean *values); +typedef void (AL_APIENTRY *LPALGETINTEGERVDIRECT)(ALCcontext *context, ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALGETFLOATVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETDOUBLEVDIRECT)(ALCcontext *context, ALenum param, ALdouble *values); +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEANDIRECT)(ALCcontext *context, ALenum param); +typedef ALint (AL_APIENTRY *LPALGETINTEGERDIRECT)(ALCcontext *context, ALenum param); +typedef ALfloat (AL_APIENTRY *LPALGETFLOATDIRECT)(ALCcontext *context, ALenum param); +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLEDIRECT)(ALCcontext *context, ALenum param); +typedef ALenum (AL_APIENTRY *LPALGETERRORDIRECT)(ALCcontext *context); +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENTDIRECT)(ALCcontext *context, const ALchar *extname); +typedef void* (AL_APIENTRY *LPALGETPROCADDRESSDIRECT)(ALCcontext *context, const ALchar *fname); +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUEDIRECT)(ALCcontext *context, const ALchar *ename); +typedef void (AL_APIENTRY *LPALLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +typedef void (AL_APIENTRY *LPALLISTENERFVDIRECT)(ALCcontext *context, ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3); +typedef void (AL_APIENTRY *LPALLISTENERIVDIRECT)(ALCcontext *context, ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALGETLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +typedef void (AL_APIENTRY *LPALGETLISTENERFVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3); +typedef void (AL_APIENTRY *LPALGETLISTENERIVDIRECT)(ALCcontext *context, ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALGENSOURCESDIRECT)(ALCcontext *context, ALsizei n, ALuint *sources); +typedef void (AL_APIENTRY *LPALDELETESOURCESDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources); +typedef ALboolean (AL_APIENTRY *LPALISSOURCEDIRECT)(ALCcontext *context, ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +typedef void (AL_APIENTRY *LPALSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); +typedef void (AL_APIENTRY *LPALSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALGETSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +typedef void (AL_APIENTRY *LPALGETSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); +typedef void (AL_APIENTRY *LPALGETSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALSOURCEPLAYVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCESTOPVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCEREWINDVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCEPAUSEVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCEPLAYDIRECT)(ALCcontext *context, ALuint source); +typedef void (AL_APIENTRY *LPALSOURCESTOPDIRECT)(ALCcontext *context, ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEREWINDDIRECT)(ALCcontext *context, ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEPAUSEDIRECT)(ALCcontext *context, ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers); +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers); +typedef void (AL_APIENTRY *LPALGENBUFFERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *buffers); +typedef void (AL_APIENTRY *LPALDELETEBUFFERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers); +typedef ALboolean (AL_APIENTRY *LPALISBUFFERDIRECT)(ALCcontext *context, ALuint buffer); +typedef void (AL_APIENTRY *LPALBUFFERDATADIRECT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate); +typedef void (AL_APIENTRY *LPALBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +typedef void (AL_APIENTRY *LPALBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); +typedef void (AL_APIENTRY *LPALBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALGETBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +typedef void (AL_APIENTRY *LPALGETBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); +typedef void (AL_APIENTRY *LPALGETBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *values); +/* ALC_EXT_EFX */ +typedef void (AL_APIENTRY *LPALGENEFFECTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effects); +typedef void (AL_APIENTRY *LPALDELETEEFFECTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effects); +typedef ALboolean (AL_APIENTRY *LPALISEFFECTDIRECT)(ALCcontext *context, ALuint effect); +typedef void (AL_APIENTRY *LPALEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALGETEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALGETEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGENFILTERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *filters); +typedef void (AL_APIENTRY *LPALDELETEFILTERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *filters); +typedef ALboolean (AL_APIENTRY *LPALISFILTERDIRECT)(ALCcontext *context, ALuint filter); +typedef void (AL_APIENTRY *LPALFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALGETFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALGETFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effectslots); +typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effectslots); +typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOTDIRECT)(ALCcontext *context, ALuint effectslot); +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *values); +/* AL_EXT_BUFFER_DATA_STATIC */ +typedef void (AL_APIENTRY *LPALBUFFERDATASTATICDIRECT)(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq); +/* AL_SOFT_buffer_sub_data */ +typedef void (AL_APIENTRY *LPALBUFFERSUBDATADIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length); +/* AL_EXT_FOLDBACK */ +typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTARTDIRECT)(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback); +typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTOPDIRECT)(ALCcontext *context); +/* AL_SOFT_source_latency */ +typedef void (AL_APIENTRY *LPALSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble); +typedef void (AL_APIENTRY *LPALSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble,ALdouble,ALdouble); +typedef void (AL_APIENTRY *LPALSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALdouble*); +typedef void (AL_APIENTRY *LPALGETSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*); +typedef void (AL_APIENTRY *LPALGETSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*); +typedef void (AL_APIENTRY *LPALGETSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*); +typedef void (AL_APIENTRY *LPALSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT); +typedef void (AL_APIENTRY *LPALSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT); +typedef void (AL_APIENTRY *LPALSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALint64SOFT*); +typedef void (AL_APIENTRY *LPALGETSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*); +typedef void (AL_APIENTRY *LPALGETSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*); +typedef void (AL_APIENTRY *LPALGETSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*); +/* AL_SOFT_deferred_updates */ +typedef void (AL_APIENTRY *LPALDEFERUPDATESDIRECTSOFT)(ALCcontext *context); +typedef void (AL_APIENTRY *LPALPROCESSUPDATESDIRECTSOFT)(ALCcontext *context); +/* AL_SOFT_source_resampler */ +typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGIDIRECTSOFT)(ALCcontext *context, ALenum pname, ALsizei index); +/* AL_SOFT_events */ +typedef void (AL_APIENTRY *LPALEVENTCONTROLDIRECTSOFT)(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable); +typedef void (AL_APIENTRY *LPALEVENTCALLBACKDIRECTSOFT)(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam); +typedef void* (AL_APIENTRY *LPALGETPOINTERDIRECTSOFT)(ALCcontext *context, ALenum pname); +typedef void (AL_APIENTRY *LPALGETPOINTERVDIRECTSOFT)(ALCcontext *context, ALenum pname, void **values); +/* AL_SOFT_callback_buffer */ +typedef void (AL_APIENTRY *LPALBUFFERCALLBACKDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); +typedef void (AL_APIENTRY *LPALGETBUFFERPTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value); +typedef void (AL_APIENTRY *LPALGETBUFFER3PTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3); +typedef void (AL_APIENTRY *LPALGETBUFFERPTRVDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **values); +/* AL_SOFT_source_start_delay */ +typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEDIRECTSOFT)(ALCcontext *context, ALuint source, ALint64SOFT start_time); +typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEVDIRECTSOFT)(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time); +/* EAX */ +typedef ALenum (AL_APIENTRY *LPEAXSETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_buffer, ALuint property_size); +typedef ALenum (AL_APIENTRY *LPEAXGETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size); +typedef ALboolean (AL_APIENTRY *LPEAXSETBUFFERMODEDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value); +typedef ALenum (AL_APIENTRY *LPEAXGETBUFFERMODEDIRECT)(ALCcontext *context, ALuint buffer, ALint *pReserved); +#ifdef AL_ALEXT_PROTOTYPES +void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) noexcept; +void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability) noexcept; +ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability) noexcept; + +void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value) noexcept; +void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value) noexcept; +void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum distanceModel) noexcept; + +const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALenum param) noexcept; +void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum param, ALboolean *values) noexcept; +void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum param, ALint *values) noexcept; +void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum param, ALfloat *values) noexcept; +void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum param, ALdouble *values) noexcept; +ALboolean AL_APIENTRY alGetBooleanDirect(ALCcontext *context, ALenum param) noexcept; +ALint AL_APIENTRY alGetIntegerDirect(ALCcontext *context, ALenum param) noexcept; +ALfloat AL_APIENTRY alGetFloatDirect(ALCcontext *context, ALenum param) noexcept; +ALdouble AL_APIENTRY alGetDoubleDirect(ALCcontext *context, ALenum param) noexcept; + +ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) noexcept; +ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extname) noexcept; +void* AL_APIENTRY alGetProcAddressDirect(ALCcontext *context, const ALchar *fname) noexcept; +ALenum AL_APIENTRY alGetEnumValueDirect(ALCcontext *context, const ALchar *ename) noexcept; + +void AL_APIENTRY alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value) noexcept; +void AL_APIENTRY alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) noexcept; +void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum param, const ALfloat *values) noexcept; +void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint value) noexcept; +void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) noexcept; +void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum param, const ALint *values) noexcept; +void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum param, ALfloat *value) noexcept; +void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept; +void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum param, ALfloat *values) noexcept; +void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value) noexcept; +void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) noexcept; +void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum param, ALint *values) noexcept; + +void AL_APIENTRY alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources) noexcept; +void AL_APIENTRY alDeleteSourcesDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept; +ALboolean AL_APIENTRY alIsSourceDirect(ALCcontext *context, ALuint source) noexcept; +void AL_APIENTRY alSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value) noexcept; +void AL_APIENTRY alSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) noexcept; +void AL_APIENTRY alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) noexcept; +void AL_APIENTRY alSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint value) noexcept; +void AL_APIENTRY alSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) noexcept; +void AL_APIENTRY alSourceivDirect(ALCcontext *context, ALuint source, ALenum param, const ALint *values) noexcept; +void AL_APIENTRY alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) noexcept; +void AL_APIENTRY alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept; +void AL_APIENTRY alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) noexcept; +void AL_APIENTRY alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value) noexcept; +void AL_APIENTRY alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) noexcept; +void AL_APIENTRY alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param, ALint *values) noexcept; +void AL_APIENTRY alSourcePlayDirect(ALCcontext *context, ALuint source) noexcept; +void AL_APIENTRY alSourceStopDirect(ALCcontext *context, ALuint source) noexcept; +void AL_APIENTRY alSourceRewindDirect(ALCcontext *context, ALuint source) noexcept; +void AL_APIENTRY alSourcePauseDirect(ALCcontext *context, ALuint source) noexcept; +void AL_APIENTRY alSourcePlayvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept; +void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept; +void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept; +void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept; +void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) noexcept; +void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) noexcept; + +void AL_APIENTRY alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers) noexcept; +void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei n, const ALuint *buffers) noexcept; +ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint buffer) noexcept; +void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) noexcept; +void AL_APIENTRY alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) noexcept; +void AL_APIENTRY alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) noexcept; +void AL_APIENTRY alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) noexcept; +void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value) noexcept; +void AL_APIENTRY alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) noexcept; +void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) noexcept; +void AL_APIENTRY alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) noexcept; +void AL_APIENTRY alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept; +void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) noexcept; +void AL_APIENTRY alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) noexcept; +void AL_APIENTRY alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) noexcept; +void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) noexcept; + +void AL_APIENTRY alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects) noexcept; +void AL_APIENTRY alDeleteEffectsDirect(ALCcontext *context, ALsizei n, const ALuint *effects) noexcept; +ALboolean AL_APIENTRY alIsEffectDirect(ALCcontext *context, ALuint effect) noexcept; +void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint iValue) noexcept; +void AL_APIENTRY alEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, const ALint *piValues) noexcept; +void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat flValue) noexcept; +void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *pflValues) noexcept; +void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValue) noexcept; +void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValues) noexcept; +void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValue) noexcept; +void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValues) noexcept; + +void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) noexcept; +void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei n, const ALuint *filters) noexcept; +ALboolean AL_APIENTRY alIsFilterDirect(ALCcontext *context, ALuint filter) noexcept; +void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint iValue) noexcept; +void AL_APIENTRY alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, const ALint *piValues) noexcept; +void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat flValue) noexcept; +void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *pflValues) noexcept; +void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValue) noexcept; +void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValues) noexcept; +void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValue) noexcept; +void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValues) noexcept; + +void AL_APIENTRY alGenAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, ALuint *effectslots) noexcept; +void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, const ALuint *effectslots) noexcept; +ALboolean AL_APIENTRY alIsAuxiliaryEffectSlotDirect(ALCcontext *context, ALuint effectslot) noexcept; +void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint iValue) noexcept; +void AL_APIENTRY alAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *piValues) noexcept; +void AL_APIENTRY alAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat flValue) noexcept; +void AL_APIENTRY alAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *pflValues) noexcept; +void AL_APIENTRY alGetAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValue) noexcept; +void AL_APIENTRY alGetAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValues) noexcept; +void AL_APIENTRY alGetAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValue) noexcept; +void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValues) noexcept; + +void AL_APIENTRY alBufferDataStaticDirect(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) noexcept; + +void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) noexcept; + +void AL_APIENTRY alRequestFoldbackStartDirect(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) noexcept; +void AL_APIENTRY alRequestFoldbackStopDirect(ALCcontext *context) noexcept; + +void AL_APIENTRY alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value) noexcept; +void AL_APIENTRY alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) noexcept; +void AL_APIENTRY alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALdouble *values) noexcept; +void AL_APIENTRY alGetSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value) noexcept; +void AL_APIENTRY alGetSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) noexcept; +void AL_APIENTRY alGetSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *values) noexcept; +void AL_APIENTRY alSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value) noexcept; +void AL_APIENTRY alSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) noexcept; +void AL_APIENTRY alSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALint64SOFT *values) noexcept; +void AL_APIENTRY alGetSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value) noexcept; +void AL_APIENTRY alGetSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) noexcept; +void AL_APIENTRY alGetSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *values) noexcept; + +ALint64SOFT AL_APIENTRY alGetInteger64DirectSOFT(ALCcontext *context, ALenum pname) noexcept; +void AL_APIENTRY alGetInteger64vDirectSOFT(ALCcontext *context, ALenum pname, ALint64SOFT *values) noexcept; + +void AL_APIENTRY alDeferUpdatesDirectSOFT(ALCcontext *context) noexcept; +void AL_APIENTRY alProcessUpdatesDirectSOFT(ALCcontext *context) noexcept; + +const ALchar* AL_APIENTRY alGetStringiDirectSOFT(ALCcontext *context, ALenum pname, ALsizei index) noexcept; + +void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) noexcept; +void AL_APIENTRY alEventCallbackDirectSOFT(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) noexcept; +void* AL_APIENTRY alGetPointerDirectSOFT(ALCcontext *context, ALenum pname) noexcept; +void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, void **values) noexcept; + +void AL_APIENTRY alBufferCallbackDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) noexcept; +void AL_APIENTRY alGetBufferPtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) noexcept; +void AL_APIENTRY alGetBuffer3PtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2) noexcept; +void AL_APIENTRY alGetBufferPtrvDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) noexcept; + +void AL_APIENTRY alSourcePlayAtTimeDirectSOFT(ALCcontext *context, ALuint source, ALint64SOFT start_time) noexcept; +void AL_APIENTRY alSourcePlayAtTimevDirectSOFT(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) noexcept; + +ALenum AL_APIENTRY EAXSetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept; +ALenum AL_APIENTRY EAXGetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept; +ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) noexcept; +ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, ALint *pReserved) noexcept; +#endif +#endif + /* Non-standard export. Not part of any extension. */ AL_API const ALchar* AL_APIENTRY alsoft_get_version(void); -- cgit v1.2.3 From 6a007660fb7bac51f01ef0b9466bfcc6ade7389b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 14 May 2023 00:55:54 -0700 Subject: Implement direct functions for context state --- CMakeLists.txt | 1 + al/direct_defs.h | 35 +++++++ al/error.cpp | 7 +- al/state.cpp | 279 ++++++++++++++++++++++++------------------------------- alc/alc.cpp | 22 +++++ 5 files changed, 180 insertions(+), 164 deletions(-) create mode 100644 al/direct_defs.h (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index fe46a688..eeef181f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -742,6 +742,7 @@ set(OPENAL_OBJS al/buffer.h al/debug.cpp al/debug.h + al/direct_defs.h al/effect.cpp al/effect.h al/effects/autowah.cpp diff --git a/al/direct_defs.h b/al/direct_defs.h new file mode 100644 index 00000000..555e9565 --- /dev/null +++ b/al/direct_defs.h @@ -0,0 +1,35 @@ +#ifndef AL_DIRECT_DEFS_H +#define AL_DIRECT_DEFS_H + +#define DECL_FUNC(R, Name) \ +R AL_API Name(void) START_API_FUNC \ +{ \ + return Name##Direct(GetContextRef().get()); \ +} END_API_FUNC + +#define DECL_FUNC1(R, Name, T1) \ +R AL_API Name(T1 a) START_API_FUNC \ +{ \ + return Name##Direct(GetContextRef().get(), a); \ +} END_API_FUNC + +#define DECL_FUNC2(R, Name, T1, T2) \ +R AL_API Name(T1 a, T2 b) START_API_FUNC \ +{ \ + return Name##Direct(GetContextRef().get(), a, b); \ +} END_API_FUNC + + +#define DECL_FUNCEXT(R, Name,Ext) \ +R AL_API Name##Ext(void) START_API_FUNC \ +{ \ + return Name##Direct##Ext(GetContextRef().get()); \ +} END_API_FUNC + +#define DECL_FUNCEXT2(R, Name,Ext, T1, T2) \ +R AL_API Name##Ext(T1 a, T2 b) START_API_FUNC \ +{ \ + return Name##Direct##Ext(GetContextRef().get(), a, b); \ +} END_API_FUNC + +#endif /* AL_DIRECT_DEFS_H */ diff --git a/al/error.cpp b/al/error.cpp index b0607d66..e33ee161 100644 --- a/al/error.cpp +++ b/al/error.cpp @@ -41,6 +41,7 @@ #include "almalloc.h" #include "core/except.h" #include "core/logging.h" +#include "direct_defs.h" #include "opthelpers.h" @@ -89,10 +90,9 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...) debugMessage(DebugSource::API, DebugType::Error, 0, DebugSeverity::High, msglen, msg); } -AL_API ALenum AL_APIENTRY alGetError(void) -START_API_FUNC +AL_API DECL_FUNC(ALenum, alGetError) +FORCE_ALIGN ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) noexcept { - ContextRef context{GetContextRef()}; if(!context) UNLIKELY { static constexpr ALenum deferror{AL_INVALID_OPERATION}; @@ -111,4 +111,3 @@ START_API_FUNC return context->mLastError.exchange(AL_NO_ERROR); } -END_API_FUNC diff --git a/al/state.cpp b/al/state.cpp index f749af50..e1b50af0 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -45,6 +45,7 @@ #include "core/except.h" #include "core/mixer/defs.h" #include "core/voice.h" +#include "direct_defs.h" #include "intrusive_ptr.h" #include "opthelpers.h" #include "strutils.h" @@ -303,11 +304,10 @@ START_API_FUNC END_API_FUNC -AL_API void AL_APIENTRY alEnable(ALenum capability) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; switch(capability) { @@ -315,7 +315,7 @@ START_API_FUNC { std::lock_guard _{context->mPropLock}; context->mSourceDistanceModel = true; - UpdateProps(context.get()); + UpdateProps(context); } break; @@ -331,13 +331,11 @@ START_API_FUNC context->setError(AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability); } } -END_API_FUNC -AL_API void AL_APIENTRY alDisable(ALenum capability) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; switch(capability) { @@ -345,7 +343,7 @@ START_API_FUNC { std::lock_guard _{context->mPropLock}; context->mSourceDistanceModel = false; - UpdateProps(context.get()); + UpdateProps(context); } break; @@ -361,13 +359,11 @@ START_API_FUNC context->setError(AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability); } } -END_API_FUNC -AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability) -START_API_FUNC +FORCE_ALIGN ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return AL_FALSE; + if(!context) UNLIKELY + return AL_FALSE; std::lock_guard _{context->mPropLock}; ALboolean value{AL_FALSE}; @@ -391,127 +387,88 @@ START_API_FUNC return value; } -END_API_FUNC - -AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname) -START_API_FUNC -{ - ALboolean value{AL_FALSE}; - alGetBooleanv(pname, &value); - return value; -} -END_API_FUNC -AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname) -START_API_FUNC -{ - ALdouble value{0.0}; - alGetDoublev(pname, &value); - return value; +#define DECL_GETFUNC(R, Name, Ext) \ +AL_API R AL_APIENTRY Name##Ext(ALenum pname) \ +START_API_FUNC \ +{ \ + R value{}; \ + Name##vDirect##Ext(GetContextRef().get(), pname, &value); \ + return value; \ +} \ +END_API_FUNC \ +FORCE_ALIGN R AL_APIENTRY Name##Direct##Ext(ALCcontext *context, ALenum pname) noexcept \ +{ \ + R value{}; \ + Name##vDirect##Ext(context, pname, &value); \ + return value; \ } -END_API_FUNC -AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname) -START_API_FUNC -{ - ALfloat value{0.0f}; - alGetFloatv(pname, &value); - return value; -} -END_API_FUNC +DECL_GETFUNC(ALboolean, alGetBoolean,) +DECL_GETFUNC(ALdouble, alGetDouble,) +DECL_GETFUNC(ALfloat, alGetFloat,) +DECL_GETFUNC(ALint, alGetInteger,) -AL_API ALint AL_APIENTRY alGetInteger(ALenum pname) -START_API_FUNC -{ - ALint value{0}; - alGetIntegerv(pname, &value); - return value; -} -END_API_FUNC +DECL_GETFUNC(ALint64SOFT, alGetInteger64,SOFT) +DECL_GETFUNC(ALvoid*, alGetPointer,SOFT) -AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname) -START_API_FUNC -{ - ALint64SOFT value{0}; - alGetInteger64vSOFT(pname, &value); - return value; -} -END_API_FUNC +#undef DECL_GETFUNC -AL_API ALvoid* AL_APIENTRY alGetPointerSOFT(ALenum pname) -START_API_FUNC -{ - ALvoid *value{nullptr}; - alGetPointervSOFT(pname, &value); - return value; -} -END_API_FUNC -AL_API void AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum pname, ALboolean *values) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(!values) UNLIKELY return context->setError(AL_INVALID_VALUE, "NULL pointer"); - GetValue(context.get(), pname, values); + GetValue(context, pname, values); } -END_API_FUNC -AL_API void AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum pname, ALdouble *values) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(!values) UNLIKELY return context->setError(AL_INVALID_VALUE, "NULL pointer"); - GetValue(context.get(), pname, values); + GetValue(context, pname, values); } -END_API_FUNC -AL_API void AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum pname, ALfloat *values) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(!values) UNLIKELY return context->setError(AL_INVALID_VALUE, "NULL pointer"); - GetValue(context.get(), pname, values); + GetValue(context, pname, values); } -END_API_FUNC -AL_API void AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum pname, ALint *values) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(!values) UNLIKELY return context->setError(AL_INVALID_VALUE, "NULL pointer"); - GetValue(context.get(), pname, values); + GetValue(context, pname, values); } -END_API_FUNC -AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetInteger64vDirectSOFT(ALCcontext *context, ALenum pname, ALint64SOFT *values) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(!values) UNLIKELY return context->setError(AL_INVALID_VALUE, "NULL pointer"); - GetValue(context.get(), pname, values); + GetValue(context, pname, values); } -END_API_FUNC -AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, ALvoid **values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, ALvoid **values) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(!values) UNLIKELY return context->setError(AL_INVALID_VALUE, "NULL pointer"); @@ -538,13 +495,11 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid context pointer property 0x%04x", pname); } } -END_API_FUNC -AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname) -START_API_FUNC +FORCE_ALIGN const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALenum pname) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return nullptr; + if(!context) UNLIKELY + return nullptr; const ALchar *value{nullptr}; switch(pname) @@ -602,13 +557,11 @@ START_API_FUNC } return value; } -END_API_FUNC -AL_API void AL_APIENTRY alDopplerFactor(ALfloat value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(!(value >= 0.0f && std::isfinite(value))) context->setError(AL_INVALID_VALUE, "Doppler factor %f out of range", value); @@ -616,39 +569,14 @@ START_API_FUNC { std::lock_guard _{context->mPropLock}; context->mDopplerFactor = value; - UpdateProps(context.get()); - } -} -END_API_FUNC - -AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) -START_API_FUNC -{ - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; - - if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY - context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, - DebugSeverity::Medium, -1, - "alDopplerVelocity is deprecated in AL 1.1, use alSpeedOfSound; " - "alDopplerVelocity(x) -> alSpeedOfSound(343.3f * x)"); - - if(!(value >= 0.0f && std::isfinite(value))) - context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value); - else - { - std::lock_guard _{context->mPropLock}; - context->mDopplerVelocity = value; - UpdateProps(context.get()); + UpdateProps(context); } } -END_API_FUNC -AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(!(value > 0.0f && std::isfinite(value))) context->setError(AL_INVALID_VALUE, "Speed of sound %f out of range", value); @@ -656,58 +584,50 @@ START_API_FUNC { std::lock_guard _{context->mPropLock}; context->mSpeedOfSound = value; - UpdateProps(context.get()); + UpdateProps(context); } } -END_API_FUNC -AL_API void AL_APIENTRY alDistanceModel(ALenum value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(auto model = DistanceModelFromALenum(value)) { std::lock_guard _{context->mPropLock}; context->mDistanceModel = *model; if(!context->mSourceDistanceModel) - UpdateProps(context.get()); + UpdateProps(context); } else context->setError(AL_INVALID_VALUE, "Distance model 0x%04x out of range", value); } -END_API_FUNC -AL_API void AL_APIENTRY alDeferUpdatesSOFT(void) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alDeferUpdatesDirectSOFT(ALCcontext *context) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mPropLock}; context->deferUpdates(); } -END_API_FUNC -AL_API void AL_APIENTRY alProcessUpdatesSOFT(void) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alProcessUpdatesDirectSOFT(ALCcontext *context) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mPropLock}; context->processUpdates(); } -END_API_FUNC -AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index) -START_API_FUNC +FORCE_ALIGN const ALchar* AL_APIENTRY alGetStringiDirectSOFT(ALCcontext *context, ALenum pname, ALsizei index) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return nullptr; + if(!context) UNLIKELY + return nullptr; const ALchar *value{nullptr}; switch(pname) @@ -724,6 +644,45 @@ START_API_FUNC } return value; } + +AL_API DECL_FUNC1(void, alEnable, ALenum) +AL_API DECL_FUNC1(void, alDisable, ALenum) +AL_API DECL_FUNC1(ALboolean, alIsEnabled, ALenum) +AL_API DECL_FUNC2(void, alGetBooleanv, ALenum, ALboolean*) +AL_API DECL_FUNC2(void, alGetDoublev, ALenum, ALdouble*) +AL_API DECL_FUNC2(void, alGetFloatv, ALenum, ALfloat*) +AL_API DECL_FUNC2(void, alGetIntegerv, ALenum, ALint*) +AL_API DECL_FUNCEXT2(void, alGetInteger64v,SOFT, ALenum, ALint64SOFT*) +AL_API DECL_FUNCEXT2(void, alGetPointerv,SOFT, ALenum, ALvoid**) +AL_API DECL_FUNC1(const ALchar*, alGetString, ALenum) +AL_API DECL_FUNC1(void, alDopplerFactor, ALfloat) +AL_API DECL_FUNC1(void, alSpeedOfSound, ALfloat) +AL_API DECL_FUNC1(void, alDistanceModel, ALenum) +AL_API DECL_FUNCEXT(void, alDeferUpdates,SOFT) +AL_API DECL_FUNCEXT(void, alProcessUpdates,SOFT) +AL_API DECL_FUNCEXT2(const ALchar*, alGetStringi,SOFT, ALenum,ALsizei) + +AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) +START_API_FUNC +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY + context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + DebugSeverity::Medium, -1, + "alDopplerVelocity is deprecated in AL 1.1, use alSpeedOfSound; " + "alDopplerVelocity(x) -> alSpeedOfSound(343.3f * x)"); + + if(!(value >= 0.0f && std::isfinite(value))) + context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value); + else + { + std::lock_guard _{context->mPropLock}; + context->mDopplerVelocity = value; + UpdateProps(context.get()); + } +} END_API_FUNC diff --git a/alc/alc.cpp b/alc/alc.cpp index 9fedee0b..c9a56d90 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -467,6 +467,28 @@ const struct { DECL(alPushDebugGroupEXT), DECL(alPopDebugGroupEXT), DECL(alGetDebugMessageLogEXT), + + /* Direct Context functions */ + DECL(alEnableDirect), + DECL(alDisableDirect), + DECL(alIsEnabledDirect), + DECL(alDopplerFactorDirect), + DECL(alSpeedOfSoundDirect), + DECL(alDistanceModelDirect), + DECL(alGetStringDirect), + DECL(alGetBooleanvDirect), + DECL(alGetIntegervDirect), + DECL(alGetFloatvDirect), + DECL(alGetDoublevDirect), + DECL(alGetBooleanDirect), + DECL(alGetIntegerDirect), + DECL(alGetFloatDirect), + DECL(alGetDoubleDirect), + + DECL(alDeferUpdatesDirectSOFT), + DECL(alProcessUpdatesDirectSOFT), + DECL(alGetStringiDirectSOFT), + #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), -- cgit v1.2.3 From 1b2e5ba854c5c7fa35deb8cfb17f413341596a77 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 14 May 2023 01:27:42 -0700 Subject: Implement direct functions for extension queries and EAX --- al/buffer.cpp | 8 ++++++-- al/extension.cpp | 26 +++++++++++++++++--------- alc/alc.cpp | 10 ++++++++++ alc/context.cpp | 25 +++++++++++-------------- 4 files changed, 44 insertions(+), 25 deletions(-) (limited to 'alc') diff --git a/al/buffer.cpp b/al/buffer.cpp index bfc10906..216c82eb 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -1547,10 +1547,12 @@ BufferSubList::~BufferSubList() #ifdef ALSOFT_EAX FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint *buffers, ALint value) noexcept +{ return EAXSetBufferModeDirect(GetContextRef().get(), n, buffers, value); } +FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, ALsizei n, + const ALuint *buffers, ALint value) noexcept { #define EAX_PREFIX "[EAXSetBufferMode] " - const auto context = ContextRef{GetContextRef()}; if(!context) { ERR(EAX_PREFIX "%s\n", "No current context."); @@ -1688,10 +1690,12 @@ FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint *buff } FORCE_ALIGN ALenum AL_APIENTRY EAXGetBufferMode(ALuint buffer, ALint *pReserved) noexcept +{ return EAXGetBufferModeDirect(GetContextRef().get(), buffer, pReserved); } +FORCE_ALIGN ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, + ALint *pReserved) noexcept { #define EAX_PREFIX "[EAXGetBufferMode] " - const auto context = ContextRef{GetContextRef()}; if(!context) { ERR(EAX_PREFIX "%s\n", "No current context."); diff --git a/al/extension.cpp b/al/extension.cpp index dbaf4d5f..077e3324 100644 --- a/al/extension.cpp +++ b/al/extension.cpp @@ -30,14 +30,15 @@ #include "alc/context.h" #include "alstring.h" #include "core/except.h" +#include "direct_defs.h" #include "opthelpers.h" -AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName) -START_API_FUNC +AL_API DECL_FUNC1(ALboolean, alIsExtensionPresent, const ALchar*) +FORCE_ALIGN ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extName) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return AL_FALSE; + if(!context) UNLIKELY + return AL_FALSE; if(!extName) UNLIKELY { @@ -54,21 +55,28 @@ START_API_FUNC return AL_FALSE; } -END_API_FUNC AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName) -START_API_FUNC { if(!funcName) return nullptr; return alcGetProcAddress(nullptr, funcName); } -END_API_FUNC + +FORCE_ALIGN ALvoid* AL_APIENTRY alGetProcAddressDirect(ALCcontext*, const ALchar *funcName) noexcept +{ + if(!funcName) return nullptr; + return alcGetProcAddress(nullptr, funcName); +} AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName) -START_API_FUNC { if(!enumName) return static_cast(0); return alcGetEnumValue(nullptr, enumName); } -END_API_FUNC + +FORCE_ALIGN ALenum AL_APIENTRY alGetEnumValueDirect(ALCcontext*, const ALchar *enumName) noexcept +{ + if(!enumName) return static_cast(0); + return alcGetEnumValue(nullptr, enumName); +} diff --git a/alc/alc.cpp b/alc/alc.cpp index c9a56d90..23ed101d 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -485,6 +485,11 @@ const struct { DECL(alGetFloatDirect), DECL(alGetDoubleDirect), + DECL(alGetErrorDirect), + DECL(alIsExtensionPresentDirect), + DECL(alGetProcAddress), + DECL(alGetEnumValueDirect), + DECL(alDeferUpdatesDirectSOFT), DECL(alProcessUpdatesDirectSOFT), DECL(alGetStringiDirectSOFT), @@ -495,6 +500,11 @@ const struct { DECL(EAXSet), DECL(EAXGetBufferMode), DECL(EAXSetBufferMode), + + DECL(EAXGetDirect), + DECL(EAXSetDirect), + DECL(EAXGetBufferModeDirect), + DECL(EAXSetBufferModeDirect), #endif }; #undef DECL diff --git a/alc/context.cpp b/alc/context.cpp index d920d4b6..81529adf 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -1049,16 +1049,14 @@ public: } // namespace -FORCE_ALIGN ALenum AL_APIENTRY EAXSet( - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_value, +FORCE_ALIGN ALenum AL_APIENTRY EAXSet(const GUID *property_set_id, ALuint property_id, + ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept +{ return EAXSetDirect(GetContextRef().get(), property_set_id, property_id, property_source_id, property_value, property_value_size); } +FORCE_ALIGN ALenum AL_APIENTRY EAXSetDirect(ALCcontext *context, const GUID *property_set_id, + ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept try { - auto context = GetContextRef(); - if(!context) eax_fail_set("No current context."); @@ -1077,16 +1075,15 @@ catch (...) return AL_INVALID_OPERATION; } -FORCE_ALIGN ALenum AL_APIENTRY EAXGet( - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_value, + +FORCE_ALIGN ALenum AL_APIENTRY EAXGet(const GUID *property_set_id, ALuint property_id, + ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept +{ return EAXGetDirect(GetContextRef().get(), property_set_id, property_id, property_source_id, property_value, property_value_size); } +FORCE_ALIGN ALenum AL_APIENTRY EAXGetDirect(ALCcontext *context, const GUID *property_set_id, + ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept try { - auto context = GetContextRef(); - if(!context) eax_fail_get("No current context."); -- cgit v1.2.3 From f7ab4181ea3353971f02c60d050faae3ee4cc029 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 14 May 2023 14:30:17 -0700 Subject: Implement direct functions for buffers --- al/buffer.cpp | 359 +++++++++++++++++++++++++++---------------------------- al/direct_defs.h | 42 +++++++ alc/inprogext.h | 8 ++ 3 files changed, 228 insertions(+), 181 deletions(-) (limited to 'alc') diff --git a/al/buffer.cpp b/al/buffer.cpp index 216c82eb..291871e5 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -55,6 +55,7 @@ #include "core/except.h" #include "core/logging.h" #include "core/voice.h" +#include "direct_defs.h" #include "opthelpers.h" #ifdef ALSOFT_EAX @@ -635,11 +636,10 @@ std::optional DecomposeUserFormat(ALenum format) } // namespace -AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(n < 0) UNLIKELY context->setError(AL_INVALID_VALUE, "Generating %d buffers", n); @@ -673,13 +673,12 @@ START_API_FUNC std::copy(ids.begin(), ids.end(), buffers); } } -END_API_FUNC -AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei n, + const ALuint *buffers) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(n < 0) UNLIKELY context->setError(AL_INVALID_VALUE, "Deleting %d buffers", n); @@ -717,12 +716,9 @@ START_API_FUNC }; std::for_each(buffers, buffers_end, delete_buffer); } -END_API_FUNC -AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer) -START_API_FUNC +FORCE_ALIGN ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint buffer) noexcept { - ContextRef context{GetContextRef()}; if(context) LIKELY { ALCdevice *device{context->mALDevice.get()}; @@ -732,19 +728,21 @@ START_API_FUNC } return AL_FALSE; } -END_API_FUNC AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) START_API_FUNC -{ alBufferStorageSOFT(buffer, format, data, size, freq, 0); } +{ alBufferStorageDirectSOFT(GetContextRef().get(), buffer, format, data, size, freq, 0); } END_API_FUNC -AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) noexcept +{ alBufferStorageDirectSOFT(context, buffer, format, data, size, freq, 0); } + +FORCE_ALIGN void AL_APIENTRY alBufferStorageDirectSOFT(ALCcontext *context, ALuint buffer, + ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -769,19 +767,17 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); else { - LoadData(context.get(), albuf, freq, static_cast(size), usrfmt->channels, + LoadData(context, albuf, freq, static_cast(size), usrfmt->channels, usrfmt->type, static_cast(data), flags); } } } -END_API_FUNC -FORCE_ALIGN void AL_APIENTRY alBufferDataStatic(const ALuint buffer, ALenum format, ALvoid *data, - ALsizei size, ALsizei freq) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alBufferDataStaticDirect(ALCcontext *context, const ALuint buffer, + ALenum format, ALvoid *data, ALsizei size, ALsizei freq) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -798,16 +794,15 @@ START_API_FUNC if(!usrfmt) UNLIKELY return context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); - PrepareUserPtr(context.get(), albuf, freq, usrfmt->channels, usrfmt->type, + PrepareUserPtr(context, albuf, freq, usrfmt->channels, usrfmt->type, static_cast(data), static_cast(size)); } -END_API_FUNC -AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access) -START_API_FUNC +FORCE_ALIGN void* AL_APIENTRY alMapBufferDirectSOFT(ALCcontext *context, ALuint buffer, + ALsizei offset, ALsizei length, ALbitfieldSOFT access) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return nullptr; + if(!context) UNLIKELY + return nullptr; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -855,13 +850,11 @@ START_API_FUNC return nullptr; } -END_API_FUNC -AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alUnmapBufferDirectSOFT(ALCcontext *context, ALuint buffer) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -878,13 +871,12 @@ START_API_FUNC albuf->MappedSize = 0; } } -END_API_FUNC -AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alFlushMappedBufferDirectSOFT(ALCcontext *context, ALuint buffer, + ALsizei offset, ALsizei length) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -910,13 +902,12 @@ START_API_FUNC std::atomic_thread_fence(std::memory_order_seq_cst); } } -END_API_FUNC -AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, + ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -969,60 +960,13 @@ START_API_FUNC assert(al::to_underlying(usrfmt->type) == al::to_underlying(albuf->mType)); memcpy(albuf->mData.data()+offset, data, static_cast(length)); } -END_API_FUNC -AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint /*buffer*/, ALuint /*samplerate*/, - ALenum /*internalformat*/, ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, - const ALvoid* /*data*/) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, + ALfloat /*value*/) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; - - context->setError(AL_INVALID_OPERATION, "alBufferSamplesSOFT not supported"); -} -END_API_FUNC - -AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint /*buffer*/, ALsizei /*offset*/, - ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, const ALvoid* /*data*/) -START_API_FUNC -{ - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; - - context->setError(AL_INVALID_OPERATION, "alBufferSubSamplesSOFT not supported"); -} -END_API_FUNC - -AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint /*buffer*/, ALsizei /*offset*/, - ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, ALvoid* /*data*/) -START_API_FUNC -{ - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; - - context->setError(AL_INVALID_OPERATION, "alGetBufferSamplesSOFT not supported"); -} -END_API_FUNC - -AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum /*format*/) -START_API_FUNC -{ - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return AL_FALSE; - - context->setError(AL_INVALID_OPERATION, "alIsBufferFormatSupportedSOFT not supported"); - return AL_FALSE; -} -END_API_FUNC - - -AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat /*value*/) -START_API_FUNC -{ - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1035,14 +979,12 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, - ALfloat /*value1*/, ALfloat /*value2*/, ALfloat /*value3*/) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, + ALfloat /*value1*/, ALfloat /*value2*/, ALfloat /*value3*/) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1055,13 +997,12 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, + const ALfloat *values) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1076,14 +1017,13 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, + ALint value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1138,14 +1078,12 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, - ALint /*value1*/, ALint /*value2*/, ALint /*value3*/) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, + ALint /*value1*/, ALint /*value2*/, ALint /*value3*/) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1158,10 +1096,9 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, + const ALint *values) noexcept { if(values) { @@ -1172,13 +1109,13 @@ START_API_FUNC case AL_AMBISONIC_LAYOUT_SOFT: case AL_AMBISONIC_SCALING_SOFT: case AL_UNPACK_AMBISONIC_ORDER_SOFT: - alBufferi(buffer, param, values[0]); + alBufferiDirect(context, buffer, param, values[0]); return; } } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1209,14 +1146,13 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, + ALfloat *value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1237,13 +1173,12 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, + ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1258,20 +1193,19 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, + ALfloat *values) noexcept { switch(param) { case AL_SEC_LENGTH_SOFT: - alGetBufferf(buffer, param, values); + alGetBufferfDirect(context, buffer, param, values); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1286,14 +1220,13 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, + ALint *value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1354,13 +1287,12 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, + ALint *value1, ALint *value2, ALint *value3) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1374,10 +1306,9 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, + ALint *values) noexcept { switch(param) { @@ -1393,12 +1324,12 @@ START_API_FUNC case AL_AMBISONIC_LAYOUT_SOFT: case AL_AMBISONIC_SCALING_SOFT: case AL_UNPACK_AMBISONIC_ORDER_SOFT: - alGetBufferi(buffer, param, values); + alGetBufferiDirect(context, buffer, param, values); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1418,15 +1349,13 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, - ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alBufferCallbackDirectSOFT(ALCcontext *context, ALuint buffer, + ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1444,17 +1373,16 @@ START_API_FUNC if(!usrfmt) UNLIKELY context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); else - PrepareCallback(context.get(), albuf, freq, usrfmt->channels, usrfmt->type, callback, + PrepareCallback(context, albuf, freq, usrfmt->channels, usrfmt->type, callback, userptr); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetBufferPtrDirectSOFT(ALCcontext *context, ALuint buffer, + ALenum param, ALvoid **value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1476,13 +1404,12 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer pointer property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetBuffer3PtrDirectSOFT(ALCcontext *context, ALuint buffer, + ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1496,21 +1423,20 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer 3-pointer property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetBufferPtrvDirectSOFT(ALCcontext *context, ALuint buffer, + ALenum param, ALvoid **values) noexcept { switch(param) { case AL_BUFFER_CALLBACK_FUNCTION_SOFT: case AL_BUFFER_CALLBACK_USER_PARAM_SOFT: - alGetBufferPtrSOFT(buffer, param, values); + alGetBufferPtrDirectSOFT(context, buffer, param, values); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->BufferLock}; @@ -1524,6 +1450,77 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid buffer pointer-vector property 0x%04x", param); } } + + +DECL_FUNC2(void, alGenBuffers, ALsizei, ALuint*) +DECL_FUNC2(void, alDeleteBuffers, ALsizei, const ALuint*) +DECL_FUNC1(ALboolean, alIsBuffer, ALuint) +DECL_FUNC5(void, alBufferDataStatic, ALuint, ALenum, ALvoid*, ALsizei, ALsizei) +DECL_FUNCEXT5(void, alBufferCallback,SOFT, ALuint, ALenum, ALsizei, ALBUFFERCALLBACKTYPESOFT, ALvoid*) +DECL_FUNCEXT6(void, alBufferStorage,SOFT, ALuint, ALenum, const ALvoid*, ALsizei, ALsizei, ALbitfieldSOFT) +DECL_FUNCEXT4(void*, alMapBuffer,SOFT, ALuint, ALsizei, ALsizei, ALbitfieldSOFT) +DECL_FUNCEXT1(void, alUnmapBuffer,SOFT, ALuint) +DECL_FUNCEXT3(void, alFlushMappedBuffer,SOFT, ALuint, ALsizei, ALsizei) +DECL_FUNCEXT5(void, alBufferSubData,SOFT, ALuint, ALenum, const ALvoid*, ALsizei, ALsizei) +DECL_FUNC3(void, alBufferf, ALuint, ALenum, ALfloat) +DECL_FUNC5(void, alBuffer3f, ALuint, ALenum, ALfloat, ALfloat, ALfloat) +DECL_FUNC3(void, alBufferfv, ALuint, ALenum, const ALfloat*) +DECL_FUNC3(void, alBufferi, ALuint, ALenum, ALint) +DECL_FUNC5(void, alBuffer3i, ALuint, ALenum, ALint, ALint, ALint) +DECL_FUNC3(void, alBufferiv, ALuint, ALenum, const ALint*) +DECL_FUNC3(void, alGetBufferf, ALuint, ALenum, ALfloat*) +DECL_FUNC5(void, alGetBuffer3f, ALuint, ALenum, ALfloat*, ALfloat*, ALfloat*) +DECL_FUNC3(void, alGetBufferfv, ALuint, ALenum, ALfloat*) +DECL_FUNC3(void, alGetBufferi, ALuint, ALenum, ALint*) +DECL_FUNC5(void, alGetBuffer3i, ALuint, ALenum, ALint*, ALint*, ALint*) +DECL_FUNC3(void, alGetBufferiv, ALuint, ALenum, ALint*) +DECL_FUNCEXT3(void, alGetBufferPtr,SOFT, ALuint, ALenum, ALvoid**) +DECL_FUNCEXT5(void, alGetBuffer3Ptr,SOFT, ALuint, ALenum, ALvoid**, ALvoid**, ALvoid**) +DECL_FUNCEXT3(void, alGetBufferPtrv,SOFT, ALuint, ALenum, ALvoid**) + +AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint /*buffer*/, ALuint /*samplerate*/, + ALenum /*internalformat*/, ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, + const ALvoid* /*data*/) +START_API_FUNC +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + context->setError(AL_INVALID_OPERATION, "alBufferSamplesSOFT not supported"); +} +END_API_FUNC + +AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint /*buffer*/, ALsizei /*offset*/, + ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, const ALvoid* /*data*/) +START_API_FUNC +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + context->setError(AL_INVALID_OPERATION, "alBufferSubSamplesSOFT not supported"); +} +END_API_FUNC + +AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint /*buffer*/, ALsizei /*offset*/, + ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, ALvoid* /*data*/) +START_API_FUNC +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return; + + context->setError(AL_INVALID_OPERATION, "alGetBufferSamplesSOFT not supported"); +} +END_API_FUNC + +AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum /*format*/) +START_API_FUNC +{ + ContextRef context{GetContextRef()}; + if(!context) UNLIKELY return AL_FALSE; + + context->setError(AL_INVALID_OPERATION, "alIsBufferFormatSupportedSOFT not supported"); + return AL_FALSE; +} END_API_FUNC diff --git a/al/direct_defs.h b/al/direct_defs.h index 555e9565..be92e759 100644 --- a/al/direct_defs.h +++ b/al/direct_defs.h @@ -19,6 +19,18 @@ R AL_API Name(T1 a, T2 b) START_API_FUNC \ return Name##Direct(GetContextRef().get(), a, b); \ } END_API_FUNC +#define DECL_FUNC3(R, Name, T1, T2, T3) \ +R AL_API Name(T1 a, T2 b, T3 c) START_API_FUNC \ +{ \ + return Name##Direct(GetContextRef().get(), a, b, c); \ +} END_API_FUNC + +#define DECL_FUNC5(R, Name, T1, T2, T3, T4, T5) \ +R AL_API Name(T1 a, T2 b, T3 c, T4 d, T5 e) START_API_FUNC \ +{ \ + return Name##Direct(GetContextRef().get(), a, b, c, d, e); \ +} END_API_FUNC + #define DECL_FUNCEXT(R, Name,Ext) \ R AL_API Name##Ext(void) START_API_FUNC \ @@ -26,10 +38,40 @@ R AL_API Name##Ext(void) START_API_FUNC \ return Name##Direct##Ext(GetContextRef().get()); \ } END_API_FUNC +#define DECL_FUNCEXT1(R, Name,Ext, T1) \ +R AL_API Name##Ext(T1 a) START_API_FUNC \ +{ \ + return Name##Direct##Ext(GetContextRef().get(), a); \ +} END_API_FUNC + #define DECL_FUNCEXT2(R, Name,Ext, T1, T2) \ R AL_API Name##Ext(T1 a, T2 b) START_API_FUNC \ { \ return Name##Direct##Ext(GetContextRef().get(), a, b); \ } END_API_FUNC +#define DECL_FUNCEXT3(R, Name,Ext, T1, T2, T3) \ +R AL_API Name##Ext(T1 a, T2 b, T3 c) START_API_FUNC \ +{ \ + return Name##Direct##Ext(GetContextRef().get(), a, b, c); \ +} END_API_FUNC + +#define DECL_FUNCEXT4(R, Name,Ext, T1, T2, T3, T4) \ +R AL_API Name##Ext(T1 a, T2 b, T3 c, T4 d) START_API_FUNC \ +{ \ + return Name##Direct##Ext(GetContextRef().get(), a, b, c, d); \ +} END_API_FUNC + +#define DECL_FUNCEXT5(R, Name,Ext, T1, T2, T3, T4, T5) \ +R AL_API Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e) START_API_FUNC \ +{ \ + return Name##Direct##Ext(GetContextRef().get(), a, b, c, d, e); \ +} END_API_FUNC + +#define DECL_FUNCEXT6(R, Name,Ext, T1, T2, T3, T4, T5, T6) \ +R AL_API Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f) START_API_FUNC \ +{ \ + return Name##Direct##Ext(GetContextRef().get(), a, b, c, d, e, f); \ +} END_API_FUNC + #endif /* AL_DIRECT_DEFS_H */ diff --git a/alc/inprogext.h b/alc/inprogext.h index 2d7da9b2..3e20caaf 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -20,11 +20,19 @@ typedef void (AL_APIENTRY*LPALBUFFERSTORAGESOFT)(ALuint buffer, ALenum format, c typedef void* (AL_APIENTRY*LPALMAPBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access); typedef void (AL_APIENTRY*LPALUNMAPBUFFERSOFT)(ALuint buffer); typedef void (AL_APIENTRY*LPALFLUSHMAPPEDBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length); +typedef void (AL_APIENTRY*LPALBUFFERSTORAGEDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags); +typedef void* (AL_APIENTRY*LPALMAPBUFFERDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access); +typedef void (AL_APIENTRY*LPALUNMAPBUFFERDIRECTSOFT)(ALCcontext *context, ALuint buffer); +typedef void (AL_APIENTRY*LPALFLUSHMAPPEDBUFFERDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length); #ifdef AL_ALEXT_PROTOTYPES AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags); AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access); AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer); AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length); +void AL_APIENTRY alBufferStorageDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags) noexcept; +void* AL_APIENTRY alMapBufferDirectSOFT(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access) noexcept; +void AL_APIENTRY alUnmapBufferDirectSOFT(ALCcontext *context, ALuint buffer) noexcept; +void AL_APIENTRY alFlushMappedBufferDirectSOFT(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length) noexcept; #endif #endif -- cgit v1.2.3 From 9d60823014c038bd4078fdf47e83118b2a17fc32 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 14 May 2023 17:31:08 -0700 Subject: Add more direct functions to the function table --- alc/alc.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index 23ed101d..91ac1842 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -490,10 +490,76 @@ const struct { DECL(alGetProcAddress), DECL(alGetEnumValueDirect), + DECL(alGenBuffersDirect), + DECL(alDeleteBuffersDirect), + DECL(alIsBufferDirect), + DECL(alBufferDataDirect), + DECL(alBufferiDirect), + DECL(alBuffer3iDirect), + DECL(alBufferivDirect), + DECL(alBufferfDirect), + DECL(alBuffer3fDirect), + DECL(alBufferfvDirect), + DECL(alGetBufferiDirect), + DECL(alGetBuffer3iDirect), + DECL(alGetBufferivDirect), + DECL(alGetBufferfDirect), + DECL(alGetBuffer3fDirect), + DECL(alGetBufferfvDirect), + + DECL(alGenSourcesDirect), + DECL(alDeleteSourcesDirect), + DECL(alIsSourceDirect), + DECL(alSourcePlayDirect), + DECL(alSourceStopDirect), + DECL(alSourcePauseDirect), + DECL(alSourceRewindDirect), + DECL(alSourcePlayvDirect), + DECL(alSourceStopvDirect), + DECL(alSourcePausevDirect), + DECL(alSourceRewindvDirect), + DECL(alSourceiDirect), + DECL(alSource3iDirect), + DECL(alSourceivDirect), + DECL(alSourcefDirect), + DECL(alSource3fDirect), + DECL(alSourcefvDirect), + DECL(alGetSourceiDirect), + DECL(alGetSource3iDirect), + DECL(alGetSourceivDirect), + DECL(alGetSourcefDirect), + DECL(alGetSource3fDirect), + DECL(alGetSourcefvDirect), + DECL(alSourceQueueBuffersDirect), + DECL(alSourceUnqueueBuffersDirect), + DECL(alDeferUpdatesDirectSOFT), DECL(alProcessUpdatesDirectSOFT), DECL(alGetStringiDirectSOFT), + DECL(alBufferDataStaticDirect), + DECL(alBufferCallbackDirectSOFT), + DECL(alBufferSubDataDirectSOFT), + DECL(alBufferStorageDirectSOFT), + DECL(alMapBufferDirectSOFT), + DECL(alUnmapBufferDirectSOFT), + DECL(alFlushMappedBufferDirectSOFT), + + DECL(alSourcei64DirectSOFT), + DECL(alSource3i64DirectSOFT), + DECL(alSourcei64vDirectSOFT), + DECL(alSourcedDirectSOFT), + DECL(alSource3dDirectSOFT), + DECL(alSourcedvDirectSOFT), + DECL(alGetSourcei64DirectSOFT), + DECL(alGetSource3i64DirectSOFT), + DECL(alGetSourcei64vDirectSOFT), + DECL(alGetSourcedDirectSOFT), + DECL(alGetSource3dDirectSOFT), + DECL(alGetSourcedvDirectSOFT), + DECL(alSourcePlayAtTimeDirectSOFT), + DECL(alSourcePlayAtTimevDirectSOFT), + #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), -- cgit v1.2.3 From 6b9b875d6f256c659762073a227032f7e7fcbc02 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 14 May 2023 17:53:48 -0700 Subject: Implement direct functions for the listener and events --- al/direct_defs.h | 6 +++ al/event.cpp | 22 ++++---- al/listener.cpp | 149 +++++++++++++++++++++++++++---------------------------- alc/alc.cpp | 15 ++++++ 4 files changed, 107 insertions(+), 85 deletions(-) (limited to 'alc') diff --git a/al/direct_defs.h b/al/direct_defs.h index be92e759..c36211ae 100644 --- a/al/direct_defs.h +++ b/al/direct_defs.h @@ -25,6 +25,12 @@ R AL_API Name(T1 a, T2 b, T3 c) START_API_FUNC \ return Name##Direct(GetContextRef().get(), a, b, c); \ } END_API_FUNC +#define DECL_FUNC4(R, Name, T1, T2, T3, T4) \ +R AL_API Name(T1 a, T2 b, T3 c, T4 d) START_API_FUNC \ +{ \ + return Name##Direct(GetContextRef().get(), a, b, c, d); \ +} END_API_FUNC + #define DECL_FUNC5(R, Name, T1, T2, T3, T4, T5) \ R AL_API Name(T1 a, T2 b, T3 c, T4 d, T5 e) START_API_FUNC \ { \ diff --git a/al/event.cpp b/al/event.cpp index eb6af45c..f7ef7b50 100644 --- a/al/event.cpp +++ b/al/event.cpp @@ -27,6 +27,7 @@ #include "core/logging.h" #include "core/voice_change.h" #include "debug.h" +#include "direct_defs.h" #include "opthelpers.h" #include "ringbuffer.h" #include "threads.h" @@ -172,11 +173,11 @@ void StopEventThrd(ALCcontext *ctx) ctx->mEventThread.join(); } -AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsizei count, + const ALenum *types, ALboolean enable) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(count < 0) context->setError(AL_INVALID_VALUE, "Controlling %d events", count); if(count <= 0) return; @@ -225,17 +226,18 @@ START_API_FUNC std::lock_guard _{context->mEventCbLock}; } } -END_API_FUNC -AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alEventCallbackDirectSOFT(ALCcontext *context, + ALEVENTPROCSOFT callback, void *userParam) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mPropLock}; std::lock_guard __{context->mEventCbLock}; context->mEventCb = callback; context->mEventParam = userParam; } -END_API_FUNC + +DECL_FUNCEXT3(void, alEventControl,SOFT, ALsizei, const ALenum*, ALboolean) +DECL_FUNCEXT2(void, alEventCallback,SOFT, ALEVENTPROCSOFT, void*) diff --git a/al/listener.cpp b/al/listener.cpp index 06d7c370..4ee4f8d7 100644 --- a/al/listener.cpp +++ b/al/listener.cpp @@ -33,6 +33,7 @@ #include "almalloc.h" #include "atomic.h" #include "core/except.h" +#include "direct_defs.h" #include "opthelpers.h" @@ -68,11 +69,10 @@ inline void CommitAndUpdateProps(ALCcontext *context) } // namespace -AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALlistener &listener = context->mListener; std::lock_guard _{context->mPropLock}; @@ -82,27 +82,26 @@ START_API_FUNC if(!(value >= 0.0f && std::isfinite(value))) return context->setError(AL_INVALID_VALUE, "Listener gain out of range"); listener.Gain = value; - UpdateProps(context.get()); + UpdateProps(context); break; case AL_METERS_PER_UNIT: if(!(value >= AL_MIN_METERS_PER_UNIT && value <= AL_MAX_METERS_PER_UNIT)) return context->setError(AL_INVALID_VALUE, "Listener meters per unit out of range"); listener.mMetersPerUnit = value; - UpdateProps(context.get()); + UpdateProps(context); break; default: context->setError(AL_INVALID_ENUM, "Invalid listener float property"); } } -END_API_FUNC -AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1, + ALfloat value2, ALfloat value3) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALlistener &listener = context->mListener; std::lock_guard _{context->mPropLock}; @@ -114,7 +113,7 @@ START_API_FUNC listener.Position[0] = value1; listener.Position[1] = value2; listener.Position[2] = value3; - CommitAndUpdateProps(context.get()); + CommitAndUpdateProps(context); break; case AL_VELOCITY: @@ -123,17 +122,16 @@ START_API_FUNC listener.Velocity[0] = value1; listener.Velocity[1] = value2; listener.Velocity[2] = value3; - CommitAndUpdateProps(context.get()); + CommitAndUpdateProps(context); break; default: context->setError(AL_INVALID_ENUM, "Invalid listener 3-float property"); } } -END_API_FUNC -AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum param, + const ALfloat *values) noexcept { if(values) { @@ -141,18 +139,18 @@ START_API_FUNC { case AL_GAIN: case AL_METERS_PER_UNIT: - alListenerf(param, values[0]); + alListenerfDirect(context, param, values[0]); return; case AL_POSITION: case AL_VELOCITY: - alListener3f(param, values[0], values[1], values[2]); + alListener3fDirect(context, param, values[0], values[1], values[2]); return; } } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(!values) UNLIKELY return context->setError(AL_INVALID_VALUE, "NULL pointer"); @@ -172,21 +170,19 @@ START_API_FUNC listener.OrientUp[0] = values[3]; listener.OrientUp[1] = values[4]; listener.OrientUp[2] = values[5]; - CommitAndUpdateProps(context.get()); + CommitAndUpdateProps(context); break; default: context->setError(AL_INVALID_ENUM, "Invalid listener float-vector property"); } } -END_API_FUNC -AL_API void AL_APIENTRY alListeneri(ALenum param, ALint /*value*/) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint /*value*/) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mPropLock}; switch(param) @@ -195,22 +191,21 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid listener integer property"); } } -END_API_FUNC -AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum param, ALint value1, + ALint value2, ALint value3) noexcept { switch(param) { case AL_POSITION: case AL_VELOCITY: - alListener3f(param, static_cast(value1), static_cast(value2), - static_cast(value3)); + alListener3fDirect(context, param, static_cast(value1), + static_cast(value2), static_cast(value3)); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mPropLock}; switch(param) @@ -219,10 +214,9 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid listener 3-integer property"); } } -END_API_FUNC -AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum param, + const ALint *values) noexcept { if(values) { @@ -231,8 +225,8 @@ START_API_FUNC { case AL_POSITION: case AL_VELOCITY: - alListener3f(param, static_cast(values[0]), static_cast(values[1]), - static_cast(values[2])); + alListener3fDirect(context, param, static_cast(values[0]), + static_cast(values[1]), static_cast(values[2])); return; case AL_ORIENTATION: @@ -242,13 +236,13 @@ START_API_FUNC fvals[3] = static_cast(values[3]); fvals[4] = static_cast(values[4]); fvals[5] = static_cast(values[5]); - alListenerfv(param, fvals); + alListenerfvDirect(context, param, fvals); return; } } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mPropLock}; if(!values) UNLIKELY @@ -259,14 +253,13 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid listener integer-vector property"); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum param, + ALfloat *value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALlistener &listener = context->mListener; std::lock_guard _{context->mPropLock}; @@ -286,13 +279,12 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid listener float property"); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum param, + ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALlistener &listener = context->mListener; std::lock_guard _{context->mPropLock}; @@ -316,26 +308,25 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid listener 3-float property"); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum param, + ALfloat *values) noexcept { switch(param) { case AL_GAIN: case AL_METERS_PER_UNIT: - alGetListenerf(param, values); + alGetListenerfDirect(context, param, values); return; case AL_POSITION: case AL_VELOCITY: - alGetListener3f(param, values+0, values+1, values+2); + alGetListener3fDirect(context, param, values+0, values+1, values+2); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALlistener &listener = context->mListener; std::lock_guard _{context->mPropLock}; @@ -357,14 +348,12 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid listener float-vector property"); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mPropLock}; if(!value) @@ -375,13 +364,12 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid listener integer property"); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum param, + ALint *value1, ALint *value2, ALint *value3) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALlistener &listener = context->mListener; std::lock_guard _{context->mPropLock}; @@ -405,21 +393,20 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid listener 3-integer property"); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum param, + ALint *values) noexcept { switch(param) { case AL_POSITION: case AL_VELOCITY: - alGetListener3i(param, values+0, values+1, values+2); + alGetListener3iDirect(context, param, values+0, values+1, values+2); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALlistener &listener = context->mListener; std::lock_guard _{context->mPropLock}; @@ -441,4 +428,16 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid listener integer-vector property"); } } -END_API_FUNC + +DECL_FUNC2(void, alListenerf, ALenum, ALfloat) +DECL_FUNC4(void, alListener3f, ALenum, ALfloat, ALfloat, ALfloat) +DECL_FUNC2(void, alListenerfv, ALenum, const ALfloat*) +DECL_FUNC2(void, alListeneri, ALenum, ALint) +DECL_FUNC4(void, alListener3i, ALenum, ALint, ALint, ALint) +DECL_FUNC2(void, alListeneriv, ALenum, const ALint*) +DECL_FUNC2(void, alGetListenerf, ALenum, ALfloat*) +DECL_FUNC4(void, alGetListener3f, ALenum, ALfloat*, ALfloat*, ALfloat*) +DECL_FUNC2(void, alGetListenerfv, ALenum, ALfloat*) +DECL_FUNC2(void, alGetListeneri, ALenum, ALint*) +DECL_FUNC4(void, alGetListener3i, ALenum, ALint*, ALint*, ALint*) +DECL_FUNC2(void, alGetListeneriv, ALenum, ALint*) diff --git a/alc/alc.cpp b/alc/alc.cpp index 91ac1842..c6a1a1fe 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -490,6 +490,19 @@ const struct { DECL(alGetProcAddress), DECL(alGetEnumValueDirect), + DECL(alListeneriDirect), + DECL(alListener3iDirect), + DECL(alListenerivDirect), + DECL(alListenerfDirect), + DECL(alListener3fDirect), + DECL(alListenerfvDirect), + DECL(alGetListeneriDirect), + DECL(alGetListener3iDirect), + DECL(alGetListenerivDirect), + DECL(alGetListenerfDirect), + DECL(alGetListener3fDirect), + DECL(alGetListenerfvDirect), + DECL(alGenBuffersDirect), DECL(alDeleteBuffersDirect), DECL(alIsBufferDirect), @@ -560,6 +573,8 @@ const struct { DECL(alSourcePlayAtTimeDirectSOFT), DECL(alSourcePlayAtTimevDirectSOFT), + DECL(alEventControlDirectSOFT), + DECL(alEventCallbackDirectSOFT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), -- cgit v1.2.3 From a6884f630383e98ded68858b93df8f040b83eece Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 14 May 2023 18:15:38 -0700 Subject: Implement direct functions for the debug API --- al/debug.cpp | 59 ++++++++++++++++++++++++++++++++++++++------------------- alc/alc.cpp | 7 +++++++ alc/inprogext.h | 12 ++++++++++++ 3 files changed, 59 insertions(+), 19 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index 71aadc85..e28df917 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -234,20 +234,28 @@ void ALCcontext::sendDebugMessage(std::unique_lock &debuglock, Debug FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) noexcept +{ return alDebugMessageCallbackDirectEXT(GetContextRef().get(), callback, userParam); } + +FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context, + ALDEBUGPROCEXT callback, void *userParam) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mDebugCbLock}; context->mDebugCb = callback; context->mDebugParam = userParam; } -FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, - ALenum severity, ALsizei length, const ALchar *message) noexcept + +FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept +{ return alDebugMessageInsertDirectEXT(GetContextRef().get(), source, type, id, severity, length, message); } + +FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, + ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(!context->mContextFlags.test(ContextFlags::DebugBit)) return; @@ -285,11 +293,14 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, } -FORCE_ALIGN void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, - ALsizei count, const ALuint *ids, ALboolean enable) noexcept +FORCE_ALIGN void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept +{ return alDebugMessageControlDirectEXT(GetContextRef().get(), source, type, severity, count, ids, enable); } + +FORCE_ALIGN void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, + ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(count > 0) { @@ -384,9 +395,13 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type FORCE_ALIGN void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept +{ return alPushDebugGroupDirectEXT(GetContextRef().get(), source, id, length, message); } + +FORCE_ALIGN void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, + ALuint id, ALsizei length, const ALchar *message) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(length < 0) { @@ -427,9 +442,12 @@ FORCE_ALIGN void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsiz } FORCE_ALIGN void AL_APIENTRY alPopDebugGroupEXT(void) noexcept +{ return alPopDebugGroupDirectEXT(GetContextRef().get()); } + +FORCE_ALIGN void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::unique_lock debuglock{context->mDebugCbLock}; if(context->mDebugGroups.size() <= 1) @@ -451,12 +469,15 @@ FORCE_ALIGN void AL_APIENTRY alPopDebugGroupEXT(void) noexcept } -FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, - ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, - ALchar *logBuf) noexcept +FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept +{ return alGetDebugMessageLogDirectEXT(GetContextRef().get(), count, logBufSize, sources, types, ids, severities, lengths, logBuf); } + +FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, + ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, + ALsizei *lengths, ALchar *logBuf) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return 0; + if(!context) UNLIKELY + return 0; if(logBufSize < 0) { diff --git a/alc/alc.cpp b/alc/alc.cpp index c6a1a1fe..7d5b7ee0 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -575,6 +575,13 @@ const struct { DECL(alEventControlDirectSOFT), DECL(alEventCallbackDirectSOFT), + + DECL(alDebugMessageCallbackDirectEXT), + DECL(alDebugMessageInsertDirectEXT), + DECL(alDebugMessageControlDirectEXT), + DECL(alPushDebugGroupDirectEXT), + DECL(alPopDebugGroupDirectEXT), + DECL(alGetDebugMessageLogDirectEXT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), diff --git a/alc/inprogext.h b/alc/inprogext.h index 3e20caaf..00629a9f 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -108,6 +108,12 @@ typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLEXT)(ALenum source, ALenum type typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPEXT)(ALenum source, ALuint id, ALsizei length, const ALchar *message); typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void); typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf); +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKDIRECTEXT)(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam); +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable); +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPDIRECTEXT)(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message); +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPDIRECTEXT)(ALCcontext *context); +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGDIRECTEXT)(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf); #ifdef AL_ALEXT_PROTOTYPES void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) noexcept; void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; @@ -115,6 +121,12 @@ void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum sev void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept; void AL_APIENTRY alPopDebugGroupEXT(void) noexcept; ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept; +void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) noexcept; +void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; +void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept; +void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept; +void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) noexcept; +ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept; #endif #endif -- cgit v1.2.3 From 5ab9ce58808a6c92bbb92c8f58d7694cb86e5414 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 14 May 2023 18:47:24 -0700 Subject: Implement direct functions for EFX --- al/auxeffectslot.cpp | 169 ++++++++++++++++++++++++++------------------------- al/effect.cpp | 111 +++++++++++++++++---------------- al/filter.cpp | 109 ++++++++++++++++----------------- alc/alc.cpp | 34 +++++++++++ 4 files changed, 228 insertions(+), 195 deletions(-) (limited to 'alc') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 3a3222b8..5fa8fe55 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -47,6 +47,7 @@ #include "core/except.h" #include "core/fpu_ctrl.h" #include "core/logging.h" +#include "direct_defs.h" #include "effect.h" #include "opthelpers.h" @@ -309,11 +310,11 @@ inline void UpdateProps(ALeffectslot *slot, ALCcontext *context) } // namespace -AL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGenAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, + ALuint *effectslots) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(n < 0) UNLIKELY context->setError(AL_INVALID_VALUE, "Generating %d effect slots", n); @@ -327,7 +328,7 @@ START_API_FUNC device->AuxiliaryEffectSlotMax, context->mNumEffectSlots, n); return; } - if(!EnsureEffectSlots(context.get(), static_cast(n))) + if(!EnsureEffectSlots(context, static_cast(n))) { context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d effectslot%s", n, (n==1) ? "" : "s"); @@ -336,7 +337,7 @@ START_API_FUNC if(n == 1) { - ALeffectslot *slot{AllocEffectSlot(context.get())}; + ALeffectslot *slot{AllocEffectSlot(context)}; effectslots[0] = slot->id; } else @@ -345,19 +346,18 @@ START_API_FUNC ALsizei count{n}; ids.reserve(static_cast(count)); do { - ALeffectslot *slot{AllocEffectSlot(context.get())}; + ALeffectslot *slot{AllocEffectSlot(context)}; ids.emplace_back(slot->id); } while(--count); std::copy(ids.cbegin(), ids.cend(), effectslots); } } -END_API_FUNC -AL_API void AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, + const ALuint *effectslots) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(n < 0) UNLIKELY context->setError(AL_INVALID_VALUE, "Deleting %d effect slots", n); @@ -366,7 +366,7 @@ START_API_FUNC std::lock_guard _{context->mEffectSlotLock}; if(n == 1) { - ALeffectslot *slot{LookupEffectSlot(context.get(), effectslots[0])}; + ALeffectslot *slot{LookupEffectSlot(context, effectslots[0])}; if(!slot) UNLIKELY { context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslots[0]); @@ -378,15 +378,15 @@ START_API_FUNC effectslots[0]); return; } - RemoveActiveEffectSlots({&slot, 1u}, context.get()); - FreeEffectSlot(context.get(), slot); + RemoveActiveEffectSlots({&slot, 1u}, context); + FreeEffectSlot(context, slot); } else { auto slots = std::vector(static_cast(n)); for(size_t i{0};i < slots.size();++i) { - ALeffectslot *slot{LookupEffectSlot(context.get(), effectslots[i])}; + ALeffectslot *slot{LookupEffectSlot(context, effectslots[i])}; if(!slot) UNLIKELY { context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslots[i]); @@ -410,26 +410,23 @@ START_API_FUNC slots.erase(slots_end, slots.end()); /* All effectslots are valid, remove and delete them */ - RemoveActiveEffectSlots(slots, context.get()); + RemoveActiveEffectSlots(slots, context); for(ALeffectslot *slot : slots) - FreeEffectSlot(context.get(), slot); + FreeEffectSlot(context, slot); } } -END_API_FUNC -AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot) -START_API_FUNC +FORCE_ALIGN ALboolean AL_APIENTRY alIsAuxiliaryEffectSlotDirect(ALCcontext *context, + ALuint effectslot) noexcept { - ContextRef context{GetContextRef()}; if(context) LIKELY { std::lock_guard _{context->mEffectSlotLock}; - if(LookupEffectSlot(context.get(), effectslot) != nullptr) + if(LookupEffectSlot(context, effectslot) != nullptr) return AL_TRUE; } return AL_FALSE; } -END_API_FUNC AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid) @@ -541,15 +538,15 @@ START_API_FUNC END_API_FUNC -AL_API void AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, + ALenum param, ALint value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mPropLock}; std::lock_guard __{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot); + ALeffectslot *slot = LookupEffectSlot(context, effectslot); if(!slot) UNLIKELY return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); @@ -565,12 +562,12 @@ START_API_FUNC std::lock_guard ___{device->EffectLock}; ALeffect *effect{value ? LookupEffect(device, static_cast(value)) : nullptr}; if(effect) - err = slot->initEffect(effect->type, effect->Props, context.get()); + err = slot->initEffect(effect->type, effect->Props, context); else { if(value != 0) return context->setError(AL_INVALID_VALUE, "Invalid effect ID %u", value); - err = slot->initEffect(AL_EFFECT_NULL, EffectProps{}, context.get()); + err = slot->initEffect(AL_EFFECT_NULL, EffectProps{}, context); } } if(err != AL_NO_ERROR) UNLIKELY @@ -581,9 +578,9 @@ START_API_FUNC if(slot->mState == SlotState::Initial) UNLIKELY { slot->mPropsDirty = false; - slot->updateProps(context.get()); + slot->updateProps(context); - AddActiveEffectSlots({&slot, 1}, context.get()); + AddActiveEffectSlots({&slot, 1}, context); slot->mState = SlotState::Playing; return; } @@ -599,7 +596,7 @@ START_API_FUNC break; case AL_EFFECTSLOT_TARGET_SOFT: - target = LookupEffectSlot(context.get(), static_cast(value)); + target = LookupEffectSlot(context, static_cast(value)); if(value && !target) return context->setError(AL_INVALID_VALUE, "Invalid effect slot target ID"); if(slot->Target == target) UNLIKELY @@ -623,7 +620,7 @@ START_API_FUNC if(target) IncrementRef(target->ref); DecrementRef(oldtarget->ref); slot->Target = target; - slot->updateProps(context.get()); + slot->updateProps(context); return; } @@ -677,12 +674,11 @@ START_API_FUNC return context->setError(AL_INVALID_ENUM, "Invalid effect slot integer property 0x%04x", param); } - UpdateProps(slot, context.get()); + UpdateProps(slot, context); } -END_API_FUNC -AL_API void AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, + ALenum param, const ALint *values) noexcept { switch(param) { @@ -691,15 +687,15 @@ START_API_FUNC case AL_EFFECTSLOT_TARGET_SOFT: case AL_EFFECTSLOT_STATE_SOFT: case AL_BUFFER: - alAuxiliaryEffectSloti(effectslot, param, values[0]); + alAuxiliaryEffectSlotiDirect(context, effectslot, param, values[0]); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot); + ALeffectslot *slot = LookupEffectSlot(context, effectslot); if(!slot) UNLIKELY return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); @@ -710,17 +706,16 @@ START_API_FUNC "Invalid effect slot integer-vector property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, + ALenum param, ALfloat value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mPropLock}; std::lock_guard __{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot); + ALeffectslot *slot = LookupEffectSlot(context, effectslot); if(!slot) UNLIKELY return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); @@ -738,25 +733,24 @@ START_API_FUNC return context->setError(AL_INVALID_ENUM, "Invalid effect slot float property 0x%04x", param); } - UpdateProps(slot, context.get()); + UpdateProps(slot, context); } -END_API_FUNC -AL_API void AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, + ALenum param, const ALfloat *values) noexcept { switch(param) { case AL_EFFECTSLOT_GAIN: - alAuxiliaryEffectSlotf(effectslot, param, values[0]); + alAuxiliaryEffectSlotfDirect(context, effectslot, param, values[0]); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot); + ALeffectslot *slot = LookupEffectSlot(context, effectslot); if(!slot) UNLIKELY return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); @@ -767,17 +761,16 @@ START_API_FUNC "Invalid effect slot float-vector property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotiDirect(ALCcontext *context, + ALuint effectslot, ALenum param, ALint *value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot); + ALeffectslot *slot = LookupEffectSlot(context, effectslot); if(!slot) UNLIKELY return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); @@ -809,10 +802,9 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid effect slot integer property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotivDirect(ALCcontext *context, + ALuint effectslot, ALenum param, ALint *values) noexcept { switch(param) { @@ -821,15 +813,15 @@ START_API_FUNC case AL_EFFECTSLOT_TARGET_SOFT: case AL_EFFECTSLOT_STATE_SOFT: case AL_BUFFER: - alGetAuxiliaryEffectSloti(effectslot, param, values); + alGetAuxiliaryEffectSlotiDirect(context, effectslot, param, values); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot); + ALeffectslot *slot = LookupEffectSlot(context, effectslot); if(!slot) UNLIKELY return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); @@ -840,16 +832,15 @@ START_API_FUNC param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotfDirect(ALCcontext *context, + ALuint effectslot, ALenum param, ALfloat *value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot); + ALeffectslot *slot = LookupEffectSlot(context, effectslot); if(!slot) UNLIKELY return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); @@ -863,23 +854,22 @@ START_API_FUNC context->setError(AL_INVALID_ENUM, "Invalid effect slot float property 0x%04x", param); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context, + ALuint effectslot, ALenum param, ALfloat *values) noexcept { switch(param) { case AL_EFFECTSLOT_GAIN: - alGetAuxiliaryEffectSlotf(effectslot, param, values); + alGetAuxiliaryEffectSlotfDirect(context, effectslot, param, values); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context.get(), effectslot); + ALeffectslot *slot = LookupEffectSlot(context, effectslot); if(!slot) UNLIKELY return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); @@ -890,7 +880,18 @@ START_API_FUNC param); } } -END_API_FUNC + +DECL_FUNC2(void, alGenAuxiliaryEffectSlots, ALsizei, ALuint*) +DECL_FUNC2(void, alDeleteAuxiliaryEffectSlots, ALsizei, const ALuint*) +DECL_FUNC1(ALboolean, alIsAuxiliaryEffectSlot, ALuint) +DECL_FUNC3(void, alAuxiliaryEffectSlotf, ALuint, ALenum, ALfloat) +DECL_FUNC3(void, alAuxiliaryEffectSlotfv, ALuint, ALenum, const ALfloat*) +DECL_FUNC3(void, alAuxiliaryEffectSloti, ALuint, ALenum, ALint) +DECL_FUNC3(void, alAuxiliaryEffectSlotiv, ALuint, ALenum, const ALint*) +DECL_FUNC3(void, alGetAuxiliaryEffectSlotf, ALuint, ALenum, ALfloat*) +DECL_FUNC3(void, alGetAuxiliaryEffectSlotfv, ALuint, ALenum, ALfloat*) +DECL_FUNC3(void, alGetAuxiliaryEffectSloti, ALuint, ALenum, ALint*) +DECL_FUNC3(void, alGetAuxiliaryEffectSlotiv, ALuint, ALenum, ALint*) ALeffectslot::ALeffectslot(ALCcontext *context) diff --git a/al/effect.cpp b/al/effect.cpp index 3ca7c37e..a0ec2135 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -49,6 +49,7 @@ #include "alstring.h" #include "core/except.h" #include "core/logging.h" +#include "direct_defs.h" #include "opthelpers.h" #ifdef ALSOFT_EAX @@ -230,11 +231,10 @@ inline ALeffect *LookupEffect(ALCdevice *device, ALuint id) } // namespace -AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(n < 0) UNLIKELY context->setError(AL_INVALID_VALUE, "Generating %d effects", n); @@ -268,13 +268,12 @@ START_API_FUNC std::copy(ids.cbegin(), ids.cend(), effects); } } -END_API_FUNC -AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alDeleteEffectsDirect(ALCcontext *context, ALsizei n, + const ALuint *effects) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(n < 0) UNLIKELY context->setError(AL_INVALID_VALUE, "Deleting %d effects", n); @@ -303,12 +302,9 @@ START_API_FUNC }; std::for_each(effects, effects_end, delete_effect); } -END_API_FUNC -AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect) -START_API_FUNC +FORCE_ALIGN ALboolean AL_APIENTRY alIsEffectDirect(ALCcontext *context, ALuint effect) noexcept { - ContextRef context{GetContextRef()}; if(context) LIKELY { ALCdevice *device{context->mALDevice.get()}; @@ -318,13 +314,12 @@ START_API_FUNC } return AL_FALSE; } -END_API_FUNC -AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, + ALint value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->EffectLock}; @@ -361,20 +356,19 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, + const ALint *values) noexcept { switch(param) { case AL_EFFECT_TYPE: - alEffecti(effect, param, values[0]); + alEffectiDirect(context, effect, param, values[0]); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->EffectLock}; @@ -391,13 +385,12 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, + ALfloat value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->EffectLock}; @@ -414,13 +407,12 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, + const ALfloat *values) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->EffectLock}; @@ -437,13 +429,12 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, + ALint *value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->EffectLock}; @@ -462,20 +453,19 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, + ALint *values) noexcept { switch(param) { case AL_EFFECT_TYPE: - alGetEffecti(effect, param, values); + alGetEffectiDirect(context, effect, param, values); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->EffectLock}; @@ -492,13 +482,12 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, + ALfloat *value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->EffectLock}; @@ -515,13 +504,12 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, + ALfloat *values) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->EffectLock}; @@ -538,7 +526,18 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC + +DECL_FUNC2(void, alGenEffects, ALsizei, ALuint*) +DECL_FUNC2(void, alDeleteEffects, ALsizei, const ALuint*) +DECL_FUNC1(ALboolean, alIsEffect, ALuint) +DECL_FUNC3(void, alEffectf, ALuint, ALenum, ALfloat) +DECL_FUNC3(void, alEffectfv, ALuint, ALenum, const ALfloat*) +DECL_FUNC3(void, alEffecti, ALuint, ALenum, ALint) +DECL_FUNC3(void, alEffectiv, ALuint, ALenum, const ALint*) +DECL_FUNC3(void, alGetEffectf, ALuint, ALenum, ALfloat*) +DECL_FUNC3(void, alGetEffectfv, ALuint, ALenum, ALfloat*) +DECL_FUNC3(void, alGetEffecti, ALuint, ALenum, ALint*) +DECL_FUNC3(void, alGetEffectiv, ALuint, ALenum, ALint*) void InitEffect(ALeffect *effect) diff --git a/al/filter.cpp b/al/filter.cpp index 11d71179..9176a516 100644 --- a/al/filter.cpp +++ b/al/filter.cpp @@ -43,6 +43,7 @@ #include "almalloc.h" #include "alnumeric.h" #include "core/except.h" +#include "direct_defs.h" #include "opthelpers.h" @@ -401,11 +402,10 @@ inline ALfilter *LookupFilter(ALCdevice *device, ALuint id) } // namespace -AL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(n < 0) UNLIKELY context->setError(AL_INVALID_VALUE, "Generating %d filters", n); @@ -439,13 +439,12 @@ START_API_FUNC std::copy(ids.begin(), ids.end(), filters); } } -END_API_FUNC -AL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei n, + const ALuint *filters) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; if(n < 0) UNLIKELY context->setError(AL_INVALID_VALUE, "Deleting %d filters", n); @@ -474,12 +473,9 @@ START_API_FUNC }; std::for_each(filters, filters_end, delete_filter); } -END_API_FUNC -AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter) -START_API_FUNC +FORCE_ALIGN ALboolean AL_APIENTRY alIsFilterDirect(ALCcontext *context, ALuint filter) noexcept { - ContextRef context{GetContextRef()}; if(context) LIKELY { ALCdevice *device{context->mALDevice.get()}; @@ -489,14 +485,13 @@ START_API_FUNC } return AL_FALSE; } -END_API_FUNC -AL_API void AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, + ALint value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->FilterLock}; @@ -524,20 +519,19 @@ START_API_FUNC } } } -END_API_FUNC -AL_API void AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, + const ALint *values) noexcept { switch(param) { case AL_FILTER_TYPE: - alFilteri(filter, param, values[0]); + alFilteriDirect(context, filter, param, values[0]); return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->FilterLock}; @@ -554,13 +548,12 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, + ALfloat value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->FilterLock}; @@ -577,13 +570,12 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, + const ALfloat *values) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->FilterLock}; @@ -600,13 +592,12 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, + ALint *value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->FilterLock}; @@ -628,10 +619,9 @@ START_API_FUNC } } } -END_API_FUNC -AL_API void AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, + ALint *values) noexcept { switch(param) { @@ -640,8 +630,8 @@ START_API_FUNC return; } - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->FilterLock}; @@ -658,13 +648,12 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, + ALfloat *value) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->FilterLock}; @@ -681,13 +670,12 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC -AL_API void AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *values) -START_API_FUNC +FORCE_ALIGN void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, + ALfloat *values) noexcept { - ContextRef context{GetContextRef()}; - if(!context) UNLIKELY return; + if(!context) UNLIKELY + return; ALCdevice *device{context->mALDevice.get()}; std::lock_guard _{device->FilterLock}; @@ -704,7 +692,18 @@ START_API_FUNC context->setError(e.errorCode(), "%s", e.what()); } } -END_API_FUNC + +DECL_FUNC2(void, alGenFilters, ALsizei, ALuint*) +DECL_FUNC2(void, alDeleteFilters, ALsizei, const ALuint*) +DECL_FUNC1(ALboolean, alIsFilter, ALuint) +DECL_FUNC3(void, alFilterf, ALuint, ALenum, ALfloat) +DECL_FUNC3(void, alFilterfv, ALuint, ALenum, const ALfloat*) +DECL_FUNC3(void, alFilteri, ALuint, ALenum, ALint) +DECL_FUNC3(void, alFilteriv, ALuint, ALenum, const ALint*) +DECL_FUNC3(void, alGetFilterf, ALuint, ALenum, ALfloat*) +DECL_FUNC3(void, alGetFilterfv, ALuint, ALenum, ALfloat*) +DECL_FUNC3(void, alGetFilteri, ALuint, ALenum, ALint*) +DECL_FUNC3(void, alGetFilteriv, ALuint, ALenum, ALint*) FilterSubList::~FilterSubList() diff --git a/alc/alc.cpp b/alc/alc.cpp index 7d5b7ee0..bddc3384 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -546,6 +546,40 @@ const struct { DECL(alSourceQueueBuffersDirect), DECL(alSourceUnqueueBuffersDirect), + DECL(alGenFiltersDirect), + DECL(alDeleteFiltersDirect), + DECL(alIsFilterDirect), + DECL(alFilteriDirect), + DECL(alFilterivDirect), + DECL(alFilterfDirect), + DECL(alFilterfvDirect), + DECL(alGetFilteriDirect), + DECL(alGetFilterivDirect), + DECL(alGetFilterfDirect), + DECL(alGetFilterfvDirect), + DECL(alGenEffectsDirect), + DECL(alDeleteEffectsDirect), + DECL(alIsEffectDirect), + DECL(alEffectiDirect), + DECL(alEffectivDirect), + DECL(alEffectfDirect), + DECL(alEffectfvDirect), + DECL(alGetEffectiDirect), + DECL(alGetEffectivDirect), + DECL(alGetEffectfDirect), + DECL(alGetEffectfvDirect), + DECL(alGenAuxiliaryEffectSlotsDirect), + DECL(alDeleteAuxiliaryEffectSlotsDirect), + DECL(alIsAuxiliaryEffectSlotDirect), + DECL(alAuxiliaryEffectSlotiDirect), + DECL(alAuxiliaryEffectSlotivDirect), + DECL(alAuxiliaryEffectSlotfDirect), + DECL(alAuxiliaryEffectSlotfvDirect), + DECL(alGetAuxiliaryEffectSlotiDirect), + DECL(alGetAuxiliaryEffectSlotivDirect), + DECL(alGetAuxiliaryEffectSlotfDirect), + DECL(alGetAuxiliaryEffectSlotfvDirect), + DECL(alDeferUpdatesDirectSOFT), DECL(alProcessUpdatesDirectSOFT), DECL(alGetStringiDirectSOFT), -- cgit v1.2.3 From b80502e41d4d0fa0978bfa11b73803e5dfa45148 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 14 May 2023 19:44:06 -0700 Subject: Add extension strings for the in-progress direct API --- alc/alc.cpp | 2 ++ alc/context.cpp | 1 + 2 files changed, 3 insertions(+) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index bddc3384..8b108b51 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -1169,6 +1169,7 @@ constexpr ALCchar alcNoDeviceExtList[] = "ALC_ENUMERATE_ALL_EXT " "ALC_ENUMERATION_EXT " "ALC_EXT_CAPTURE " + "ALC_EXTX_direct_context " "ALC_EXT_EFX " "ALC_EXT_thread_local_context " "ALC_SOFT_loopback " @@ -1180,6 +1181,7 @@ constexpr ALCchar alcExtensionList[] = "ALC_EXT_CAPTURE " "ALC_EXTX_debug " "ALC_EXT_DEDICATED " + "ALC_EXTX_direct_context " "ALC_EXT_disconnect " "ALC_EXT_EFX " "ALC_EXT_thread_local_context " diff --git a/alc/context.cpp b/alc/context.cpp index 81529adf..bcd72f92 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -55,6 +55,7 @@ std::vector getContextExtensions() noexcept "AL_EXT_ALAW", "AL_EXT_BFORMAT", "AL_EXTX_debug", + "AL_EXTX_direct_context", "AL_EXT_DOUBLE", "AL_EXT_EXPONENT_DISTANCE", "AL_EXT_FLOAT32", -- cgit v1.2.3 From eca86489e422f00d96ce59a5c53fa45bdcea593e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 22 May 2023 02:25:30 -0700 Subject: Make the API functions noexcept Only relevant for C++, but these functions can't throw as it's a C-based API. Letting the compiler know that helps improve code generation. Extension callbacks must also not let exceptions leave the callback, or else Bad Things can happen. The macro AL_DISABLE_NOEXCEPT may be defined before including the headers to not mark functions as noexcept, but this should only be done if the caller can't otherwise be fixed. --- al/auxeffectslot.cpp | 16 +- al/buffer.cpp | 20 +- al/direct_defs.h | 52 ++-- al/error.cpp | 4 +- al/extension.cpp | 4 +- al/source.cpp | 18 +- al/state.cpp | 12 +- alc/alc.cpp | 124 +++------ alc/inprogext.h | 701 ++++++++++++++++++++++++------------------------ examples/alffplay.cpp | 12 +- examples/alstreamcb.cpp | 4 +- include/AL/al.h | 311 +++++++++++---------- include/AL/alc.h | 99 ++++--- include/AL/alext.h | 183 +++++++------ include/AL/efx.h | 136 +++++----- 15 files changed, 819 insertions(+), 877 deletions(-) (limited to 'alc') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index acc05f94..8fd158e8 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -420,8 +420,7 @@ FORCE_ALIGN ALboolean AL_APIENTRY alIsAuxiliaryEffectSlotDirect(ALCcontext *cont } -AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid) -START_API_FUNC +AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; @@ -442,10 +441,8 @@ START_API_FUNC AddActiveEffectSlots({&slot, 1}, context.get()); slot->mState = SlotState::Playing; } -END_API_FUNC -AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei n, const ALuint *slotids) -START_API_FUNC +AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei n, const ALuint *slotids) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; @@ -477,10 +474,8 @@ START_API_FUNC for(auto slot : slots) slot->mState = SlotState::Playing; } -END_API_FUNC -AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint slotid) -START_API_FUNC +AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint slotid) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; @@ -496,10 +491,8 @@ START_API_FUNC RemoveActiveEffectSlots({&slot, 1}, context.get()); slot->mState = SlotState::Stopped; } -END_API_FUNC -AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint *slotids) -START_API_FUNC +AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint *slotids) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; @@ -526,7 +519,6 @@ START_API_FUNC for(auto slot : slots) slot->mState = SlotState::Stopped; } -END_API_FUNC FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, diff --git a/al/buffer.cpp b/al/buffer.cpp index 01c9b5a4..7feac255 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -721,14 +721,12 @@ FORCE_ALIGN ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint b } -AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) -START_API_FUNC +AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) noexcept { auto context = GetContextRef(); if(!context) UNLIKELY return; alBufferStorageDirectSOFT(context.get(), buffer, format, data, size, freq, 0); } -END_API_FUNC FORCE_ALIGN void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) noexcept { alBufferStorageDirectSOFT(context, buffer, format, data, size, freq, 0); } @@ -1409,40 +1407,33 @@ AL_API DECL_FUNCEXT3(void, alGetBufferPtrv,SOFT, ALuint, ALenum, ALvoid**) AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint /*buffer*/, ALuint /*samplerate*/, ALenum /*internalformat*/, ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, - const ALvoid* /*data*/) -START_API_FUNC + const ALvoid* /*data*/) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; context->setError(AL_INVALID_OPERATION, "alBufferSamplesSOFT not supported"); } -END_API_FUNC AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint /*buffer*/, ALsizei /*offset*/, - ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, const ALvoid* /*data*/) -START_API_FUNC + ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, const ALvoid* /*data*/) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; context->setError(AL_INVALID_OPERATION, "alBufferSubSamplesSOFT not supported"); } -END_API_FUNC AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint /*buffer*/, ALsizei /*offset*/, - ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, ALvoid* /*data*/) -START_API_FUNC + ALsizei /*samples*/, ALenum /*channels*/, ALenum /*type*/, ALvoid* /*data*/) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; context->setError(AL_INVALID_OPERATION, "alGetBufferSamplesSOFT not supported"); } -END_API_FUNC -AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum /*format*/) -START_API_FUNC +AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum /*format*/) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return AL_FALSE; @@ -1450,7 +1441,6 @@ START_API_FUNC context->setError(AL_INVALID_OPERATION, "alIsBufferFormatSupportedSOFT not supported"); return AL_FALSE; } -END_API_FUNC BufferSubList::~BufferSubList() diff --git a/al/direct_defs.h b/al/direct_defs.h index e483fc71..d8946eb4 100644 --- a/al/direct_defs.h +++ b/al/direct_defs.h @@ -12,108 +12,108 @@ constexpr void DefaultVal() noexcept { } } // namespace detail_ #define DECL_FUNC(R, Name) \ -R AL_APIENTRY Name(void) START_API_FUNC \ +R AL_APIENTRY Name(void) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct(context.get()); \ -} END_API_FUNC +} #define DECL_FUNC1(R, Name, T1) \ -R AL_APIENTRY Name(T1 a) START_API_FUNC \ +R AL_APIENTRY Name(T1 a) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct(context.get(), a); \ -} END_API_FUNC +} #define DECL_FUNC2(R, Name, T1, T2) \ -R AL_APIENTRY Name(T1 a, T2 b) START_API_FUNC \ +R AL_APIENTRY Name(T1 a, T2 b) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct(context.get(), a, b); \ -} END_API_FUNC +} #define DECL_FUNC3(R, Name, T1, T2, T3) \ -R AL_APIENTRY Name(T1 a, T2 b, T3 c) START_API_FUNC \ +R AL_APIENTRY Name(T1 a, T2 b, T3 c) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct(context.get(), a, b, c); \ -} END_API_FUNC +} #define DECL_FUNC4(R, Name, T1, T2, T3, T4) \ -R AL_APIENTRY Name(T1 a, T2 b, T3 c, T4 d) START_API_FUNC \ +R AL_APIENTRY Name(T1 a, T2 b, T3 c, T4 d) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct(context.get(), a, b, c, d); \ -} END_API_FUNC +} #define DECL_FUNC5(R, Name, T1, T2, T3, T4, T5) \ -R AL_APIENTRY Name(T1 a, T2 b, T3 c, T4 d, T5 e) START_API_FUNC \ +R AL_APIENTRY Name(T1 a, T2 b, T3 c, T4 d, T5 e) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct(context.get(), a, b, c, d, e); \ -} END_API_FUNC +} #define DECL_FUNCEXT(R, Name,Ext) \ -R AL_APIENTRY Name##Ext(void) START_API_FUNC \ +R AL_APIENTRY Name##Ext(void) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct##Ext(context.get()); \ -} END_API_FUNC +} #define DECL_FUNCEXT1(R, Name,Ext, T1) \ -R AL_APIENTRY Name##Ext(T1 a) START_API_FUNC \ +R AL_APIENTRY Name##Ext(T1 a) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct##Ext(context.get(), a); \ -} END_API_FUNC +} #define DECL_FUNCEXT2(R, Name,Ext, T1, T2) \ -R AL_APIENTRY Name##Ext(T1 a, T2 b) START_API_FUNC \ +R AL_APIENTRY Name##Ext(T1 a, T2 b) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct##Ext(context.get(), a, b); \ -} END_API_FUNC +} #define DECL_FUNCEXT3(R, Name,Ext, T1, T2, T3) \ -R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c) START_API_FUNC \ +R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct##Ext(context.get(), a, b, c); \ -} END_API_FUNC +} #define DECL_FUNCEXT4(R, Name,Ext, T1, T2, T3, T4) \ -R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d) START_API_FUNC \ +R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct##Ext(context.get(), a, b, c, d); \ -} END_API_FUNC +} #define DECL_FUNCEXT5(R, Name,Ext, T1, T2, T3, T4, T5) \ -R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e) START_API_FUNC \ +R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct##Ext(context.get(), a, b, c, d, e); \ -} END_API_FUNC +} #define DECL_FUNCEXT6(R, Name,Ext, T1, T2, T3, T4, T5, T6) \ -R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f) START_API_FUNC \ +R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f) noexcept \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct##Ext(context.get(), a, b, c, d, e, f); \ -} END_API_FUNC +} #endif /* AL_DIRECT_DEFS_H */ diff --git a/al/error.cpp b/al/error.cpp index 8e6bb3b8..3a1a9ac3 100644 --- a/al/error.cpp +++ b/al/error.cpp @@ -93,7 +93,7 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...) /* Special-case alGetError since it (potentially) raises a debug signal and * returns a non-default value for a null context. */ -AL_API ALenum AL_APIENTRY alGetError(void) START_API_FUNC +AL_API ALenum AL_APIENTRY alGetError(void) noexcept { auto context = GetContextRef(); if(!context) UNLIKELY @@ -112,7 +112,7 @@ AL_API ALenum AL_APIENTRY alGetError(void) START_API_FUNC return deferror; } return alGetErrorDirect(context.get()); -} END_API_FUNC +} FORCE_ALIGN ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) noexcept { diff --git a/al/extension.cpp b/al/extension.cpp index edd30f88..6d1ac327 100644 --- a/al/extension.cpp +++ b/al/extension.cpp @@ -54,7 +54,7 @@ FORCE_ALIGN ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context } -AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName) +AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName) noexcept { if(!funcName) return nullptr; return alcGetProcAddress(nullptr, funcName); @@ -66,7 +66,7 @@ FORCE_ALIGN ALvoid* AL_APIENTRY alGetProcAddressDirect(ALCcontext*, const ALchar return alcGetProcAddress(nullptr, funcName); } -AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName) +AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName) noexcept { if(!enumName) return static_cast(0); return alcGetEnumValue(nullptr, enumName); diff --git a/al/source.cpp b/al/source.cpp index 0efc7fb9..8dbbbcd8 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -3555,28 +3555,16 @@ AL_API DECL_FUNCEXT5(void, alGetSource3i64,SOFT, ALuint, ALenum, ALint64SOFT*, A AL_API DECL_FUNCEXT3(void, alGetSourcei64v,SOFT, ALuint, ALenum, ALint64SOFT*) AL_API DECL_FUNC3(void, alSourceQueueBuffers, ALuint, ALsizei, const ALuint*) AL_API DECL_FUNC3(void, alSourceUnqueueBuffers, ALuint, ALsizei, ALuint*) -FORCE_ALIGN void AL_APIENTRY alSourcePlayAtTimeSOFT(ALuint source, ALint64SOFT time) START_API_FUNC -{ - auto context = GetContextRef(); - if(!context) UNLIKELY return; - return alSourcePlayAtTimeDirectSOFT(context.get(), source, time); -} END_API_FUNC -FORCE_ALIGN void AL_APIENTRY alSourcePlayAtTimevSOFT(ALsizei n, const ALuint *sources, ALint64SOFT time) START_API_FUNC -{ - auto context = GetContextRef(); - if(!context) UNLIKELY return; - return alSourcePlayAtTimevDirectSOFT(context.get(), n, sources, time); -} END_API_FUNC +FORCE_ALIGN DECL_FUNCEXT2(void, alSourcePlayAtTime,SOFT, ALuint, ALint64SOFT) +FORCE_ALIGN DECL_FUNCEXT3(void, alSourcePlayAtTimev,SOFT, ALsizei, const ALuint*, ALint64SOFT) -AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint, ALsizei, const ALuint*) -START_API_FUNC +AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint, ALsizei, const ALuint*) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; context->setError(AL_INVALID_OPERATION, "alSourceQueueBufferLayersSOFT not supported"); } -END_API_FUNC ALsource::ALsource() diff --git a/al/state.cpp b/al/state.cpp index 60d18818..2b6c1bb2 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -294,14 +294,12 @@ inline void UpdateProps(ALCcontext *context) /* WARNING: Non-standard export! Not part of any extension, or exposed in the * alcFunctions list. */ -AL_API const ALchar* AL_APIENTRY alsoft_get_version(void) -START_API_FUNC +AL_API const ALchar* AL_APIENTRY alsoft_get_version(void) noexcept { static const auto spoof = al::getenv("ALSOFT_SPOOF_VERSION"); if(spoof) return spoof->c_str(); return ALSOFT_VERSION; } -END_API_FUNC FORCE_ALIGN void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) noexcept @@ -380,14 +378,14 @@ FORCE_ALIGN ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum } #define DECL_GETFUNC(R, Name, Ext) \ -AL_API R AL_APIENTRY Name##Ext(ALenum pname) START_API_FUNC \ +AL_API R AL_APIENTRY Name##Ext(ALenum pname) noexcept \ { \ R value{}; \ auto context = GetContextRef(); \ if(!context) UNLIKELY return value; \ Name##vDirect##Ext(GetContextRef().get(), pname, &value); \ return value; \ -} END_API_FUNC \ +} \ FORCE_ALIGN R AL_APIENTRY Name##Direct##Ext(ALCcontext *context, ALenum pname) noexcept \ { \ R value{}; \ @@ -614,7 +612,7 @@ AL_API DECL_FUNCEXT(void, alDeferUpdates,SOFT) AL_API DECL_FUNCEXT(void, alProcessUpdates,SOFT) AL_API DECL_FUNCEXT2(const ALchar*, alGetStringi,SOFT, ALenum,ALsizei) -AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) START_API_FUNC +AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; @@ -633,7 +631,7 @@ AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) START_API_FUNC context->mDopplerVelocity = value; UpdateProps(context.get()); } -} END_API_FUNC +} void UpdateContextProps(ALCcontext *context) diff --git a/alc/alc.cpp b/alc/alc.cpp index 8b108b51..3cad507e 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2759,18 +2759,15 @@ ContextRef GetContextRef(void) * Standard ALC functions ************************************************/ -ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) -START_API_FUNC +ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) noexcept { DeviceRef dev{VerifyDevice(device)}; if(dev) return dev->LastError.exchange(ALC_NO_ERROR); return LastNullDeviceError.exchange(ALC_NO_ERROR); } -END_API_FUNC -ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context) -START_API_FUNC +ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context) noexcept { ContextRef ctx{VerifyContext(context)}; if(!ctx) @@ -2792,10 +2789,8 @@ START_API_FUNC ctx->deferUpdates(); } } -END_API_FUNC -ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context) -START_API_FUNC +ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context) noexcept { ContextRef ctx{VerifyContext(context)}; if(!ctx) @@ -2817,11 +2812,9 @@ START_API_FUNC ctx->processUpdates(); } } -END_API_FUNC -ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param) -START_API_FUNC +ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param) noexcept { const ALCchar *value{nullptr}; @@ -2940,7 +2933,6 @@ START_API_FUNC return value; } -END_API_FUNC static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span values) @@ -3264,8 +3256,7 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span return 0; } -ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) -START_API_FUNC +ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) noexcept { DeviceRef dev{VerifyDevice(device)}; if(size <= 0 || values == nullptr) @@ -3273,10 +3264,8 @@ START_API_FUNC else GetIntegerv(dev.get(), param, {values, static_cast(size)}); } -END_API_FUNC -ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values) -START_API_FUNC +ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values) noexcept { DeviceRef dev{VerifyDevice(device)}; if(size <= 0 || values == nullptr) @@ -3411,11 +3400,9 @@ START_API_FUNC break; } } -END_API_FUNC -ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName) -START_API_FUNC +ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName) noexcept { DeviceRef dev{VerifyDevice(device)}; if(!extName) @@ -3439,11 +3426,9 @@ START_API_FUNC } return ALC_FALSE; } -END_API_FUNC -ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName) -START_API_FUNC +ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName) noexcept { if(!funcName) { @@ -3468,11 +3453,9 @@ START_API_FUNC } return nullptr; } -END_API_FUNC -ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName) -START_API_FUNC +ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName) noexcept { if(!enumName) { @@ -3498,11 +3481,9 @@ START_API_FUNC return 0; } -END_API_FUNC -ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList) -START_API_FUNC +ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList) noexcept { /* Explicitly hold the list lock while taking the StateLock in case the * device is asynchronously destroyed, to ensure this new context is @@ -3606,10 +3587,8 @@ START_API_FUNC TRACE("Created context %p\n", voidp{context.get()}); return context.release(); } -END_API_FUNC -ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context) -START_API_FUNC +ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context) noexcept { std::unique_lock listlock{ListLock}; auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context); @@ -3635,26 +3614,20 @@ START_API_FUNC Device->Flags.reset(DeviceRunning); } } -END_API_FUNC -ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void) -START_API_FUNC +ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void) noexcept { ALCcontext *Context{ALCcontext::getThreadContext()}; if(!Context) Context = ALCcontext::sGlobalContext.load(); return Context; } -END_API_FUNC /** Returns the currently active thread-local context. */ -ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void) -START_API_FUNC +ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void) noexcept { return ALCcontext::getThreadContext(); } -END_API_FUNC -ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) -START_API_FUNC +ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) noexcept { /* context must be valid or nullptr */ ContextRef ctx; @@ -3688,11 +3661,9 @@ START_API_FUNC return ALC_TRUE; } -END_API_FUNC /** Makes the given context the active context for the current thread. */ -ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context) -START_API_FUNC +ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context) noexcept { /* context must be valid or nullptr */ ContextRef ctx; @@ -3711,11 +3682,9 @@ START_API_FUNC return ALC_TRUE; } -END_API_FUNC -ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context) -START_API_FUNC +ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context) noexcept { ContextRef ctx{VerifyContext(Context)}; if(!ctx) @@ -3725,11 +3694,9 @@ START_API_FUNC } return ctx->mALDevice.get(); } -END_API_FUNC -ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) -START_API_FUNC +ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) noexcept { InitConfig(); @@ -3807,10 +3774,8 @@ START_API_FUNC TRACE("Created device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str()); return device.release(); } -END_API_FUNC -ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) -START_API_FUNC +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) noexcept { std::unique_lock listlock{ListLock}; auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device); @@ -3857,14 +3822,12 @@ START_API_FUNC return ALC_TRUE; } -END_API_FUNC /************************************************ * ALC capture functions ************************************************/ -ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples) -START_API_FUNC +ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples) noexcept { InitConfig(); @@ -3935,10 +3898,8 @@ START_API_FUNC TRACE("Created capture device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str()); return device.release(); } -END_API_FUNC -ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) -START_API_FUNC +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) noexcept { std::unique_lock listlock{ListLock}; auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device); @@ -3964,10 +3925,8 @@ START_API_FUNC return ALC_TRUE; } -END_API_FUNC -ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) -START_API_FUNC +ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) noexcept { DeviceRef dev{VerifyDevice(device)}; if(!dev || dev->Type != DeviceType::Capture) @@ -3993,10 +3952,8 @@ START_API_FUNC } } } -END_API_FUNC -ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device) -START_API_FUNC +ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device) noexcept { DeviceRef dev{VerifyDevice(device)}; if(!dev || dev->Type != DeviceType::Capture) @@ -4009,10 +3966,8 @@ START_API_FUNC dev->Flags.reset(DeviceRunning); } } -END_API_FUNC -ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) -START_API_FUNC +ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) noexcept { DeviceRef dev{VerifyDevice(device)}; if(!dev || dev->Type != DeviceType::Capture) @@ -4041,7 +3996,6 @@ START_API_FUNC backend->captureSamples(static_cast(buffer), usamples); } -END_API_FUNC /************************************************ @@ -4049,8 +4003,7 @@ END_API_FUNC ************************************************/ /** Open a loopback device, for manual rendering. */ -ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName) -START_API_FUNC +ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName) noexcept { InitConfig(); @@ -4107,13 +4060,11 @@ START_API_FUNC TRACE("Created loopback device %p\n", voidp{device.get()}); return device.release(); } -END_API_FUNC /** * Determines if the loopback device supports the given format for rendering. */ -ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type) -START_API_FUNC +ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type) noexcept { DeviceRef dev{VerifyDevice(device)}; if(!dev || dev->Type != DeviceType::Loopback) @@ -4129,14 +4080,12 @@ START_API_FUNC return ALC_FALSE; } -END_API_FUNC /** * Renders some samples into a buffer, using the format last set by the * attributes given to alcCreateContext. */ -FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) -START_API_FUNC +FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) noexcept { if(!device || device->Type != DeviceType::Loopback) alcSetError(device, ALC_INVALID_DEVICE); @@ -4145,7 +4094,6 @@ START_API_FUNC else device->renderSamples(buffer, static_cast(samples), device->channelsFromFmt()); } -END_API_FUNC /************************************************ @@ -4153,8 +4101,7 @@ END_API_FUNC ************************************************/ /** Pause the DSP to stop audio processing. */ -ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device) -START_API_FUNC +ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device) noexcept { DeviceRef dev{VerifyDevice(device)}; if(!dev || dev->Type != DeviceType::Playback) @@ -4168,11 +4115,9 @@ START_API_FUNC dev->Flags.set(DevicePaused); } } -END_API_FUNC /** Resume the DSP to restart audio processing. */ -ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device) -START_API_FUNC +ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device) noexcept { DeviceRef dev{VerifyDevice(device)}; if(!dev || dev->Type != DeviceType::Playback) @@ -4203,7 +4148,6 @@ START_API_FUNC DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), device->Frequency, device->UpdateSize, device->BufferSize); } -END_API_FUNC /************************************************ @@ -4211,8 +4155,7 @@ END_API_FUNC ************************************************/ /** Gets a string parameter at the given index. */ -ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index) -START_API_FUNC +ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index) noexcept { DeviceRef dev{VerifyDevice(device)}; if(!dev || dev->Type == DeviceType::Capture) @@ -4232,11 +4175,9 @@ START_API_FUNC return nullptr; } -END_API_FUNC /** Resets the given device output, using the specified attribute list. */ -ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs) -START_API_FUNC +ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs) noexcept { std::unique_lock listlock{ListLock}; DeviceRef dev{VerifyDevice(device)}; @@ -4258,7 +4199,6 @@ START_API_FUNC return ResetDeviceParams(dev.get(), attribs) ? ALC_TRUE : ALC_FALSE; } -END_API_FUNC /************************************************ @@ -4267,8 +4207,7 @@ END_API_FUNC /** Reopens the given device output, using the specified name and attribute list. */ FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, - const ALCchar *deviceName, const ALCint *attribs) -START_API_FUNC + const ALCchar *deviceName, const ALCint *attribs) noexcept { if(deviceName) { @@ -4343,4 +4282,3 @@ START_API_FUNC ResetDeviceParams(dev.get(), attribs); return ALC_TRUE; } -END_API_FUNC diff --git a/alc/inprogext.h b/alc/inprogext.h index 00629a9f..38ef2bf8 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -16,23 +16,23 @@ typedef unsigned int ALbitfieldSOFT; #define AL_MAP_WRITE_BIT_SOFT 0x00000002 #define AL_MAP_PERSISTENT_BIT_SOFT 0x00000004 #define AL_PRESERVE_DATA_BIT_SOFT 0x00000008 -typedef void (AL_APIENTRY*LPALBUFFERSTORAGESOFT)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags); -typedef void* (AL_APIENTRY*LPALMAPBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access); -typedef void (AL_APIENTRY*LPALUNMAPBUFFERSOFT)(ALuint buffer); -typedef void (AL_APIENTRY*LPALFLUSHMAPPEDBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length); -typedef void (AL_APIENTRY*LPALBUFFERSTORAGEDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags); -typedef void* (AL_APIENTRY*LPALMAPBUFFERDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access); -typedef void (AL_APIENTRY*LPALUNMAPBUFFERDIRECTSOFT)(ALCcontext *context, ALuint buffer); -typedef void (AL_APIENTRY*LPALFLUSHMAPPEDBUFFERDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length); +typedef void (AL_APIENTRY*LPALBUFFERSTORAGESOFT)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY*LPALMAPBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALUNMAPBUFFERSOFT)(ALuint buffer) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALFLUSHMAPPEDBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALBUFFERSTORAGEDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY*LPALMAPBUFFERDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALUNMAPBUFFERDIRECTSOFT)(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALFLUSHMAPPEDBUFFERDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags); -AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access); -AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer); -AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length); -void AL_APIENTRY alBufferStorageDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags) noexcept; -void* AL_APIENTRY alMapBufferDirectSOFT(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access) noexcept; -void AL_APIENTRY alUnmapBufferDirectSOFT(ALCcontext *context, ALuint buffer) noexcept; -void AL_APIENTRY alFlushMappedBufferDirectSOFT(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length) noexcept; +AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags) AL_API_NOEXCEPT; +AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferStorageDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags) AL_API_NOEXCEPT; +void* AL_APIENTRY alMapBufferDirectSOFT(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access) AL_API_NOEXCEPT; +void AL_APIENTRY alUnmapBufferDirectSOFT(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT; +void AL_APIENTRY alFlushMappedBufferDirectSOFT(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length) AL_API_NOEXCEPT; #endif #endif @@ -45,15 +45,15 @@ void AL_APIENTRY alFlushMappedBufferDirectSOFT(ALCcontext *context, ALuint buffe #define AL_SOFT_convolution_reverb #define AL_EFFECT_CONVOLUTION_REVERB_SOFT 0xA000 #define AL_EFFECTSLOT_STATE_SOFT 0x199D -typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYSOFT)(ALuint slotid); -typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYVSOFT)(ALsizei n, const ALuint *slotids); -typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTSTOPSOFT)(ALuint slotid); -typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTSTOPVSOFT)(ALsizei n, const ALuint *slotids); +typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYSOFT)(ALuint slotid) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYVSOFT)(ALsizei n, const ALuint *slotids) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTSTOPSOFT)(ALuint slotid) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTSTOPVSOFT)(ALsizei n, const ALuint *slotids) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid); -AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei n, const ALuint *slotids); -AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint slotid); -AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint *slotids); +AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei n, const ALuint *slotids) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint slotid) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint *slotids) AL_API_NOEXCEPT; #endif #endif @@ -101,361 +101,360 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_STACK_UNDERFLOW_EXT 0x19CD #define AL_CONTEXT_FLAGS_EXT 0x19CE -typedef void (AL_APIENTRY*ALDEBUGPROCEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam); -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKEXT)(ALDEBUGPROCEXT callback, void *userParam); -typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLEXT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable); -typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPEXT)(ALenum source, ALuint id, ALsizei length, const ALchar *message); -typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void); -typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf); -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKDIRECTEXT)(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam); -typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable); -typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPDIRECTEXT)(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message); -typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPDIRECTEXT)(ALCcontext *context); -typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGDIRECTEXT)(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf); +typedef void (AL_APIENTRY*ALDEBUGPROCEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKEXT)(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLEXT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPEXT)(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void) AL_API_NOEXCEPT17; +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKDIRECTEXT)(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPDIRECTEXT)(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPDIRECTEXT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGDIRECTEXT)(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) noexcept; -void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; -void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept; -void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept; -void AL_APIENTRY alPopDebugGroupEXT(void) noexcept; -ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept; -void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) noexcept; -void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept; -void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept; -void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) noexcept; -void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) noexcept; -ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept; +void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alPopDebugGroupEXT(void) AL_API_NOEXCEPT; +ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) AL_API_NOEXCEPT; +ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; #endif #endif #ifndef AL_EXT_direct_context #define AL_EXT_direct_context -typedef void (AL_APIENTRY *LPALENABLEDIRECT)(ALCcontext *context, ALenum capability); -typedef void (AL_APIENTRY *LPALDISABLEDIRECT)(ALCcontext *context, ALenum capability); -typedef ALboolean (AL_APIENTRY *LPALISENABLEDDIRECT)(ALCcontext *context, ALenum capability); -typedef void (AL_APIENTRY *LPALDOPPLERFACTORDIRECT)(ALCcontext *context, ALfloat value); -typedef void (AL_APIENTRY *LPALSPEEDOFSOUNDDIRECT)(ALCcontext *context, ALfloat value); -typedef void (AL_APIENTRY *LPALDISTANCEMODELDIRECT)(ALCcontext *context, ALenum distanceModel); -typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGDIRECT)(ALCcontext *context, ALenum param); -typedef void (AL_APIENTRY *LPALGETBOOLEANVDIRECT)(ALCcontext *context, ALenum param, ALboolean *values); -typedef void (AL_APIENTRY *LPALGETINTEGERVDIRECT)(ALCcontext *context, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGETFLOATVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETDOUBLEVDIRECT)(ALCcontext *context, ALenum param, ALdouble *values); -typedef ALboolean (AL_APIENTRY *LPALGETBOOLEANDIRECT)(ALCcontext *context, ALenum param); -typedef ALint (AL_APIENTRY *LPALGETINTEGERDIRECT)(ALCcontext *context, ALenum param); -typedef ALfloat (AL_APIENTRY *LPALGETFLOATDIRECT)(ALCcontext *context, ALenum param); -typedef ALdouble (AL_APIENTRY *LPALGETDOUBLEDIRECT)(ALCcontext *context, ALenum param); -typedef ALenum (AL_APIENTRY *LPALGETERRORDIRECT)(ALCcontext *context); -typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENTDIRECT)(ALCcontext *context, const ALchar *extname); -typedef void* (AL_APIENTRY *LPALGETPROCADDRESSDIRECT)(ALCcontext *context, const ALchar *fname); -typedef ALenum (AL_APIENTRY *LPALGETENUMVALUEDIRECT)(ALCcontext *context, const ALchar *ename); -typedef void (AL_APIENTRY *LPALLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALLISTENERFVDIRECT)(ALCcontext *context, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALLISTENERIVDIRECT)(ALCcontext *context, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETLISTENERFVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETLISTENERIVDIRECT)(ALCcontext *context, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGENSOURCESDIRECT)(ALCcontext *context, ALsizei n, ALuint *sources); -typedef void (AL_APIENTRY *LPALDELETESOURCESDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources); -typedef ALboolean (AL_APIENTRY *LPALISSOURCEDIRECT)(ALCcontext *context, ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALSOURCEPLAYVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCESTOPVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEREWINDVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEPAUSEVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEPLAYDIRECT)(ALCcontext *context, ALuint source); -typedef void (AL_APIENTRY *LPALSOURCESTOPDIRECT)(ALCcontext *context, ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEREWINDDIRECT)(ALCcontext *context, ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEPAUSEDIRECT)(ALCcontext *context, ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers); -typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers); -typedef void (AL_APIENTRY *LPALGENBUFFERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *buffers); -typedef void (AL_APIENTRY *LPALDELETEBUFFERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers); -typedef ALboolean (AL_APIENTRY *LPALISBUFFERDIRECT)(ALCcontext *context, ALuint buffer); -typedef void (AL_APIENTRY *LPALBUFFERDATADIRECT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate); -typedef void (AL_APIENTRY *LPALBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALENABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISENABLEDDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDOPPLERFACTORDIRECT)(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSPEEDOFSOUNDDIRECT)(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISTANCEMODELDIRECT)(ALCcontext *context, ALenum distanceModel) AL_API_NOEXCEPT17; +typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBOOLEANVDIRECT)(ALCcontext *context, ALenum param, ALboolean *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETINTEGERVDIRECT)(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFLOATVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETDOUBLEVDIRECT)(ALCcontext *context, ALenum param, ALdouble *values) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEANDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALint (AL_APIENTRY *LPALGETINTEGERDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALfloat (AL_APIENTRY *LPALGETFLOATDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLEDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETERRORDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENTDIRECT)(ALCcontext *context, const ALchar *extname) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY *LPALGETPROCADDRESSDIRECT)(ALCcontext *context, const ALchar *fname) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUEDIRECT)(ALCcontext *context, const ALchar *ename) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERFVDIRECT)(ALCcontext *context, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERIVDIRECT)(ALCcontext *context, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERFVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERIVDIRECT)(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENSOURCESDIRECT)(ALCcontext *context, ALsizei n, ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETESOURCESDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISSOURCEDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOPVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWINDVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSEVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOPDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWINDDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSEDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENBUFFERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEBUFFERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISBUFFERDIRECT)(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERDATADIRECT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT17; /* ALC_EXT_EFX */ -typedef void (AL_APIENTRY *LPALGENEFFECTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effects); -typedef void (AL_APIENTRY *LPALDELETEEFFECTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effects); -typedef ALboolean (AL_APIENTRY *LPALISEFFECTDIRECT)(ALCcontext *context, ALuint effect); -typedef void (AL_APIENTRY *LPALEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALGETEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGETEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGENFILTERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *filters); -typedef void (AL_APIENTRY *LPALDELETEFILTERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *filters); -typedef ALboolean (AL_APIENTRY *LPALISFILTERDIRECT)(ALCcontext *context, ALuint filter); -typedef void (AL_APIENTRY *LPALFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALGETFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGETFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effectslots); -typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effectslots); -typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOTDIRECT)(ALCcontext *context, ALuint effectslot); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGENEFFECTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effects) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEEFFECTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effects) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEFFECTDIRECT)(ALCcontext *context, ALuint effect) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENFILTERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *filters) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEFILTERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *filters) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISFILTERDIRECT)(ALCcontext *context, ALuint filter) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOTDIRECT)(ALCcontext *context, ALuint effectslot) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; /* AL_EXT_BUFFER_DATA_STATIC */ -typedef void (AL_APIENTRY *LPALBUFFERDATASTATICDIRECT)(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq); +typedef void (AL_APIENTRY *LPALBUFFERDATASTATICDIRECT)(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT17; /* AL_SOFT_buffer_sub_data */ -typedef void (AL_APIENTRY *LPALBUFFERSUBDATADIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length); +typedef void (AL_APIENTRY *LPALBUFFERSUBDATADIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT17; /* AL_EXT_FOLDBACK */ -typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTARTDIRECT)(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback); -typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTOPDIRECT)(ALCcontext *context); +typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTARTDIRECT)(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTOPDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; /* AL_SOFT_source_latency */ -typedef void (AL_APIENTRY *LPALSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble); -typedef void (AL_APIENTRY *LPALSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble,ALdouble,ALdouble); -typedef void (AL_APIENTRY *LPALSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALdouble*); -typedef void (AL_APIENTRY *LPALGETSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY *LPALGETSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*); -typedef void (AL_APIENTRY *LPALGETSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY *LPALSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT); -typedef void (AL_APIENTRY *LPALSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT); -typedef void (AL_APIENTRY *LPALSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALint64SOFT*); -typedef void (AL_APIENTRY *LPALGETSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*); -typedef void (AL_APIENTRY *LPALGETSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*); -typedef void (AL_APIENTRY *LPALGETSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*); +typedef void (AL_APIENTRY *LPALSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble,ALdouble,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; /* AL_SOFT_deferred_updates */ -typedef void (AL_APIENTRY *LPALDEFERUPDATESDIRECTSOFT)(ALCcontext *context); -typedef void (AL_APIENTRY *LPALPROCESSUPDATESDIRECTSOFT)(ALCcontext *context); +typedef void (AL_APIENTRY *LPALDEFERUPDATESDIRECTSOFT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALPROCESSUPDATESDIRECTSOFT)(ALCcontext *context) AL_API_NOEXCEPT17; /* AL_SOFT_source_resampler */ -typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGIDIRECTSOFT)(ALCcontext *context, ALenum pname, ALsizei index); +typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGIDIRECTSOFT)(ALCcontext *context, ALenum pname, ALsizei index) AL_API_NOEXCEPT17; /* AL_SOFT_events */ -typedef void (AL_APIENTRY *LPALEVENTCONTROLDIRECTSOFT)(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable); -typedef void (AL_APIENTRY *LPALEVENTCALLBACKDIRECTSOFT)(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam); -typedef void* (AL_APIENTRY *LPALGETPOINTERDIRECTSOFT)(ALCcontext *context, ALenum pname); -typedef void (AL_APIENTRY *LPALGETPOINTERVDIRECTSOFT)(ALCcontext *context, ALenum pname, void **values); +typedef void (AL_APIENTRY *LPALEVENTCONTROLDIRECTSOFT)(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEVENTCALLBACKDIRECTSOFT)(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY *LPALGETPOINTERDIRECTSOFT)(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETPOINTERVDIRECTSOFT)(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT17; /* AL_SOFT_callback_buffer */ -typedef void (AL_APIENTRY *LPALBUFFERCALLBACKDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); -typedef void (AL_APIENTRY *LPALGETBUFFERPTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value); -typedef void (AL_APIENTRY *LPALGETBUFFER3PTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3); -typedef void (AL_APIENTRY *LPALGETBUFFERPTRVDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **values); +typedef void (AL_APIENTRY *LPALBUFFERCALLBACKDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERPTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3PTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERPTRVDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **values) AL_API_NOEXCEPT17; /* AL_SOFT_source_start_delay */ -typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEDIRECTSOFT)(ALCcontext *context, ALuint source, ALint64SOFT start_time); -typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEVDIRECTSOFT)(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time); +typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEDIRECTSOFT)(ALCcontext *context, ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEVDIRECTSOFT)(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT17; /* EAX */ -typedef ALenum (AL_APIENTRY *LPEAXSETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_buffer, ALuint property_size); -typedef ALenum (AL_APIENTRY *LPEAXGETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size); -typedef ALboolean (AL_APIENTRY *LPEAXSETBUFFERMODEDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value); -typedef ALenum (AL_APIENTRY *LPEAXGETBUFFERMODEDIRECT)(ALCcontext *context, ALuint buffer, ALint *pReserved); +typedef ALenum (AL_APIENTRY *LPEAXSETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_buffer, ALuint property_size) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPEAXGETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPEAXSETBUFFERMODEDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPEAXGETBUFFERMODEDIRECT)(ALCcontext *context, ALuint buffer, ALint *pReserved) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) noexcept; -void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability) noexcept; -ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability) noexcept; - -void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value) noexcept; -void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value) noexcept; -void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum distanceModel) noexcept; - -const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALenum param) noexcept; -void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum param, ALboolean *values) noexcept; -void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum param, ALint *values) noexcept; -void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum param, ALfloat *values) noexcept; -void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum param, ALdouble *values) noexcept; -ALboolean AL_APIENTRY alGetBooleanDirect(ALCcontext *context, ALenum param) noexcept; -ALint AL_APIENTRY alGetIntegerDirect(ALCcontext *context, ALenum param) noexcept; -ALfloat AL_APIENTRY alGetFloatDirect(ALCcontext *context, ALenum param) noexcept; -ALdouble AL_APIENTRY alGetDoubleDirect(ALCcontext *context, ALenum param) noexcept; - -ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) noexcept; -ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extname) noexcept; -void* AL_APIENTRY alGetProcAddressDirect(ALCcontext *context, const ALchar *fname) noexcept; -ALenum AL_APIENTRY alGetEnumValueDirect(ALCcontext *context, const ALchar *ename) noexcept; - -void AL_APIENTRY alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value) noexcept; -void AL_APIENTRY alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) noexcept; -void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum param, const ALfloat *values) noexcept; -void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint value) noexcept; -void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) noexcept; -void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum param, const ALint *values) noexcept; -void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum param, ALfloat *value) noexcept; -void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept; -void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum param, ALfloat *values) noexcept; -void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value) noexcept; -void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) noexcept; -void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum param, ALint *values) noexcept; - -void AL_APIENTRY alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources) noexcept; -void AL_APIENTRY alDeleteSourcesDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept; -ALboolean AL_APIENTRY alIsSourceDirect(ALCcontext *context, ALuint source) noexcept; -void AL_APIENTRY alSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value) noexcept; -void AL_APIENTRY alSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) noexcept; -void AL_APIENTRY alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) noexcept; -void AL_APIENTRY alSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint value) noexcept; -void AL_APIENTRY alSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) noexcept; -void AL_APIENTRY alSourceivDirect(ALCcontext *context, ALuint source, ALenum param, const ALint *values) noexcept; -void AL_APIENTRY alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) noexcept; -void AL_APIENTRY alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept; -void AL_APIENTRY alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) noexcept; -void AL_APIENTRY alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value) noexcept; -void AL_APIENTRY alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) noexcept; -void AL_APIENTRY alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param, ALint *values) noexcept; -void AL_APIENTRY alSourcePlayDirect(ALCcontext *context, ALuint source) noexcept; -void AL_APIENTRY alSourceStopDirect(ALCcontext *context, ALuint source) noexcept; -void AL_APIENTRY alSourceRewindDirect(ALCcontext *context, ALuint source) noexcept; -void AL_APIENTRY alSourcePauseDirect(ALCcontext *context, ALuint source) noexcept; -void AL_APIENTRY alSourcePlayvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept; -void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept; -void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept; -void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept; -void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) noexcept; -void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) noexcept; - -void AL_APIENTRY alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers) noexcept; -void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei n, const ALuint *buffers) noexcept; -ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint buffer) noexcept; -void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) noexcept; -void AL_APIENTRY alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) noexcept; -void AL_APIENTRY alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) noexcept; -void AL_APIENTRY alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) noexcept; -void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value) noexcept; -void AL_APIENTRY alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) noexcept; -void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) noexcept; -void AL_APIENTRY alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) noexcept; -void AL_APIENTRY alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept; -void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) noexcept; -void AL_APIENTRY alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) noexcept; -void AL_APIENTRY alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) noexcept; -void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) noexcept; - -void AL_APIENTRY alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects) noexcept; -void AL_APIENTRY alDeleteEffectsDirect(ALCcontext *context, ALsizei n, const ALuint *effects) noexcept; -ALboolean AL_APIENTRY alIsEffectDirect(ALCcontext *context, ALuint effect) noexcept; -void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint iValue) noexcept; -void AL_APIENTRY alEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, const ALint *piValues) noexcept; -void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat flValue) noexcept; -void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *pflValues) noexcept; -void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValue) noexcept; -void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValues) noexcept; -void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValue) noexcept; -void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValues) noexcept; - -void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) noexcept; -void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei n, const ALuint *filters) noexcept; -ALboolean AL_APIENTRY alIsFilterDirect(ALCcontext *context, ALuint filter) noexcept; -void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint iValue) noexcept; -void AL_APIENTRY alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, const ALint *piValues) noexcept; -void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat flValue) noexcept; -void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *pflValues) noexcept; -void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValue) noexcept; -void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValues) noexcept; -void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValue) noexcept; -void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValues) noexcept; - -void AL_APIENTRY alGenAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, ALuint *effectslots) noexcept; -void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, const ALuint *effectslots) noexcept; -ALboolean AL_APIENTRY alIsAuxiliaryEffectSlotDirect(ALCcontext *context, ALuint effectslot) noexcept; -void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint iValue) noexcept; -void AL_APIENTRY alAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *piValues) noexcept; -void AL_APIENTRY alAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat flValue) noexcept; -void AL_APIENTRY alAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *pflValues) noexcept; -void AL_APIENTRY alGetAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValue) noexcept; -void AL_APIENTRY alGetAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValues) noexcept; -void AL_APIENTRY alGetAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValue) noexcept; -void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValues) noexcept; - -void AL_APIENTRY alBufferDataStaticDirect(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) noexcept; - -void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) noexcept; - -void AL_APIENTRY alRequestFoldbackStartDirect(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) noexcept; -void AL_APIENTRY alRequestFoldbackStopDirect(ALCcontext *context) noexcept; - -void AL_APIENTRY alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value) noexcept; -void AL_APIENTRY alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) noexcept; -void AL_APIENTRY alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALdouble *values) noexcept; -void AL_APIENTRY alGetSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value) noexcept; -void AL_APIENTRY alGetSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) noexcept; -void AL_APIENTRY alGetSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *values) noexcept; -void AL_APIENTRY alSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value) noexcept; -void AL_APIENTRY alSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) noexcept; -void AL_APIENTRY alSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALint64SOFT *values) noexcept; -void AL_APIENTRY alGetSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value) noexcept; -void AL_APIENTRY alGetSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) noexcept; -void AL_APIENTRY alGetSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *values) noexcept; - -ALint64SOFT AL_APIENTRY alGetInteger64DirectSOFT(ALCcontext *context, ALenum pname) noexcept; -void AL_APIENTRY alGetInteger64vDirectSOFT(ALCcontext *context, ALenum pname, ALint64SOFT *values) noexcept; - -void AL_APIENTRY alDeferUpdatesDirectSOFT(ALCcontext *context) noexcept; -void AL_APIENTRY alProcessUpdatesDirectSOFT(ALCcontext *context) noexcept; - -const ALchar* AL_APIENTRY alGetStringiDirectSOFT(ALCcontext *context, ALenum pname, ALsizei index) noexcept; - -void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) noexcept; -void AL_APIENTRY alEventCallbackDirectSOFT(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) noexcept; -void* AL_APIENTRY alGetPointerDirectSOFT(ALCcontext *context, ALenum pname) noexcept; -void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, void **values) noexcept; - -void AL_APIENTRY alBufferCallbackDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) noexcept; -void AL_APIENTRY alGetBufferPtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) noexcept; -void AL_APIENTRY alGetBuffer3PtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2) noexcept; -void AL_APIENTRY alGetBufferPtrvDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) noexcept; - -void AL_APIENTRY alSourcePlayAtTimeDirectSOFT(ALCcontext *context, ALuint source, ALint64SOFT start_time) noexcept; -void AL_APIENTRY alSourcePlayAtTimevDirectSOFT(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) noexcept; - -ALenum AL_APIENTRY EAXSetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept; -ALenum AL_APIENTRY EAXGetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept; -ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) noexcept; -ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, ALint *pReserved) noexcept; +void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; +void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; + +void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum distanceModel) AL_API_NOEXCEPT; + +const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum param, ALboolean *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum param, ALdouble *values) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alGetBooleanDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALint AL_APIENTRY alGetIntegerDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALfloat AL_APIENTRY alGetFloatDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALdouble AL_APIENTRY alGetDoubleDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; + +ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extname) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetProcAddressDirect(ALCcontext *context, const ALchar *fname) AL_API_NOEXCEPT; +ALenum AL_APIENTRY alGetEnumValueDirect(ALCcontext *context, const ALchar *ename) AL_API_NOEXCEPT; + +void AL_APIENTRY alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteSourcesDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsSourceDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceivDirect(ALCcontext *context, ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceStopDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceRewindDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePauseDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteEffectsDirect(ALCcontext *context, ALsizei n, const ALuint *effects) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsEffectDirect(ALCcontext *context, ALuint effect) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei n, const ALuint *filters) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsFilterDirect(ALCcontext *context, ALuint filter) AL_API_NOEXCEPT; +void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsAuxiliaryEffectSlotDirect(ALCcontext *context, ALuint effectslot) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferDataStaticDirect(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT; + +void AL_APIENTRY alRequestFoldbackStartDirect(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT; +void AL_APIENTRY alRequestFoldbackStopDirect(ALCcontext *context) AL_API_NOEXCEPT; + +void AL_APIENTRY alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALdouble *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALint64SOFT *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alDeferUpdatesDirectSOFT(ALCcontext *context) AL_API_NOEXCEPT; +void AL_APIENTRY alProcessUpdatesDirectSOFT(ALCcontext *context) AL_API_NOEXCEPT; + +const ALchar* AL_APIENTRY alGetStringiDirectSOFT(ALCcontext *context, ALenum pname, ALsizei index) AL_API_NOEXCEPT; + +void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alEventCallbackDirectSOFT(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetPointerDirectSOFT(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT; +void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferCallbackDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferPtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3PtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferPtrvDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; + +void AL_APIENTRY alSourcePlayAtTimeDirectSOFT(ALCcontext *context, ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayAtTimevDirectSOFT(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT; + +ALenum AL_APIENTRY EAXSetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) AL_API_NOEXCEPT; +ALenum AL_APIENTRY EAXGetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) AL_API_NOEXCEPT; +ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, ALint *pReserved) AL_API_NOEXCEPT; #endif #endif /* Non-standard export. Not part of any extension. */ -AL_API const ALchar* AL_APIENTRY alsoft_get_version(void); +AL_API const ALchar* AL_APIENTRY alsoft_get_version(void) noexcept; /* Functions from abandoned extensions. Only here for binary compatibility. */ AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint src, ALsizei nb, - const ALuint *buffers); + const ALuint *buffers) noexcept; -AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname); -AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values); +AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values) AL_API_NOEXCEPT; +ALint64SOFT AL_APIENTRY alGetInteger64DirectSOFT(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT; +void AL_APIENTRY alGetInteger64vDirectSOFT(ALCcontext *context, ALenum pname, ALint64SOFT *values) AL_API_NOEXCEPT; #ifdef __cplusplus } /* extern "C" */ diff --git a/examples/alffplay.cpp b/examples/alffplay.cpp index ae40a51a..1f02ef70 100644 --- a/examples/alffplay.cpp +++ b/examples/alffplay.cpp @@ -339,14 +339,14 @@ struct AudioState { } static void AL_APIENTRY eventCallbackC(ALenum eventType, ALuint object, ALuint param, - ALsizei length, const ALchar *message, void *userParam) + ALsizei length, const ALchar *message, void *userParam) noexcept { static_cast(userParam)->eventCallback(eventType, object, param, length, message); } void eventCallback(ALenum eventType, ALuint object, ALuint param, ALsizei length, - const ALchar *message); + const ALchar *message) noexcept; - static ALsizei AL_APIENTRY bufferCallbackC(void *userptr, void *data, ALsizei size) + static ALsizei AL_APIENTRY bufferCallbackC(void *userptr, void *data, ALsizei size) noexcept { return static_cast(userptr)->bufferCallback(data, size); } - ALsizei bufferCallback(void *data, ALsizei size); + ALsizei bufferCallback(void *data, ALsizei size) noexcept; nanoseconds getClockNoLock(); nanoseconds getClock() @@ -840,7 +840,7 @@ bool AudioState::readAudio(int sample_skip) void AL_APIENTRY AudioState::eventCallback(ALenum eventType, ALuint object, ALuint param, - ALsizei length, const ALchar *message) + ALsizei length, const ALchar *message) noexcept { if(eventType == AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT) { @@ -878,7 +878,7 @@ void AL_APIENTRY AudioState::eventCallback(ALenum eventType, ALuint object, ALui } } -ALsizei AudioState::bufferCallback(void *data, ALsizei size) +ALsizei AudioState::bufferCallback(void *data, ALsizei size) noexcept { ALsizei got{0}; diff --git a/examples/alstreamcb.cpp b/examples/alstreamcb.cpp index a2e7b659..6cc24034 100644 --- a/examples/alstreamcb.cpp +++ b/examples/alstreamcb.cpp @@ -276,9 +276,9 @@ struct StreamPlayer { * but it allows the callback implementation to have a nice 'this' pointer * with normal member access. */ - static ALsizei AL_APIENTRY bufferCallbackC(void *userptr, void *data, ALsizei size) + static ALsizei AL_APIENTRY bufferCallbackC(void *userptr, void *data, ALsizei size) noexcept { return static_cast(userptr)->bufferCallback(data, size); } - ALsizei bufferCallback(void *data, ALsizei size) + ALsizei bufferCallback(void *data, ALsizei size) noexcept { /* NOTE: The callback *MUST* be real-time safe! That means no blocking, * no allocations or deallocations, no I/O, no page faults, or calls to diff --git a/include/AL/al.h b/include/AL/al.h index 5071fa5e..87274184 100644 --- a/include/AL/al.h +++ b/include/AL/al.h @@ -3,6 +3,25 @@ #ifdef __cplusplus extern "C" { + +#ifndef AL_DISABLE_NOEXCEPT +#define AL_API_NOEXCEPT noexcept +#if __cplusplus >= 201703L +#define AL_API_NOEXCEPT17 noexcept +#else +#define AL_API_NOEXCEPT17 +#endif + +#else /* AL_DISABLE_NOEXCEPT */ + +#define AL_API_NOEXCEPT +#define AL_API_NOEXCEPT17 +#endif + +#else /* __cplusplus */ + +#define AL_API_NOEXCEPT +#define AL_API_NOEXCEPT17 #endif #ifndef AL_API @@ -455,217 +474,217 @@ typedef void ALvoid; #ifndef AL_NO_PROTOTYPES /* Renderer State management. */ -AL_API void AL_APIENTRY alEnable(ALenum capability); -AL_API void AL_APIENTRY alDisable(ALenum capability); -AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability); +AL_API void AL_APIENTRY alEnable(ALenum capability) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDisable(ALenum capability) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability) AL_API_NOEXCEPT; /* Context state setting. */ -AL_API void AL_APIENTRY alDopplerFactor(ALfloat value); -AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value); -AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value); -AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel); +AL_API void AL_APIENTRY alDopplerFactor(ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel) AL_API_NOEXCEPT; /* Context state retrieval. */ -AL_API const ALchar* AL_APIENTRY alGetString(ALenum param); -AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values); -AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values); -AL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values); -AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param); -AL_API ALint AL_APIENTRY alGetInteger(ALenum param); -AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param); -AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param); +AL_API const ALchar* AL_APIENTRY alGetString(ALenum param) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param) AL_API_NOEXCEPT; +AL_API ALint AL_APIENTRY alGetInteger(ALenum param) AL_API_NOEXCEPT; +AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param) AL_API_NOEXCEPT; +AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param) AL_API_NOEXCEPT; /** * Obtain the first error generated in the AL context since the last call to * this function. */ -AL_API ALenum AL_APIENTRY alGetError(void); +AL_API ALenum AL_APIENTRY alGetError(void) AL_API_NOEXCEPT; /** Query for the presence of an extension on the AL context. */ -AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname); +AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname) AL_API_NOEXCEPT; /** * Retrieve the address of a function. The returned function may be context- * specific. */ -AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname); +AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname) AL_API_NOEXCEPT; /** * Retrieve the value of an enum. The returned value may be context-specific. */ -AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename); +AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename) AL_API_NOEXCEPT; /* Set listener parameters. */ -AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value); -AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value); -AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values); +AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values) AL_API_NOEXCEPT; /* Get listener parameters. */ -AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values); +AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values) AL_API_NOEXCEPT; /** Create source objects. */ -AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources); +AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources) AL_API_NOEXCEPT; /** Delete source objects. */ -AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources); +AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; /** Verify an ID is for a valid source. */ -AL_API ALboolean AL_APIENTRY alIsSource(ALuint source); +AL_API ALboolean AL_APIENTRY alIsSource(ALuint source) AL_API_NOEXCEPT; /* Set source parameters. */ -AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value); -AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value); -AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values); +AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT; /* Get source parameters. */ -AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values); +AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT; /** Play, restart, or resume a source, setting its state to AL_PLAYING. */ -AL_API void AL_APIENTRY alSourcePlay(ALuint source); +AL_API void AL_APIENTRY alSourcePlay(ALuint source) AL_API_NOEXCEPT; /** Stop a source, setting its state to AL_STOPPED if playing or paused. */ -AL_API void AL_APIENTRY alSourceStop(ALuint source); +AL_API void AL_APIENTRY alSourceStop(ALuint source) AL_API_NOEXCEPT; /** Rewind a source, setting its state to AL_INITIAL. */ -AL_API void AL_APIENTRY alSourceRewind(ALuint source); +AL_API void AL_APIENTRY alSourceRewind(ALuint source) AL_API_NOEXCEPT; /** Pause a source, setting its state to AL_PAUSED if playing. */ -AL_API void AL_APIENTRY alSourcePause(ALuint source); +AL_API void AL_APIENTRY alSourcePause(ALuint source) AL_API_NOEXCEPT; /** Play, restart, or resume a list of sources atomically. */ -AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources); +AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; /** Stop a list of sources atomically. */ -AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources); +AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; /** Rewind a list of sources atomically. */ -AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources); +AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; /** Pause a list of sources atomically. */ -AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources); +AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; /** Queue buffers onto a source */ -AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers); +AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT; /** Unqueue processed buffers from a source */ -AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers); +AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT; /** Create buffer objects */ -AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers); +AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers) AL_API_NOEXCEPT; /** Delete buffer objects */ -AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers); +AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT; /** Verify an ID is a valid buffer (including the NULL buffer) */ -AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer); +AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer) AL_API_NOEXCEPT; /** * Copies data into the buffer, interpreting it using the specified format and * samplerate. */ -AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate); +AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT; /* Set buffer parameters. */ -AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value); -AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values); -AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value); -AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); -AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values); +AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT; /* Get buffer parameters. */ -AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value); -AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values); -AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value); -AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); -AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values); +AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT; #endif /* AL_NO_PROTOTYPES */ /* Pointer-to-function types, useful for storing dynamically loaded AL entry * points. */ -typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability); -typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability); -typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability); -typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param); -typedef void (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values); -typedef void (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values); -typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param); -typedef ALint (AL_APIENTRY *LPALGETINTEGER)(ALenum param); -typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)(ALenum param); -typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)(ALenum param); -typedef ALenum (AL_APIENTRY *LPALGETERROR)(void); -typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname); -typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname); -typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename); -typedef void (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources); -typedef void (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources); -typedef ALboolean (AL_APIENTRY *LPALISSOURCE)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources); -typedef void (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCESTOP)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source); -typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers); -typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers); -typedef void (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers); -typedef void (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers); -typedef ALboolean (AL_APIENTRY *LPALISBUFFER)(ALuint buffer); -typedef void (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate); -typedef void (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); -typedef void (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values); -typedef void (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); -typedef void (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values); -typedef void (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value); -typedef void (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); -typedef void (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values); -typedef void (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value); -typedef void (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); -typedef void (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values); -typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value); -typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value); -typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value); -typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel); +typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability) AL_API_NOEXCEPT17; +typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param) AL_API_NOEXCEPT17; +typedef ALint (AL_APIENTRY *LPALGETINTEGER)(ALenum param) AL_API_NOEXCEPT17; +typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)(ALenum param) AL_API_NOEXCEPT17; +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)(ALenum param) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETERROR)(void) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISSOURCE)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOP)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISBUFFER)(ALuint buffer) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel) AL_API_NOEXCEPT17; #ifdef __cplusplus } /* extern "C" */ diff --git a/include/AL/alc.h b/include/AL/alc.h index 6d210333..73dcf08f 100644 --- a/include/AL/alc.h +++ b/include/AL/alc.h @@ -3,6 +3,25 @@ #ifdef __cplusplus extern "C" { + +#ifndef AL_DISABLE_NOEXCEPT +#define ALC_API_NOEXCEPT noexcept +#if __cplusplus >= 201703L +#define ALC_API_NOEXCEPT17 noexcept +#else +#define ALC_API_NOEXCEPT17 +#endif + +#else /* AL_DISABLE_NOEXCEPT */ + +#define ALC_API_NOEXCEPT +#define ALC_API_NOEXCEPT17 +#endif + +#else /* __cplusplus */ + +#define ALC_API_NOEXCEPT +#define ALC_API_NOEXCEPT17 #endif #ifndef ALC_API @@ -172,34 +191,34 @@ typedef void ALCvoid; /* Context management. */ /** Create and attach a context to the given device. */ -ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrlist); +ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrlist) ALC_API_NOEXCEPT; /** * Makes the given context the active process-wide context. Passing NULL clears * the active context. */ -ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context); +ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) ALC_API_NOEXCEPT; /** Resumes processing updates for the given context. */ -ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context); +ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context) ALC_API_NOEXCEPT; /** Suspends updates for the given context. */ -ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context); +ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context) ALC_API_NOEXCEPT; /** Remove a context from its device and destroys it. */ -ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context); +ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context) ALC_API_NOEXCEPT; /** Returns the currently active context. */ -ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void); +ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void) ALC_API_NOEXCEPT; /** Returns the device that a particular context is attached to. */ -ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context); +ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context) ALC_API_NOEXCEPT; /* Device management. */ /** Opens the named playback device. */ -ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename); +ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename) ALC_API_NOEXCEPT; /** Closes the given playback device. */ -ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device); +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) ALC_API_NOEXCEPT; /* Error support. */ /** Obtain the most recent Device error. */ -ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device); +ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) ALC_API_NOEXCEPT; /* Extension support. */ @@ -207,24 +226,24 @@ ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device); * Query for the presence of an extension on the device. Pass a NULL device to * query a device-inspecific extension. */ -ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname); +ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname) ALC_API_NOEXCEPT; /** * Retrieve the address of a function. Given a non-NULL device, the returned * function may be device-specific. */ -ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname); +ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname) ALC_API_NOEXCEPT; /** * Retrieve the value of an enum. Given a non-NULL device, the returned value * may be device-specific. */ -ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname); +ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname) ALC_API_NOEXCEPT; /* Query functions. */ /** Returns information about the device, and error strings. */ -ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param); +ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param) ALC_API_NOEXCEPT; /** Returns information about the device and the version of OpenAL. */ -ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); +ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) ALC_API_NOEXCEPT; /* Capture functions. */ @@ -232,40 +251,40 @@ ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum pa * Opens the named capture device with the given frequency, format, and buffer * size. */ -ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); +ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize) ALC_API_NOEXCEPT; /** Closes the given capture device. */ -ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device); +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) ALC_API_NOEXCEPT; /** Starts capturing samples into the device buffer. */ -ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device); +ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) ALC_API_NOEXCEPT; /** Stops capturing samples. Samples in the device buffer remain available. */ -ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device); +ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device) ALC_API_NOEXCEPT; /** Reads samples from the device buffer. */ -ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); +ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) ALC_API_NOEXCEPT; #endif /* ALC_NO_PROTOTYPES */ /* Pointer-to-function types, useful for storing dynamically loaded ALC entry * points. */ -typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist); -typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context); -typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context); -typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void); -typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context); -typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename); -typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device); -typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device); -typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname); -typedef ALCvoid* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname); -typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname); -typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param); -typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); -typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); -typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device); -typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); +typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void) ALC_API_NOEXCEPT17; +typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname) ALC_API_NOEXCEPT17; +typedef ALCvoid* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname) ALC_API_NOEXCEPT17; +typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname) ALC_API_NOEXCEPT17; +typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) ALC_API_NOEXCEPT17; +typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) ALC_API_NOEXCEPT17; #ifdef __cplusplus } /* extern "C" */ diff --git a/include/AL/alext.h b/include/AL/alext.h index d313a999..c4f4d4b2 100644 --- a/include/AL/alext.h +++ b/include/AL/alext.h @@ -141,9 +141,9 @@ extern "C" { #ifndef AL_EXT_STATIC_BUFFER #define AL_EXT_STATIC_BUFFER 1 -typedef void (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALuint,ALenum,ALvoid*,ALsizei,ALsizei); +typedef void (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALuint,ALenum,ALvoid*,ALsizei,ALsizei) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -void AL_APIENTRY alBufferDataStatic(const ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq); +void AL_APIENTRY alBufferDataStatic(const ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT; #endif #endif @@ -159,11 +159,11 @@ void AL_APIENTRY alBufferDataStatic(const ALuint buffer, ALenum format, ALvoid * #ifndef ALC_EXT_thread_local_context #define ALC_EXT_thread_local_context 1 -typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context); -typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void); +typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context) ALC_API_NOEXCEPT17; +typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context); -ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void); +ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context) ALC_API_NOEXCEPT; +ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void) ALC_API_NOEXCEPT; #endif #endif @@ -176,9 +176,9 @@ ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void); #define AL_SOFT_buffer_sub_data 1 #define AL_BYTE_RW_OFFSETS_SOFT 0x1031 #define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032 -typedef void (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei); +typedef void (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length); +AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length) AL_API_NOEXCEPT; #endif #endif @@ -195,12 +195,12 @@ AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const AL #define AL_FOLDBACK_EVENT_STOP 0x4113 #define AL_FOLDBACK_MODE_MONO 0x4101 #define AL_FOLDBACK_MODE_STEREO 0x4102 -typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei); -typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK); -typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void); +typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback); -AL_API void AL_APIENTRY alRequestFoldbackStop(void); +AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alRequestFoldbackStop(void) AL_API_NOEXCEPT; #endif #endif @@ -263,15 +263,15 @@ AL_API void AL_APIENTRY alRequestFoldbackStop(void); #define AL_SAMPLE_LENGTH_SOFT 0x200A #define AL_SEC_LENGTH_SOFT 0x200B -typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*); -typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*); -typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*); -typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum); +typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); -AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); -AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data); -AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format); +AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format) AL_API_NOEXCEPT; #endif #endif @@ -302,13 +302,13 @@ AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format); #define ALC_6POINT1_SOFT 0x1505 #define ALC_7POINT1_SOFT 0x1506 -typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*); -typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum); -typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei); +typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName); -ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type); -ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); +ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName) AL_API_NOEXCEPT; +ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type) AL_API_NOEXCEPT; +ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) AL_API_NOEXCEPT; #endif #endif @@ -328,31 +328,31 @@ ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffe #define AL_SEC_OFFSET_LATENCY_SOFT 0x1201 typedef _alsoft_int64_t ALint64SOFT; typedef _alsoft_uint64_t ALuint64SOFT; -typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble); -typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble); -typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*); -typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*); -typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT); -typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT); -typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*); -typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*); +typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value); -AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3); -AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values); -AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value); -AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3); -AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values); -AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value); -AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3); -AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values); -AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value); -AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3); -AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values); +AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values) AL_API_NOEXCEPT; #endif #endif @@ -364,11 +364,11 @@ AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64 #ifndef AL_SOFT_deferred_updates #define AL_SOFT_deferred_updates 1 #define AL_DEFERRED_UPDATES_SOFT 0xC002 -typedef void (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void); -typedef void (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void); +typedef void (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alDeferUpdatesSOFT(void); -AL_API void AL_APIENTRY alProcessUpdatesSOFT(void); +AL_API void AL_APIENTRY alDeferUpdatesSOFT(void) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alProcessUpdatesSOFT(void) AL_API_NOEXCEPT; #endif #endif @@ -400,11 +400,11 @@ AL_API void AL_APIENTRY alProcessUpdatesSOFT(void); #ifndef ALC_SOFT_pause_device #define ALC_SOFT_pause_device 1 -typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device); -typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device); +typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device); -ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device); +ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device) ALC_API_NOEXCEPT; +ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device) ALC_API_NOEXCEPT; #endif #endif @@ -448,11 +448,11 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device); #define ALC_NUM_HRTF_SPECIFIERS_SOFT 0x1994 #define ALC_HRTF_SPECIFIER_SOFT 0x1995 #define ALC_HRTF_ID_SOFT 0x1996 -typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index); -typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs); +typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index); -ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs); +ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index) ALC_API_NOEXCEPT; +ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs) ALC_API_NOEXCEPT; #endif #endif @@ -467,9 +467,9 @@ ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCi #define AL_DEFAULT_RESAMPLER_SOFT 0x1211 #define AL_SOURCE_RESAMPLER_SOFT 0x1212 #define AL_RESAMPLER_NAME_SOFT 0x1213 -typedef const ALchar* (AL_APIENTRY*LPALGETSTRINGISOFT)(ALenum pname, ALsizei index); +typedef const ALchar* (AL_APIENTRY*LPALGETSTRINGISOFT)(ALenum pname, ALsizei index) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index); +AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index) AL_API_NOEXCEPT; #endif #endif @@ -493,9 +493,9 @@ typedef _alsoft_uint64_t ALCuint64SOFT; #define ALC_DEVICE_CLOCK_LATENCY_SOFT 0x1602 #define AL_SAMPLE_OFFSET_CLOCK_SOFT 0x1202 #define AL_SEC_OFFSET_CLOCK_SOFT 0x1203 -typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); +typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); +ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values) ALC_API_NOEXCEPT; #endif #endif @@ -552,27 +552,26 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, #define AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT 0x19A5 #define AL_EVENT_TYPE_DISCONNECTED_SOFT 0x19A6 typedef void (AL_APIENTRY*ALEVENTPROCSOFT)(ALenum eventType, ALuint object, ALuint param, - ALsizei length, const ALchar *message, - void *userParam); -typedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable); -typedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam); -typedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname); -typedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values); + ALsizei length, const ALchar *message, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable); -AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam); -AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname); -AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values); +AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT; +AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values) AL_API_NOEXCEPT; #endif #endif #ifndef ALC_SOFT_reopen_device #define ALC_SOFT_reopen_device typedef ALCboolean (ALC_APIENTRY*LPALCREOPENDEVICESOFT)(ALCdevice *device, - const ALCchar *deviceName, const ALCint *attribs); + const ALCchar *deviceName, const ALCint *attribs) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, const ALCchar *deviceName, - const ALCint *attribs); + const ALCint *attribs) ALC_API_NOEXCEPT; #endif #endif @@ -580,16 +579,16 @@ ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, const ALCchar *de #define AL_SOFT_callback_buffer #define AL_BUFFER_CALLBACK_FUNCTION_SOFT 0x19A0 #define AL_BUFFER_CALLBACK_USER_PARAM_SOFT 0x19A1 -typedef ALsizei (AL_APIENTRY*ALBUFFERCALLBACKTYPESOFT)(ALvoid *userptr, ALvoid *sampledata, ALsizei numbytes); -typedef void (AL_APIENTRY*LPALBUFFERCALLBACKSOFT)(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); -typedef void (AL_APIENTRY*LPALGETBUFFERPTRSOFT)(ALuint buffer, ALenum param, ALvoid **value); -typedef void (AL_APIENTRY*LPALGETBUFFER3PTRSOFT)(ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3); -typedef void (AL_APIENTRY*LPALGETBUFFERPTRVSOFT)(ALuint buffer, ALenum param, ALvoid **values); +typedef ALsizei (AL_APIENTRY*ALBUFFERCALLBACKTYPESOFT)(ALvoid *userptr, ALvoid *sampledata, ALsizei numbytes) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALBUFFERCALLBACKSOFT)(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFERPTRSOFT)(ALuint buffer, ALenum param, ALvoid **value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFER3PTRSOFT)(ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETBUFFERPTRVSOFT)(ALuint buffer, ALenum param, ALvoid **values) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); -AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr); -AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2); -AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **ptr); +AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; #endif #endif @@ -640,11 +639,11 @@ AL_API void AL_APIENTRY alGetBufferPtrvSOFT(ALuint buffer, ALenum param, ALvoid #ifndef AL_SOFT_source_start_delay #define AL_SOFT_source_start_delay -typedef void (AL_APIENTRY*LPALSOURCEPLAYATTIMESOFT)(ALuint source, ALint64SOFT start_time); -typedef void (AL_APIENTRY*LPALSOURCEPLAYATTIMEVSOFT)(ALsizei n, const ALuint *sources, ALint64SOFT start_time); +typedef void (AL_APIENTRY*LPALSOURCEPLAYATTIMESOFT)(ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALSOURCEPLAYATTIMEVSOFT)(ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -void AL_APIENTRY alSourcePlayAtTimeSOFT(ALuint source, ALint64SOFT start_time); -void AL_APIENTRY alSourcePlayAtTimevSOFT(ALsizei n, const ALuint *sources, ALint64SOFT start_time); +void AL_APIENTRY alSourcePlayAtTimeSOFT(ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayAtTimevSOFT(ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT; #endif #endif diff --git a/include/AL/efx.h b/include/AL/efx.h index 5ab64a64..f24222c3 100644 --- a/include/AL/efx.h +++ b/include/AL/efx.h @@ -204,80 +204,80 @@ extern "C" { /* Effect object function types. */ -typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint); -typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; /* Filter object function types. */ -typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint); -typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; /* Auxiliary Effect Slot object function types. */ -typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*); -typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*); -typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat); -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*); -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects); -AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects); -AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect); -AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue); -AL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues); -AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue); -AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues); -AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue); -AL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues); -AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue); -AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues); - -AL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters); -AL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters); -AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter); -AL_API void AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue); -AL_API void AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues); -AL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue); -AL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues); -AL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue); -AL_API void AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues); -AL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue); -AL_API void AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues); - -AL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots); -AL_API void AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots); -AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot); -AL_API void AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue); -AL_API void AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues); -AL_API void AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue); -AL_API void AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues); -AL_API void AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue); -AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues); -AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue); -AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues); +AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +AL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +AL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT; +AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; #endif /* Filter ranges and defaults. */ -- cgit v1.2.3 From 7f72f83fcb3d463d4e5db5d393fff8606f0e2763 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 23 May 2023 02:32:39 -0700 Subject: Use a string_view for handling debug messages --- al/debug.cpp | 68 +++++++++++++++++++++++++++++------------------------------ al/error.cpp | 3 ++- al/event.cpp | 7 +++--- al/state.cpp | 4 ++-- alc/alc.cpp | 4 ++-- alc/context.h | 6 +++--- 6 files changed, 46 insertions(+), 46 deletions(-) (limited to 'alc') diff --git a/al/debug.cpp b/al/debug.cpp index 5a3f4873..efc7fc09 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -168,28 +168,15 @@ const char *GetDebugSeverityName(DebugSeverity severity) void ALCcontext::sendDebugMessage(std::unique_lock &debuglock, DebugSource source, - DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message) + DebugType type, ALuint id, DebugSeverity severity, std::string_view message) { if(!mDebugEnabled.load()) UNLIKELY return; - /* MaxDebugMessageLength is the size including the null terminator, - * does not include the null terminator. - */ - if(length < 0) + if(message.length() >= MaxDebugMessageLength) UNLIKELY { - size_t newlen{std::strlen(message)}; - if(newlen >= MaxDebugMessageLength) UNLIKELY - { - ERR("Debug message too long (%zu >= %d):\n-> %s\n", newlen, MaxDebugMessageLength, - message); - return; - } - length = static_cast(newlen); - } - else if(length >= MaxDebugMessageLength) UNLIKELY - { - ERR("Debug message too long (%d >= %d):\n-> %s\n", length, MaxDebugMessageLength, message); + ERR("Debug message too long (%zu >= %d):\n-> %s\n", message.length(), + MaxDebugMessageLength, message.data()); return; } @@ -215,7 +202,8 @@ void ALCcontext::sendDebugMessage(std::unique_lock &debuglock, Debug auto param = mDebugParam; debuglock.unlock(); callback(GetDebugSourceEnum(source), GetDebugTypeEnum(type), id, - GetDebugSeverityEnum(severity), length, message, param); + GetDebugSeverityEnum(severity), static_cast(message.length()), message.data(), + param); } else { @@ -229,7 +217,7 @@ void ALCcontext::sendDebugMessage(std::unique_lock &debuglock, Debug " Severity: %s\n" " Message: \"%s\"\n", GetDebugSourceName(source), GetDebugTypeName(type), id, - GetDebugSeverityName(severity), message); + GetDebugSeverityName(severity), message.data()); } } @@ -251,20 +239,32 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, if(!context->mContextFlags.test(ContextFlags::DebugBit)) return; - if(!message) + if(!message) UNLIKELY return context->setError(AL_INVALID_VALUE, "Null message pointer"); + if(length >= MaxDebugMessageLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Debug message too long (%d >= %d)", length, + MaxDebugMessageLength); + + std::string tmpmessage; + std::string_view msgview; if(length < 0) + msgview = message; + /* Testing if the message is null terminated like this is kind of ugly, but + * it's the only way to avoid an otherwise unnecessary copy since the + * callback and trace calls need a null-terminated message string. + */ + else if(message[length] == '\0') + msgview = {message, static_cast(length)}; + else { - size_t newlen{std::strlen(message)}; - if(newlen >= MaxDebugMessageLength) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu >= %d)", - newlen, MaxDebugMessageLength); - length = static_cast(newlen); + tmpmessage.assign(message, static_cast(length)); + msgview = tmpmessage; } - else if(length >= MaxDebugMessageLength) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Debug message too long (%d > %d)", length, - MaxDebugMessageLength); + + if(msgview.length() >= MaxDebugMessageLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu >= %d)", + msgview.length(), MaxDebugMessageLength); auto dsource = GetDebugSource(source); if(!dsource) @@ -280,7 +280,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, if(!dseverity) return context->setError(AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity); - context->debugMessage(*dsource, *dtype, id, *dseverity, length, message); + context->debugMessage(*dsource, *dtype, id, *dseverity, msgview); } @@ -393,7 +393,7 @@ FORCE_ALIGN void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALen length = static_cast(newlen); } else if(length >= MaxDebugMessageLength) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Debug message too long (%d > %d)", length, + return context->setError(AL_INVALID_VALUE, "Debug message too long (%d >= %d)", length, MaxDebugMessageLength); auto dsource = GetDebugSource(source); @@ -409,7 +409,8 @@ FORCE_ALIGN void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALen return context->setError(AL_STACK_OVERFLOW_EXT, "Pushing too many debug groups"); } - context->mDebugGroups.emplace_back(*dsource, id, message); + context->mDebugGroups.emplace_back(*dsource, id, + std::string_view{message, static_cast(length)}); auto &oldback = *(context->mDebugGroups.end()-2); auto &newback = context->mDebugGroups.back(); @@ -418,8 +419,7 @@ FORCE_ALIGN void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALen if(context->mContextFlags.test(ContextFlags::DebugBit)) context->sendDebugMessage(debuglock, newback.mSource, DebugType::PushGroup, newback.mId, - DebugSeverity::Notification, static_cast(newback.mMessage.size()), - newback.mMessage.data()); + DebugSeverity::Notification, newback.mMessage); } FORCE_ALIGN DECL_FUNCEXT(void, alPopDebugGroup,EXT) @@ -441,7 +441,7 @@ FORCE_ALIGN void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) noexc context->mDebugGroups.pop_back(); if(context->mContextFlags.test(ContextFlags::DebugBit)) context->sendDebugMessage(debuglock, source, DebugType::PopGroup, id, - DebugSeverity::Notification, static_cast(message.size()), message.data()); + DebugSeverity::Notification, message); } diff --git a/al/error.cpp b/al/error.cpp index 3a1a9ac3..9db13947 100644 --- a/al/error.cpp +++ b/al/error.cpp @@ -87,7 +87,8 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...) ALenum curerr{AL_NO_ERROR}; mLastError.compare_exchange_strong(curerr, errorCode); - debugMessage(DebugSource::API, DebugType::Error, 0, DebugSeverity::High, msglen, msg); + debugMessage(DebugSource::API, DebugType::Error, 0, DebugSeverity::High, + {msg, static_cast(msglen)}); } /* Special-case alGetError since it (potentially) raises a debug signal and diff --git a/al/event.cpp b/al/event.cpp index f606f765..7bd5ae1b 100644 --- a/al/event.cpp +++ b/al/event.cpp @@ -121,7 +121,7 @@ int EventThread(ALCcontext *context) const std::string_view message{evt.msg}; context->debugMessage(DebugSource::System, DebugType::Error, 0, - DebugSeverity::High, static_cast(message.length()), message.data()); + DebugSeverity::High, message); if(context->mEventCb && enabledevts.test(al::to_underlying(AsyncEnableBits::Disconnected))) @@ -130,9 +130,8 @@ int EventThread(ALCcontext *context) context->mEventParam); }; - std::visit(overloaded - {proc_srcstate, proc_buffercomp, proc_release, proc_disconnect, proc_killthread}, - event); + std::visit(overloaded{proc_srcstate, proc_buffercomp, proc_release, proc_disconnect, + proc_killthread}, event); } while(evt_data.len != 0); } return 0; diff --git a/al/state.cpp b/al/state.cpp index 2b6c1bb2..e831ccc1 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -188,7 +188,7 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) case AL_DOPPLER_VELOCITY: if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, - DebugSeverity::Medium, -1, + DebugSeverity::Medium, "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; " "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f"); *values = cast_value(context->mDopplerVelocity); @@ -619,7 +619,7 @@ AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) noexcept if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, - DebugSeverity::Medium, -1, + DebugSeverity::Medium, "alDopplerVelocity is deprecated in AL 1.1, use alSpeedOfSound; " "alDopplerVelocity(x) -> alSpeedOfSound(343.3f * x)"); diff --git a/alc/alc.cpp b/alc/alc.cpp index 3cad507e..88aa73c5 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2777,7 +2777,7 @@ ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context) noexcept } if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY - ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, -1, + ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, "alcSuspendContext behavior is not portable -- some implementations suspend all " "rendering, some only defer property changes, and some are completely no-op; consider " "using alcDevicePauseSOFT to suspend all rendering, or alDeferUpdatesSOFT to only " @@ -2800,7 +2800,7 @@ ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context) noexcept } if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY - ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, -1, + ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, "alcProcessContext behavior is not portable -- some implementations resume rendering, " "some apply deferred property changes, and some are completely no-op; consider using " "alcDeviceResumeSOFT to resume rendering, or alProcessUpdatesSOFT to apply deferred " diff --git a/alc/context.h b/alc/context.h index 779be113..0611775a 100644 --- a/alc/context.h +++ b/alc/context.h @@ -191,15 +191,15 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { void setError(ALenum errorCode, const char *msg, ...); void sendDebugMessage(std::unique_lock &debuglock, DebugSource source, - DebugType type, ALuint id, DebugSeverity severity, ALsizei length, const char *message); + DebugType type, ALuint id, DebugSeverity severity, std::string_view message); void debugMessage(DebugSource source, DebugType type, ALuint id, DebugSeverity severity, - ALsizei length, const char *message) + std::string_view message) { if(!mDebugEnabled.load(std::memory_order_relaxed)) LIKELY return; std::unique_lock debuglock{mDebugCbLock}; - sendDebugMessage(debuglock, source, type, id, severity, length, message); + sendDebugMessage(debuglock, source, type, id, severity, message); } /* Process-wide current context */ -- cgit v1.2.3 From f3e9d066df50a6e77e8c15ea97b195a4b069f254 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 24 May 2023 11:56:56 -0700 Subject: Be a bit more safe with type mangling --- al/event.cpp | 4 ++-- alc/alu.cpp | 6 ++---- common/albit.h | 7 ++++--- core/async_event.h | 8 ++++++-- core/context.cpp | 6 ++++-- core/voice.cpp | 6 ++---- 6 files changed, 20 insertions(+), 17 deletions(-) (limited to 'alc') diff --git a/al/event.cpp b/al/event.cpp index 7bd5ae1b..a5b5fdc5 100644 --- a/al/event.cpp +++ b/al/event.cpp @@ -56,7 +56,7 @@ int EventThread(ALCcontext *context) std::lock_guard _{context->mEventCbLock}; do { - auto *evt_ptr = reinterpret_cast(evt_data.buf); + auto *evt_ptr = std::launder(reinterpret_cast(evt_data.buf)); evt_data.buf += sizeof(AsyncEvent); evt_data.len -= 1; @@ -164,7 +164,7 @@ void StopEventThrd(ALCcontext *ctx) evt_data = ring->getWriteVector().first; } while(evt_data.len == 0); } - std::ignore = InitAsyncEvent(reinterpret_cast(evt_data.buf)); + std::ignore = InitAsyncEvent(evt_data.buf); ring->writeAdvance(1); ctx->mEventSem.post(); diff --git a/alc/alu.cpp b/alc/alu.cpp index cf250988..c43da639 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -491,8 +491,7 @@ bool CalcEffectSlotParams(EffectSlot *slot, EffectSlot **sorted_slots, ContextBa auto evt_vec = ring->getWriteVector(); if(evt_vec.first.len > 0) LIKELY { - AsyncEffectReleaseEvent &evt = InitAsyncEvent( - reinterpret_cast(evt_vec.first.buf)); + auto &evt = InitAsyncEvent(evt_vec.first.buf); evt.mEffectState = oldstate; ring->writeAdvance(1); } @@ -1701,8 +1700,7 @@ void SendSourceStateEvent(ContextBase *context, uint id, VChangeState state) auto evt_vec = ring->getWriteVector(); if(evt_vec.first.len < 1) return; - AsyncSourceStateEvent &evt = InitAsyncEvent( - reinterpret_cast(evt_vec.first.buf)); + auto &evt = InitAsyncEvent(evt_vec.first.buf); evt.mId = id; switch(state) { diff --git a/common/albit.h b/common/albit.h index a563a4e7..962eb0aa 100644 --- a/common/albit.h +++ b/common/albit.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #if !defined(__GNUC__) && (defined(_WIN32) || defined(_WIN64)) #include @@ -16,9 +17,9 @@ std::enable_if_t, To> bit_cast(const From &src) noexcept { - union { char c; To dst; } u; - std::memcpy(&u.dst, &src, sizeof(To)); - return u.dst; + std::aligned_storage_t dst; + std::memcpy(&dst, &src, sizeof(To)); + return *std::launder(reinterpret_cast(&dst)); } #ifdef __BYTE_ORDER__ diff --git a/core/async_event.h b/core/async_event.h index 9e2d1193..c049fa02 100644 --- a/core/async_event.h +++ b/core/async_event.h @@ -54,7 +54,11 @@ using AsyncEvent = std::variant; template -auto &InitAsyncEvent(AsyncEvent *evt, Args&& ...args) -{ return std::get(*al::construct_at(evt, std::in_place_type, std::forward(args)...)); } +auto &InitAsyncEvent(std::byte *evtbuf, Args&& ...args) +{ + auto *evt = al::construct_at(reinterpret_cast(evtbuf), std::in_place_type, + std::forward(args)...); + return std::get(*evt); +} #endif diff --git a/core/context.cpp b/core/context.cpp index 145ce349..2ebbc7b1 100644 --- a/core/context.cpp +++ b/core/context.cpp @@ -66,12 +66,14 @@ ContextBase::~ContextBase() auto evt_vec = mAsyncEvents->getReadVector(); if(evt_vec.first.len > 0) { - std::destroy_n(reinterpret_cast(evt_vec.first.buf), evt_vec.first.len); + std::destroy_n(std::launder(reinterpret_cast(evt_vec.first.buf)), + evt_vec.first.len); count += evt_vec.first.len; } if(evt_vec.second.len > 0) { - std::destroy_n(reinterpret_cast(evt_vec.second.buf), evt_vec.second.len); + std::destroy_n(std::launder(reinterpret_cast(evt_vec.second.buf)), + evt_vec.second.len); count += evt_vec.second.len; } if(count > 0) diff --git a/core/voice.cpp b/core/voice.cpp index 3e78b176..65986cd1 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -226,8 +226,7 @@ void SendSourceStoppedEvent(ContextBase *context, uint id) auto evt_vec = ring->getWriteVector(); if(evt_vec.first.len < 1) return; - AsyncSourceStateEvent &evt = InitAsyncEvent( - reinterpret_cast(evt_vec.first.buf)); + auto &evt = InitAsyncEvent(evt_vec.first.buf); evt.mId = id; evt.mState = AsyncSrcState::Stop; @@ -1151,8 +1150,7 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi auto evt_vec = ring->getWriteVector(); if(evt_vec.first.len > 0) { - AsyncBufferCompleteEvent &evt = InitAsyncEvent( - reinterpret_cast(evt_vec.first.buf)); + auto &evt = InitAsyncEvent(evt_vec.first.buf); evt.mId = SourceID; evt.mCount = buffers_done; ring->writeAdvance(1); -- cgit v1.2.3 From 68908eebbec50ed8f4343f93fd8cd52427ea7ca8 Mon Sep 17 00:00:00 2001 From: "Deal(一线灵)" Date: Fri, 26 May 2023 00:23:24 +0800 Subject: Improve oboe backend (#848) * Improve oboe backend This change should handle handphone call event properly and fix crash at stop (because the mStream was disconnected by system when handphone call income) * Invoke mDevice->handleDisconnect when AAudio stream disconnected --- alc/backends/oboe.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/oboe.cpp b/alc/backends/oboe.cpp index c74b0180..01d6fb85 100644 --- a/alc/backends/oboe.cpp +++ b/alc/backends/oboe.cpp @@ -5,7 +5,6 @@ #include #include -#include #include #include "alnumeric.h" @@ -29,6 +28,8 @@ struct OboePlayback final : public BackendBase, public oboe::AudioStreamCallback oboe::DataCallbackResult onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) override; + void onErrorAfterClose(oboe::AudioStream* /* audioStream */, oboe::Result /* error */) override; + void open(const char *name) override; bool reset() override; void start() override; @@ -47,6 +48,13 @@ oboe::DataCallbackResult OboePlayback::onAudioReady(oboe::AudioStream *oboeStrea return oboe::DataCallbackResult::Continue; } +void OboePlayback::onErrorAfterClose(oboe::AudioStream* audioStream, oboe::Result error) +{ + if (error == oboe::Result::ErrorDisconnected) { + mDevice->handleDisconnect("Oboe AudioStream was disconnected: %s", oboe::convertToText(error)); + } + TRACE("Error was %s", oboe::convertToText(error)); +} void OboePlayback::open(const char *name) { -- cgit v1.2.3 From 453677bc983a5c17a6d4426e845114bb7be9b770 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 25 May 2023 23:00:10 -0700 Subject: Don't throw when failing to stop Oboe playback --- alc/backends/oboe.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'alc') diff --git a/alc/backends/oboe.cpp b/alc/backends/oboe.cpp index 01d6fb85..a0d806c8 100644 --- a/alc/backends/oboe.cpp +++ b/alc/backends/oboe.cpp @@ -206,8 +206,7 @@ void OboePlayback::stop() { oboe::Result result{mStream->stop()}; if(result != oboe::Result::OK) - throw al::backend_exception{al::backend_error::DeviceError, "Failed to stop stream: %s", - oboe::convertToText(result)}; + ERR("Failed to stop stream: %s\n", oboe::convertToText(result)); } -- cgit v1.2.3 From 2e75909ce90027267775d53e997d4936d6ef31a5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 30 May 2023 13:45:53 -0700 Subject: Don't throw when failing to stop Oboe capture --- alc/backends/oboe.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'alc') diff --git a/alc/backends/oboe.cpp b/alc/backends/oboe.cpp index a0d806c8..cc44b867 100644 --- a/alc/backends/oboe.cpp +++ b/alc/backends/oboe.cpp @@ -323,8 +323,7 @@ void OboeCapture::stop() { const oboe::Result result{mStream->stop()}; if(result != oboe::Result::OK) - throw al::backend_exception{al::backend_error::DeviceError, "Failed to stop stream: %s", - oboe::convertToText(result)}; + ERR("Failed to stop stream: %s\n", oboe::convertToText(result)); } uint OboeCapture::availableSamples() -- cgit v1.2.3 From 517bb94c0953de768f6aacca45456fd63bb2c96d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 30 May 2023 21:16:41 -0700 Subject: Add a callback to report system device changes Devices being added or removed, or the default device changing. Not all backends report this (none do currently), but it'll be supported where it can. --- CMakeLists.txt | 2 ++ alc/alc.cpp | 54 +++++++++++++++++-------------- alc/device.h | 3 ++ alc/events.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ alc/events.h | 36 +++++++++++++++++++++ alc/inprogext.h | 15 +++++++++ 6 files changed, 184 insertions(+), 24 deletions(-) create mode 100644 alc/events.cpp create mode 100644 alc/events.h (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bc8f2e2..e1c6db76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -813,6 +813,8 @@ set(ALC_OBJS alc/effects/pshifter.cpp alc/effects/reverb.cpp alc/effects/vmorpher.cpp + alc/events.cpp + alc/events.h alc/inprogext.h alc/panning.cpp) diff --git a/alc/alc.cpp b/alc/alc.cpp index 88aa73c5..c5d4b9d3 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -616,6 +616,9 @@ const struct { DECL(alPushDebugGroupDirectEXT), DECL(alPopDebugGroupDirectEXT), DECL(alGetDebugMessageLogDirectEXT), + + DECL(alcEventControlSOFT), + DECL(alcEventCallbackSOFT), #ifdef ALSOFT_EAX }, eaxFunctions[] = { DECL(EAXGet), @@ -1174,7 +1177,8 @@ constexpr ALCchar alcNoDeviceExtList[] = "ALC_EXT_thread_local_context " "ALC_SOFT_loopback " "ALC_SOFT_loopback_bformat " - "ALC_SOFT_reopen_device"; + "ALC_SOFT_reopen_device " + "ALC_SOFTX_system_events"; constexpr ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT " "ALC_ENUMERATION_EXT " @@ -1192,7 +1196,8 @@ constexpr ALCchar alcExtensionList[] = "ALC_SOFT_output_limiter " "ALC_SOFT_output_mode " "ALC_SOFT_pause_device " - "ALC_SOFT_reopen_device"; + "ALC_SOFT_reopen_device " + "ALC_SOFTX_system_events"; constexpr int alcMajorVersion{1}; constexpr int alcMinorVersion{1}; @@ -1815,28 +1820,6 @@ const std::array X71Downmix{{ }}; -/** Stores the latest ALC device error. */ -void alcSetError(ALCdevice *device, ALCenum errorCode) -{ - WARN("Error generated on device %p, code 0x%04x\n", voidp{device}, errorCode); - if(TrapALCError) - { -#ifdef _WIN32 - /* DebugBreak() will cause an exception if there is no debugger */ - if(IsDebuggerPresent()) - DebugBreak(); -#elif defined(SIGTRAP) - raise(SIGTRAP); -#endif - } - - if(device) - device->LastError.store(errorCode); - else - LastNullDeviceError.store(errorCode); -} - - std::unique_ptr CreateDeviceLimiter(const ALCdevice *device, const float threshold) { static constexpr bool AutoKnee{true}; @@ -2754,6 +2737,25 @@ ContextRef GetContextRef(void) return ContextRef{context}; } +void alcSetError(ALCdevice *device, ALCenum errorCode) +{ + WARN("Error generated on device %p, code 0x%04x\n", voidp{device}, errorCode); + if(TrapALCError) + { +#ifdef _WIN32 + /* DebugBreak() will cause an exception if there is no debugger */ + if(IsDebuggerPresent()) + DebugBreak(); +#elif defined(SIGTRAP) + raise(SIGTRAP); +#endif + } + + if(device) + device->LastError.store(errorCode); + else + LastNullDeviceError.store(errorCode); +} /************************************************ * Standard ALC functions @@ -3436,6 +3438,8 @@ ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar alcSetError(dev.get(), ALC_INVALID_VALUE); return nullptr; } + + InitConfig(); #ifdef ALSOFT_EAX if(eax_g_is_enabled) { @@ -3463,6 +3467,8 @@ ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *e alcSetError(dev.get(), ALC_INVALID_VALUE); return 0; } + + InitConfig(); #ifdef ALSOFT_EAX if(eax_g_is_enabled) { diff --git a/alc/device.h b/alc/device.h index 1274e287..c346dc9e 100644 --- a/alc/device.h +++ b/alc/device.h @@ -163,4 +163,7 @@ template<> inline std::optional ALCdevice::configValue(const char *block, const char *key) { return ConfigValueBool(DeviceName.c_str(), block, key); } +/** Stores the latest ALC device error. */ +void alcSetError(ALCdevice *device, ALCenum errorCode); + #endif diff --git a/alc/events.cpp b/alc/events.cpp new file mode 100644 index 00000000..3c9c59ee --- /dev/null +++ b/alc/events.cpp @@ -0,0 +1,98 @@ + +#include "config.h" + +#include "events.h" + +#include + +#include "alspan.h" +#include "common/threads.h" +#include "core/logging.h" +#include "device.h" + + +namespace { + +std::optional GetEventType(ALCenum type) +{ + switch(type) + { + case ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT: return alc::EventType::DefaultDeviceChanged; + case ALC_EVENT_TYPE_DEVICE_ADDED_SOFT: return alc::EventType::DeviceAdded; + case ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT: return alc::EventType::DeviceRemoved; + } + return std::nullopt; +} + +ALCenum EnumFromEventType(const alc::EventType type) +{ + switch(type) + { + case alc::EventType::DefaultDeviceChanged: return ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT; + case alc::EventType::DeviceAdded: return ALC_EVENT_TYPE_DEVICE_ADDED_SOFT; + case alc::EventType::DeviceRemoved: return ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT; + case alc::EventType::Count: break; + } + throw std::runtime_error{"Invalid EventType: "+std::to_string(al::to_underlying(type))}; +} + +} // namespace + +namespace alc { + +void Event(EventType eventType, ALCdevice *device, std::string_view message) noexcept +{ + auto eventlock = std::unique_lock{EventMutex}; + if(EventCallback && EventsEnabled.test(al::to_underlying(eventType))) + EventCallback(EnumFromEventType(eventType), device, + static_cast(message.length()), message.data(), EventUserPtr); +} + +} // namespace alc + +FORCE_ALIGN ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *types, + ALCboolean enable) noexcept +{ + if(enable != ALC_FALSE && enable != ALC_TRUE) + { + alcSetError(nullptr, ALC_INVALID_ENUM); + return ALC_FALSE; + } + if(count < 0) + { + alcSetError(nullptr, ALC_INVALID_VALUE); + return ALC_FALSE; + } + if(count == 0) + return ALC_TRUE; + if(!types) + { + alcSetError(nullptr, ALC_INVALID_VALUE); + return ALC_FALSE; + } + + std::bitset eventSet{0}; + for(ALCenum type : al::span{types, static_cast(count)}) + { + auto etype = GetEventType(type); + if(!etype) + { + WARN("Invalid event type: 0x%04x\n", type); + alcSetError(nullptr, ALC_INVALID_ENUM); + return ALC_FALSE; + } + eventSet.set(al::to_underlying(*etype)); + } + + auto eventlock = std::unique_lock{alc::EventMutex}; + if(enable) alc::EventsEnabled |= eventSet; + else alc::EventsEnabled &= eventSet; + return ALC_TRUE; +} + +FORCE_ALIGN void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *userParam) noexcept +{ + auto eventlock = std::unique_lock{alc::EventMutex}; + alc::EventCallback = callback; + alc::EventUserPtr = userParam; +} diff --git a/alc/events.h b/alc/events.h new file mode 100644 index 00000000..51f32e57 --- /dev/null +++ b/alc/events.h @@ -0,0 +1,36 @@ +#ifndef ALC_EVENTS_H +#define ALC_EVENTS_H + +#include "inprogext.h" +#include "opthelpers.h" + +#include +#include +#include + + +namespace alc { + +enum class EventType : uint8_t { + DefaultDeviceChanged, + DeviceAdded, + DeviceRemoved, + + Count +}; + +inline std::bitset EventsEnabled{0}; + +inline std::mutex EventMutex; + +inline ALCEVENTPROCTYPESOFT EventCallback{}; +inline void *EventUserPtr{}; + +void Event(ALCenum eventType, ALCdevice *device, std::string_view message) noexcept; + +inline void Event(ALCenum eventType, std::string_view message) noexcept +{ Event(eventType, nullptr, message); } + +} // namespace alc + +#endif /* ALC_EVENTS_H */ diff --git a/alc/inprogext.h b/alc/inprogext.h index 38ef2bf8..7cf49868 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -443,6 +443,21 @@ ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, AL #endif #endif +#ifndef ALC_SOFT_system_events +#define ALC_SOFT_system_events +#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19CF +#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D0 +#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D1 +typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCdevice *device, + ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *types, ALCboolean enable) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY*LPALCEVENTCALLBACKSOFT)(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *types, ALCboolean enable) ALC_API_NOEXCEPT; +void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT; +#endif +#endif + /* Non-standard export. Not part of any extension. */ AL_API const ALchar* AL_APIENTRY alsoft_get_version(void) noexcept; -- cgit v1.2.3 From e677d420b0c85082a4ccff3ab2a9f362f39a6774 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 30 May 2023 21:51:34 -0700 Subject: Move the function and enum list to a separate file --- CMakeLists.txt | 1 + alc/alc.cpp | 865 +---------------------------------------------------- alc/export_list.h | 877 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 879 insertions(+), 864 deletions(-) create mode 100644 alc/export_list.h (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index e1c6db76..8df4be2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -815,6 +815,7 @@ set(ALC_OBJS alc/effects/vmorpher.cpp alc/events.cpp alc/events.h + alc/export_list.h alc/inprogext.h alc/panning.cpp) diff --git a/alc/alc.cpp b/alc/alc.cpp index c5d4b9d3..299a1ee9 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -98,6 +98,7 @@ #include "core/voice_change.h" #include "device.h" #include "effects/base.h" +#include "export_list.h" #include "inprogext.h" #include "intrusive_ptr.h" #include "opthelpers.h" @@ -262,870 +263,6 @@ BackendFactory *PlaybackFactory{}; BackendFactory *CaptureFactory{}; -/************************************************ - * Functions, enums, and errors - ************************************************/ -#define DECL(x) { #x, reinterpret_cast(x) } -const struct { - const char *funcName; - void *address; -} alcFunctions[] = { - DECL(alcCreateContext), - DECL(alcMakeContextCurrent), - DECL(alcProcessContext), - DECL(alcSuspendContext), - DECL(alcDestroyContext), - DECL(alcGetCurrentContext), - DECL(alcGetContextsDevice), - DECL(alcOpenDevice), - DECL(alcCloseDevice), - DECL(alcGetError), - DECL(alcIsExtensionPresent), - DECL(alcGetProcAddress), - DECL(alcGetEnumValue), - DECL(alcGetString), - DECL(alcGetIntegerv), - DECL(alcCaptureOpenDevice), - DECL(alcCaptureCloseDevice), - DECL(alcCaptureStart), - DECL(alcCaptureStop), - DECL(alcCaptureSamples), - - DECL(alcSetThreadContext), - DECL(alcGetThreadContext), - - DECL(alcLoopbackOpenDeviceSOFT), - DECL(alcIsRenderFormatSupportedSOFT), - DECL(alcRenderSamplesSOFT), - - DECL(alcDevicePauseSOFT), - DECL(alcDeviceResumeSOFT), - - DECL(alcGetStringiSOFT), - DECL(alcResetDeviceSOFT), - - DECL(alcGetInteger64vSOFT), - - DECL(alcReopenDeviceSOFT), - - DECL(alEnable), - DECL(alDisable), - DECL(alIsEnabled), - DECL(alGetString), - DECL(alGetBooleanv), - DECL(alGetIntegerv), - DECL(alGetFloatv), - DECL(alGetDoublev), - DECL(alGetBoolean), - DECL(alGetInteger), - DECL(alGetFloat), - DECL(alGetDouble), - DECL(alGetError), - DECL(alIsExtensionPresent), - DECL(alGetProcAddress), - DECL(alGetEnumValue), - DECL(alListenerf), - DECL(alListener3f), - DECL(alListenerfv), - DECL(alListeneri), - DECL(alListener3i), - DECL(alListeneriv), - DECL(alGetListenerf), - DECL(alGetListener3f), - DECL(alGetListenerfv), - DECL(alGetListeneri), - DECL(alGetListener3i), - DECL(alGetListeneriv), - DECL(alGenSources), - DECL(alDeleteSources), - DECL(alIsSource), - DECL(alSourcef), - DECL(alSource3f), - DECL(alSourcefv), - DECL(alSourcei), - DECL(alSource3i), - DECL(alSourceiv), - DECL(alGetSourcef), - DECL(alGetSource3f), - DECL(alGetSourcefv), - DECL(alGetSourcei), - DECL(alGetSource3i), - DECL(alGetSourceiv), - DECL(alSourcePlayv), - DECL(alSourceStopv), - DECL(alSourceRewindv), - DECL(alSourcePausev), - DECL(alSourcePlay), - DECL(alSourceStop), - DECL(alSourceRewind), - DECL(alSourcePause), - DECL(alSourceQueueBuffers), - DECL(alSourceUnqueueBuffers), - DECL(alGenBuffers), - DECL(alDeleteBuffers), - DECL(alIsBuffer), - DECL(alBufferData), - DECL(alBufferf), - DECL(alBuffer3f), - DECL(alBufferfv), - DECL(alBufferi), - DECL(alBuffer3i), - DECL(alBufferiv), - DECL(alGetBufferf), - DECL(alGetBuffer3f), - DECL(alGetBufferfv), - DECL(alGetBufferi), - DECL(alGetBuffer3i), - DECL(alGetBufferiv), - DECL(alDopplerFactor), - DECL(alDopplerVelocity), - DECL(alSpeedOfSound), - DECL(alDistanceModel), - - DECL(alGenFilters), - DECL(alDeleteFilters), - DECL(alIsFilter), - DECL(alFilteri), - DECL(alFilteriv), - DECL(alFilterf), - DECL(alFilterfv), - DECL(alGetFilteri), - DECL(alGetFilteriv), - DECL(alGetFilterf), - DECL(alGetFilterfv), - DECL(alGenEffects), - DECL(alDeleteEffects), - DECL(alIsEffect), - DECL(alEffecti), - DECL(alEffectiv), - DECL(alEffectf), - DECL(alEffectfv), - DECL(alGetEffecti), - DECL(alGetEffectiv), - DECL(alGetEffectf), - DECL(alGetEffectfv), - DECL(alGenAuxiliaryEffectSlots), - DECL(alDeleteAuxiliaryEffectSlots), - DECL(alIsAuxiliaryEffectSlot), - DECL(alAuxiliaryEffectSloti), - DECL(alAuxiliaryEffectSlotiv), - DECL(alAuxiliaryEffectSlotf), - DECL(alAuxiliaryEffectSlotfv), - DECL(alGetAuxiliaryEffectSloti), - DECL(alGetAuxiliaryEffectSlotiv), - DECL(alGetAuxiliaryEffectSlotf), - DECL(alGetAuxiliaryEffectSlotfv), - - DECL(alDeferUpdatesSOFT), - DECL(alProcessUpdatesSOFT), - - DECL(alSourcedSOFT), - DECL(alSource3dSOFT), - DECL(alSourcedvSOFT), - DECL(alGetSourcedSOFT), - DECL(alGetSource3dSOFT), - DECL(alGetSourcedvSOFT), - DECL(alSourcei64SOFT), - DECL(alSource3i64SOFT), - DECL(alSourcei64vSOFT), - DECL(alGetSourcei64SOFT), - DECL(alGetSource3i64SOFT), - DECL(alGetSourcei64vSOFT), - - DECL(alGetStringiSOFT), - - DECL(alBufferStorageSOFT), - DECL(alMapBufferSOFT), - DECL(alUnmapBufferSOFT), - DECL(alFlushMappedBufferSOFT), - - DECL(alEventControlSOFT), - DECL(alEventCallbackSOFT), - DECL(alGetPointerSOFT), - DECL(alGetPointervSOFT), - - DECL(alBufferCallbackSOFT), - DECL(alGetBufferPtrSOFT), - DECL(alGetBuffer3PtrSOFT), - DECL(alGetBufferPtrvSOFT), - - DECL(alAuxiliaryEffectSlotPlaySOFT), - DECL(alAuxiliaryEffectSlotPlayvSOFT), - DECL(alAuxiliaryEffectSlotStopSOFT), - DECL(alAuxiliaryEffectSlotStopvSOFT), - - DECL(alSourcePlayAtTimeSOFT), - DECL(alSourcePlayAtTimevSOFT), - - DECL(alBufferSubDataSOFT), - - DECL(alBufferDataStatic), - - DECL(alDebugMessageCallbackEXT), - DECL(alDebugMessageInsertEXT), - DECL(alDebugMessageControlEXT), - DECL(alPushDebugGroupEXT), - DECL(alPopDebugGroupEXT), - DECL(alGetDebugMessageLogEXT), - - /* Direct Context functions */ - DECL(alEnableDirect), - DECL(alDisableDirect), - DECL(alIsEnabledDirect), - DECL(alDopplerFactorDirect), - DECL(alSpeedOfSoundDirect), - DECL(alDistanceModelDirect), - DECL(alGetStringDirect), - DECL(alGetBooleanvDirect), - DECL(alGetIntegervDirect), - DECL(alGetFloatvDirect), - DECL(alGetDoublevDirect), - DECL(alGetBooleanDirect), - DECL(alGetIntegerDirect), - DECL(alGetFloatDirect), - DECL(alGetDoubleDirect), - - DECL(alGetErrorDirect), - DECL(alIsExtensionPresentDirect), - DECL(alGetProcAddress), - DECL(alGetEnumValueDirect), - - DECL(alListeneriDirect), - DECL(alListener3iDirect), - DECL(alListenerivDirect), - DECL(alListenerfDirect), - DECL(alListener3fDirect), - DECL(alListenerfvDirect), - DECL(alGetListeneriDirect), - DECL(alGetListener3iDirect), - DECL(alGetListenerivDirect), - DECL(alGetListenerfDirect), - DECL(alGetListener3fDirect), - DECL(alGetListenerfvDirect), - - DECL(alGenBuffersDirect), - DECL(alDeleteBuffersDirect), - DECL(alIsBufferDirect), - DECL(alBufferDataDirect), - DECL(alBufferiDirect), - DECL(alBuffer3iDirect), - DECL(alBufferivDirect), - DECL(alBufferfDirect), - DECL(alBuffer3fDirect), - DECL(alBufferfvDirect), - DECL(alGetBufferiDirect), - DECL(alGetBuffer3iDirect), - DECL(alGetBufferivDirect), - DECL(alGetBufferfDirect), - DECL(alGetBuffer3fDirect), - DECL(alGetBufferfvDirect), - - DECL(alGenSourcesDirect), - DECL(alDeleteSourcesDirect), - DECL(alIsSourceDirect), - DECL(alSourcePlayDirect), - DECL(alSourceStopDirect), - DECL(alSourcePauseDirect), - DECL(alSourceRewindDirect), - DECL(alSourcePlayvDirect), - DECL(alSourceStopvDirect), - DECL(alSourcePausevDirect), - DECL(alSourceRewindvDirect), - DECL(alSourceiDirect), - DECL(alSource3iDirect), - DECL(alSourceivDirect), - DECL(alSourcefDirect), - DECL(alSource3fDirect), - DECL(alSourcefvDirect), - DECL(alGetSourceiDirect), - DECL(alGetSource3iDirect), - DECL(alGetSourceivDirect), - DECL(alGetSourcefDirect), - DECL(alGetSource3fDirect), - DECL(alGetSourcefvDirect), - DECL(alSourceQueueBuffersDirect), - DECL(alSourceUnqueueBuffersDirect), - - DECL(alGenFiltersDirect), - DECL(alDeleteFiltersDirect), - DECL(alIsFilterDirect), - DECL(alFilteriDirect), - DECL(alFilterivDirect), - DECL(alFilterfDirect), - DECL(alFilterfvDirect), - DECL(alGetFilteriDirect), - DECL(alGetFilterivDirect), - DECL(alGetFilterfDirect), - DECL(alGetFilterfvDirect), - DECL(alGenEffectsDirect), - DECL(alDeleteEffectsDirect), - DECL(alIsEffectDirect), - DECL(alEffectiDirect), - DECL(alEffectivDirect), - DECL(alEffectfDirect), - DECL(alEffectfvDirect), - DECL(alGetEffectiDirect), - DECL(alGetEffectivDirect), - DECL(alGetEffectfDirect), - DECL(alGetEffectfvDirect), - DECL(alGenAuxiliaryEffectSlotsDirect), - DECL(alDeleteAuxiliaryEffectSlotsDirect), - DECL(alIsAuxiliaryEffectSlotDirect), - DECL(alAuxiliaryEffectSlotiDirect), - DECL(alAuxiliaryEffectSlotivDirect), - DECL(alAuxiliaryEffectSlotfDirect), - DECL(alAuxiliaryEffectSlotfvDirect), - DECL(alGetAuxiliaryEffectSlotiDirect), - DECL(alGetAuxiliaryEffectSlotivDirect), - DECL(alGetAuxiliaryEffectSlotfDirect), - DECL(alGetAuxiliaryEffectSlotfvDirect), - - DECL(alDeferUpdatesDirectSOFT), - DECL(alProcessUpdatesDirectSOFT), - DECL(alGetStringiDirectSOFT), - - DECL(alBufferDataStaticDirect), - DECL(alBufferCallbackDirectSOFT), - DECL(alBufferSubDataDirectSOFT), - DECL(alBufferStorageDirectSOFT), - DECL(alMapBufferDirectSOFT), - DECL(alUnmapBufferDirectSOFT), - DECL(alFlushMappedBufferDirectSOFT), - - DECL(alSourcei64DirectSOFT), - DECL(alSource3i64DirectSOFT), - DECL(alSourcei64vDirectSOFT), - DECL(alSourcedDirectSOFT), - DECL(alSource3dDirectSOFT), - DECL(alSourcedvDirectSOFT), - DECL(alGetSourcei64DirectSOFT), - DECL(alGetSource3i64DirectSOFT), - DECL(alGetSourcei64vDirectSOFT), - DECL(alGetSourcedDirectSOFT), - DECL(alGetSource3dDirectSOFT), - DECL(alGetSourcedvDirectSOFT), - DECL(alSourcePlayAtTimeDirectSOFT), - DECL(alSourcePlayAtTimevDirectSOFT), - - DECL(alEventControlDirectSOFT), - DECL(alEventCallbackDirectSOFT), - - DECL(alDebugMessageCallbackDirectEXT), - DECL(alDebugMessageInsertDirectEXT), - DECL(alDebugMessageControlDirectEXT), - DECL(alPushDebugGroupDirectEXT), - DECL(alPopDebugGroupDirectEXT), - DECL(alGetDebugMessageLogDirectEXT), - - DECL(alcEventControlSOFT), - DECL(alcEventCallbackSOFT), -#ifdef ALSOFT_EAX -}, eaxFunctions[] = { - DECL(EAXGet), - DECL(EAXSet), - DECL(EAXGetBufferMode), - DECL(EAXSetBufferMode), - - DECL(EAXGetDirect), - DECL(EAXSetDirect), - DECL(EAXGetBufferModeDirect), - DECL(EAXSetBufferModeDirect), -#endif -}; -#undef DECL - -#define DECL(x) { #x, (x) } -constexpr struct { - const ALCchar *enumName; - ALCenum value; -} alcEnumerations[] = { - DECL(ALC_INVALID), - DECL(ALC_FALSE), - DECL(ALC_TRUE), - - DECL(ALC_MAJOR_VERSION), - DECL(ALC_MINOR_VERSION), - DECL(ALC_ATTRIBUTES_SIZE), - DECL(ALC_ALL_ATTRIBUTES), - DECL(ALC_DEFAULT_DEVICE_SPECIFIER), - DECL(ALC_DEVICE_SPECIFIER), - DECL(ALC_ALL_DEVICES_SPECIFIER), - DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER), - DECL(ALC_EXTENSIONS), - DECL(ALC_FREQUENCY), - DECL(ALC_REFRESH), - DECL(ALC_SYNC), - DECL(ALC_MONO_SOURCES), - DECL(ALC_STEREO_SOURCES), - DECL(ALC_CAPTURE_DEVICE_SPECIFIER), - DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER), - DECL(ALC_CAPTURE_SAMPLES), - DECL(ALC_CONNECTED), - - DECL(ALC_EFX_MAJOR_VERSION), - DECL(ALC_EFX_MINOR_VERSION), - DECL(ALC_MAX_AUXILIARY_SENDS), - - DECL(ALC_FORMAT_CHANNELS_SOFT), - DECL(ALC_FORMAT_TYPE_SOFT), - - DECL(ALC_MONO_SOFT), - DECL(ALC_STEREO_SOFT), - DECL(ALC_QUAD_SOFT), - 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), - DECL(ALC_SHORT_SOFT), - DECL(ALC_UNSIGNED_SHORT_SOFT), - DECL(ALC_INT_SOFT), - DECL(ALC_UNSIGNED_INT_SOFT), - DECL(ALC_FLOAT_SOFT), - - DECL(ALC_HRTF_SOFT), - DECL(ALC_DONT_CARE_SOFT), - DECL(ALC_HRTF_STATUS_SOFT), - DECL(ALC_HRTF_DISABLED_SOFT), - DECL(ALC_HRTF_ENABLED_SOFT), - DECL(ALC_HRTF_DENIED_SOFT), - DECL(ALC_HRTF_REQUIRED_SOFT), - DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT), - DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT), - DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT), - 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_OUTPUT_LIMITER_SOFT), - - DECL(ALC_DEVICE_CLOCK_SOFT), - DECL(ALC_DEVICE_LATENCY_SOFT), - DECL(ALC_DEVICE_CLOCK_LATENCY_SOFT), - DECL(AL_SAMPLE_OFFSET_CLOCK_SOFT), - DECL(AL_SEC_OFFSET_CLOCK_SOFT), - - DECL(ALC_OUTPUT_MODE_SOFT), - DECL(ALC_ANY_SOFT), - DECL(ALC_STEREO_BASIC_SOFT), - DECL(ALC_STEREO_UHJ_SOFT), - DECL(ALC_STEREO_HRTF_SOFT), - DECL(ALC_SURROUND_5_1_SOFT), - DECL(ALC_SURROUND_6_1_SOFT), - DECL(ALC_SURROUND_7_1_SOFT), - - DECL(ALC_NO_ERROR), - DECL(ALC_INVALID_DEVICE), - DECL(ALC_INVALID_CONTEXT), - DECL(ALC_INVALID_ENUM), - DECL(ALC_INVALID_VALUE), - DECL(ALC_OUT_OF_MEMORY), - - DECL(ALC_CONTEXT_FLAGS_EXT), - DECL(ALC_CONTEXT_DEBUG_BIT_EXT), - - - DECL(AL_INVALID), - DECL(AL_NONE), - DECL(AL_FALSE), - DECL(AL_TRUE), - - DECL(AL_SOURCE_RELATIVE), - DECL(AL_CONE_INNER_ANGLE), - DECL(AL_CONE_OUTER_ANGLE), - DECL(AL_PITCH), - DECL(AL_POSITION), - DECL(AL_DIRECTION), - DECL(AL_VELOCITY), - DECL(AL_LOOPING), - DECL(AL_BUFFER), - DECL(AL_GAIN), - DECL(AL_MIN_GAIN), - DECL(AL_MAX_GAIN), - DECL(AL_ORIENTATION), - DECL(AL_REFERENCE_DISTANCE), - DECL(AL_ROLLOFF_FACTOR), - DECL(AL_CONE_OUTER_GAIN), - DECL(AL_MAX_DISTANCE), - DECL(AL_SEC_OFFSET), - DECL(AL_SAMPLE_OFFSET), - DECL(AL_BYTE_OFFSET), - DECL(AL_SOURCE_TYPE), - DECL(AL_STATIC), - DECL(AL_STREAMING), - DECL(AL_UNDETERMINED), - DECL(AL_METERS_PER_UNIT), - DECL(AL_LOOP_POINTS_SOFT), - DECL(AL_DIRECT_CHANNELS_SOFT), - - DECL(AL_DIRECT_FILTER), - DECL(AL_AUXILIARY_SEND_FILTER), - DECL(AL_AIR_ABSORPTION_FACTOR), - DECL(AL_ROOM_ROLLOFF_FACTOR), - DECL(AL_CONE_OUTER_GAINHF), - DECL(AL_DIRECT_FILTER_GAINHF_AUTO), - DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO), - DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO), - - DECL(AL_SOURCE_STATE), - DECL(AL_INITIAL), - DECL(AL_PLAYING), - DECL(AL_PAUSED), - DECL(AL_STOPPED), - - DECL(AL_BUFFERS_QUEUED), - DECL(AL_BUFFERS_PROCESSED), - - DECL(AL_FORMAT_MONO8), - DECL(AL_FORMAT_MONO16), - DECL(AL_FORMAT_MONO_FLOAT32), - DECL(AL_FORMAT_MONO_DOUBLE_EXT), - DECL(AL_FORMAT_STEREO8), - DECL(AL_FORMAT_STEREO16), - DECL(AL_FORMAT_STEREO_FLOAT32), - DECL(AL_FORMAT_STEREO_DOUBLE_EXT), - DECL(AL_FORMAT_MONO_IMA4), - DECL(AL_FORMAT_STEREO_IMA4), - DECL(AL_FORMAT_MONO_MSADPCM_SOFT), - DECL(AL_FORMAT_STEREO_MSADPCM_SOFT), - DECL(AL_FORMAT_QUAD8_LOKI), - DECL(AL_FORMAT_QUAD16_LOKI), - DECL(AL_FORMAT_QUAD8), - DECL(AL_FORMAT_QUAD16), - DECL(AL_FORMAT_QUAD32), - DECL(AL_FORMAT_51CHN8), - DECL(AL_FORMAT_51CHN16), - DECL(AL_FORMAT_51CHN32), - DECL(AL_FORMAT_61CHN8), - DECL(AL_FORMAT_61CHN16), - DECL(AL_FORMAT_61CHN32), - DECL(AL_FORMAT_71CHN8), - DECL(AL_FORMAT_71CHN16), - DECL(AL_FORMAT_71CHN32), - DECL(AL_FORMAT_REAR8), - DECL(AL_FORMAT_REAR16), - DECL(AL_FORMAT_REAR32), - DECL(AL_FORMAT_MONO_MULAW), - DECL(AL_FORMAT_MONO_MULAW_EXT), - DECL(AL_FORMAT_STEREO_MULAW), - DECL(AL_FORMAT_STEREO_MULAW_EXT), - DECL(AL_FORMAT_QUAD_MULAW), - DECL(AL_FORMAT_51CHN_MULAW), - DECL(AL_FORMAT_61CHN_MULAW), - DECL(AL_FORMAT_71CHN_MULAW), - DECL(AL_FORMAT_REAR_MULAW), - DECL(AL_FORMAT_MONO_ALAW_EXT), - DECL(AL_FORMAT_STEREO_ALAW_EXT), - - DECL(AL_FORMAT_BFORMAT2D_8), - DECL(AL_FORMAT_BFORMAT2D_16), - DECL(AL_FORMAT_BFORMAT2D_FLOAT32), - DECL(AL_FORMAT_BFORMAT2D_MULAW), - DECL(AL_FORMAT_BFORMAT3D_8), - DECL(AL_FORMAT_BFORMAT3D_16), - DECL(AL_FORMAT_BFORMAT3D_FLOAT32), - DECL(AL_FORMAT_BFORMAT3D_MULAW), - - DECL(AL_FREQUENCY), - DECL(AL_BITS), - DECL(AL_CHANNELS), - DECL(AL_SIZE), - DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT), - DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT), - - DECL(AL_SOURCE_RADIUS), - - DECL(AL_SAMPLE_OFFSET_LATENCY_SOFT), - DECL(AL_SEC_OFFSET_LATENCY_SOFT), - - DECL(AL_STEREO_ANGLES), - - DECL(AL_UNUSED), - DECL(AL_PENDING), - DECL(AL_PROCESSED), - - DECL(AL_NO_ERROR), - DECL(AL_INVALID_NAME), - DECL(AL_INVALID_ENUM), - DECL(AL_INVALID_VALUE), - DECL(AL_INVALID_OPERATION), - DECL(AL_OUT_OF_MEMORY), - - DECL(AL_VENDOR), - DECL(AL_VERSION), - DECL(AL_RENDERER), - DECL(AL_EXTENSIONS), - - DECL(AL_DOPPLER_FACTOR), - DECL(AL_DOPPLER_VELOCITY), - DECL(AL_DISTANCE_MODEL), - DECL(AL_SPEED_OF_SOUND), - DECL(AL_SOURCE_DISTANCE_MODEL), - DECL(AL_DEFERRED_UPDATES_SOFT), - DECL(AL_GAIN_LIMIT_SOFT), - - DECL(AL_INVERSE_DISTANCE), - DECL(AL_INVERSE_DISTANCE_CLAMPED), - DECL(AL_LINEAR_DISTANCE), - DECL(AL_LINEAR_DISTANCE_CLAMPED), - DECL(AL_EXPONENT_DISTANCE), - DECL(AL_EXPONENT_DISTANCE_CLAMPED), - - DECL(AL_FILTER_TYPE), - DECL(AL_FILTER_NULL), - DECL(AL_FILTER_LOWPASS), - DECL(AL_FILTER_HIGHPASS), - DECL(AL_FILTER_BANDPASS), - - DECL(AL_LOWPASS_GAIN), - DECL(AL_LOWPASS_GAINHF), - - DECL(AL_HIGHPASS_GAIN), - DECL(AL_HIGHPASS_GAINLF), - - DECL(AL_BANDPASS_GAIN), - DECL(AL_BANDPASS_GAINHF), - DECL(AL_BANDPASS_GAINLF), - - DECL(AL_EFFECT_TYPE), - DECL(AL_EFFECT_NULL), - DECL(AL_EFFECT_REVERB), - DECL(AL_EFFECT_EAXREVERB), - DECL(AL_EFFECT_CHORUS), - DECL(AL_EFFECT_DISTORTION), - DECL(AL_EFFECT_ECHO), - DECL(AL_EFFECT_FLANGER), - DECL(AL_EFFECT_PITCH_SHIFTER), - DECL(AL_EFFECT_FREQUENCY_SHIFTER), - DECL(AL_EFFECT_VOCAL_MORPHER), - DECL(AL_EFFECT_RING_MODULATOR), - DECL(AL_EFFECT_AUTOWAH), - DECL(AL_EFFECT_COMPRESSOR), - DECL(AL_EFFECT_EQUALIZER), - DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT), - DECL(AL_EFFECT_DEDICATED_DIALOGUE), - - DECL(AL_EFFECTSLOT_EFFECT), - DECL(AL_EFFECTSLOT_GAIN), - DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO), - DECL(AL_EFFECTSLOT_NULL), - - DECL(AL_EAXREVERB_DENSITY), - DECL(AL_EAXREVERB_DIFFUSION), - DECL(AL_EAXREVERB_GAIN), - DECL(AL_EAXREVERB_GAINHF), - DECL(AL_EAXREVERB_GAINLF), - DECL(AL_EAXREVERB_DECAY_TIME), - DECL(AL_EAXREVERB_DECAY_HFRATIO), - DECL(AL_EAXREVERB_DECAY_LFRATIO), - DECL(AL_EAXREVERB_REFLECTIONS_GAIN), - DECL(AL_EAXREVERB_REFLECTIONS_DELAY), - DECL(AL_EAXREVERB_REFLECTIONS_PAN), - DECL(AL_EAXREVERB_LATE_REVERB_GAIN), - DECL(AL_EAXREVERB_LATE_REVERB_DELAY), - DECL(AL_EAXREVERB_LATE_REVERB_PAN), - DECL(AL_EAXREVERB_ECHO_TIME), - DECL(AL_EAXREVERB_ECHO_DEPTH), - DECL(AL_EAXREVERB_MODULATION_TIME), - DECL(AL_EAXREVERB_MODULATION_DEPTH), - DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF), - DECL(AL_EAXREVERB_HFREFERENCE), - DECL(AL_EAXREVERB_LFREFERENCE), - DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR), - DECL(AL_EAXREVERB_DECAY_HFLIMIT), - - DECL(AL_REVERB_DENSITY), - DECL(AL_REVERB_DIFFUSION), - DECL(AL_REVERB_GAIN), - DECL(AL_REVERB_GAINHF), - DECL(AL_REVERB_DECAY_TIME), - DECL(AL_REVERB_DECAY_HFRATIO), - DECL(AL_REVERB_REFLECTIONS_GAIN), - DECL(AL_REVERB_REFLECTIONS_DELAY), - DECL(AL_REVERB_LATE_REVERB_GAIN), - DECL(AL_REVERB_LATE_REVERB_DELAY), - DECL(AL_REVERB_AIR_ABSORPTION_GAINHF), - DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR), - DECL(AL_REVERB_DECAY_HFLIMIT), - - DECL(AL_CHORUS_WAVEFORM), - DECL(AL_CHORUS_PHASE), - DECL(AL_CHORUS_RATE), - DECL(AL_CHORUS_DEPTH), - DECL(AL_CHORUS_FEEDBACK), - DECL(AL_CHORUS_DELAY), - - DECL(AL_DISTORTION_EDGE), - DECL(AL_DISTORTION_GAIN), - DECL(AL_DISTORTION_LOWPASS_CUTOFF), - DECL(AL_DISTORTION_EQCENTER), - DECL(AL_DISTORTION_EQBANDWIDTH), - - DECL(AL_ECHO_DELAY), - DECL(AL_ECHO_LRDELAY), - DECL(AL_ECHO_DAMPING), - DECL(AL_ECHO_FEEDBACK), - DECL(AL_ECHO_SPREAD), - - DECL(AL_FLANGER_WAVEFORM), - DECL(AL_FLANGER_PHASE), - DECL(AL_FLANGER_RATE), - DECL(AL_FLANGER_DEPTH), - DECL(AL_FLANGER_FEEDBACK), - DECL(AL_FLANGER_DELAY), - - DECL(AL_FREQUENCY_SHIFTER_FREQUENCY), - DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION), - DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION), - - DECL(AL_RING_MODULATOR_FREQUENCY), - DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF), - DECL(AL_RING_MODULATOR_WAVEFORM), - - DECL(AL_PITCH_SHIFTER_COARSE_TUNE), - DECL(AL_PITCH_SHIFTER_FINE_TUNE), - - DECL(AL_COMPRESSOR_ONOFF), - - DECL(AL_EQUALIZER_LOW_GAIN), - DECL(AL_EQUALIZER_LOW_CUTOFF), - DECL(AL_EQUALIZER_MID1_GAIN), - DECL(AL_EQUALIZER_MID1_CENTER), - DECL(AL_EQUALIZER_MID1_WIDTH), - DECL(AL_EQUALIZER_MID2_GAIN), - DECL(AL_EQUALIZER_MID2_CENTER), - DECL(AL_EQUALIZER_MID2_WIDTH), - DECL(AL_EQUALIZER_HIGH_GAIN), - DECL(AL_EQUALIZER_HIGH_CUTOFF), - - DECL(AL_DEDICATED_GAIN), - - DECL(AL_AUTOWAH_ATTACK_TIME), - DECL(AL_AUTOWAH_RELEASE_TIME), - DECL(AL_AUTOWAH_RESONANCE), - DECL(AL_AUTOWAH_PEAK_GAIN), - - DECL(AL_VOCAL_MORPHER_PHONEMEA), - DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING), - DECL(AL_VOCAL_MORPHER_PHONEMEB), - DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING), - DECL(AL_VOCAL_MORPHER_WAVEFORM), - DECL(AL_VOCAL_MORPHER_RATE), - - DECL(AL_EFFECTSLOT_TARGET_SOFT), - - DECL(AL_NUM_RESAMPLERS_SOFT), - DECL(AL_DEFAULT_RESAMPLER_SOFT), - DECL(AL_SOURCE_RESAMPLER_SOFT), - DECL(AL_RESAMPLER_NAME_SOFT), - - DECL(AL_SOURCE_SPATIALIZE_SOFT), - DECL(AL_AUTO_SOFT), - - DECL(AL_MAP_READ_BIT_SOFT), - DECL(AL_MAP_WRITE_BIT_SOFT), - DECL(AL_MAP_PERSISTENT_BIT_SOFT), - DECL(AL_PRESERVE_DATA_BIT_SOFT), - - DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT), - DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT), - DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT), - DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT), - DECL(AL_EVENT_TYPE_DISCONNECTED_SOFT), - - DECL(AL_DROP_UNMATCHED_SOFT), - DECL(AL_REMIX_UNMATCHED_SOFT), - - DECL(AL_AMBISONIC_LAYOUT_SOFT), - DECL(AL_AMBISONIC_SCALING_SOFT), - DECL(AL_FUMA_SOFT), - DECL(AL_ACN_SOFT), - DECL(AL_SN3D_SOFT), - DECL(AL_N3D_SOFT), - - DECL(AL_BUFFER_CALLBACK_FUNCTION_SOFT), - DECL(AL_BUFFER_CALLBACK_USER_PARAM_SOFT), - - DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT), - - DECL(AL_EFFECT_CONVOLUTION_REVERB_SOFT), - DECL(AL_EFFECTSLOT_STATE_SOFT), - - DECL(AL_FORMAT_UHJ2CHN8_SOFT), - DECL(AL_FORMAT_UHJ2CHN16_SOFT), - DECL(AL_FORMAT_UHJ2CHN_FLOAT32_SOFT), - DECL(AL_FORMAT_UHJ3CHN8_SOFT), - DECL(AL_FORMAT_UHJ3CHN16_SOFT), - DECL(AL_FORMAT_UHJ3CHN_FLOAT32_SOFT), - DECL(AL_FORMAT_UHJ4CHN8_SOFT), - DECL(AL_FORMAT_UHJ4CHN16_SOFT), - DECL(AL_FORMAT_UHJ4CHN_FLOAT32_SOFT), - DECL(AL_STEREO_MODE_SOFT), - DECL(AL_NORMAL_SOFT), - DECL(AL_SUPER_STEREO_SOFT), - DECL(AL_SUPER_STEREO_WIDTH_SOFT), - - DECL(AL_FORMAT_UHJ2CHN_MULAW_SOFT), - DECL(AL_FORMAT_UHJ2CHN_ALAW_SOFT), - DECL(AL_FORMAT_UHJ2CHN_IMA4_SOFT), - DECL(AL_FORMAT_UHJ2CHN_MSADPCM_SOFT), - DECL(AL_FORMAT_UHJ3CHN_MULAW_SOFT), - DECL(AL_FORMAT_UHJ3CHN_ALAW_SOFT), - DECL(AL_FORMAT_UHJ4CHN_MULAW_SOFT), - DECL(AL_FORMAT_UHJ4CHN_ALAW_SOFT), - - DECL(AL_DONT_CARE_EXT), - DECL(AL_DEBUG_OUTPUT_EXT), - DECL(AL_DEBUG_CALLBACK_FUNCTION_EXT), - DECL(AL_DEBUG_CALLBACK_USER_PARAM_EXT), - DECL(AL_DEBUG_SOURCE_API_EXT), - DECL(AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT), - DECL(AL_DEBUG_SOURCE_THIRD_PARTY_EXT), - DECL(AL_DEBUG_SOURCE_APPLICATION_EXT), - DECL(AL_DEBUG_SOURCE_OTHER_EXT), - DECL(AL_DEBUG_TYPE_ERROR_EXT), - DECL(AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT), - DECL(AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT), - DECL(AL_DEBUG_TYPE_PORTABILITY_EXT), - DECL(AL_DEBUG_TYPE_PERFORMANCE_EXT), - DECL(AL_DEBUG_TYPE_MARKER_EXT), - DECL(AL_DEBUG_TYPE_PUSH_GROUP_EXT), - DECL(AL_DEBUG_TYPE_POP_GROUP_EXT), - DECL(AL_DEBUG_TYPE_OTHER_EXT), - DECL(AL_DEBUG_SEVERITY_HIGH_EXT), - DECL(AL_DEBUG_SEVERITY_MEDIUM_EXT), - DECL(AL_DEBUG_SEVERITY_LOW_EXT), - DECL(AL_DEBUG_SEVERITY_NOTIFICATION_EXT), - DECL(AL_DEBUG_LOGGED_MESSAGES_EXT), - DECL(AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT), - DECL(AL_MAX_DEBUG_MESSAGE_LENGTH_EXT), - DECL(AL_MAX_DEBUG_LOGGED_MESSAGES_EXT), - DECL(AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT), - DECL(AL_STACK_OVERFLOW_EXT), - DECL(AL_STACK_UNDERFLOW_EXT), - - DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), - -#ifdef ALSOFT_EAX -}, eaxEnumerations[] = { - DECL(AL_EAX_RAM_SIZE), - DECL(AL_EAX_RAM_FREE), - DECL(AL_STORAGE_AUTOMATIC), - DECL(AL_STORAGE_HARDWARE), - DECL(AL_STORAGE_ACCESSIBLE), -#endif // ALSOFT_EAX -}; -#undef DECL - constexpr ALCchar alcNoError[] = "No Error"; constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device"; constexpr ALCchar alcErrInvalidContext[] = "Invalid Context"; diff --git a/alc/export_list.h b/alc/export_list.h new file mode 100644 index 00000000..7b347e76 --- /dev/null +++ b/alc/export_list.h @@ -0,0 +1,877 @@ +#ifndef ALC_EXPORT_LIST_H +#define ALC_EXPORT_LIST_H + +#include "AL/alc.h" +#include "AL/al.h" +#include "AL/alext.h" + +#include "inprogext.h" +#ifdef ALSOFT_EAX +#include "context.h" +#include "al/eax/x_ram.h" +#endif + + +struct FuncExport { + const char *funcName; + void *address; +}; +#define DECL(x) { #x, reinterpret_cast(x) } +inline const FuncExport alcFunctions[]{ + DECL(alcCreateContext), + DECL(alcMakeContextCurrent), + DECL(alcProcessContext), + DECL(alcSuspendContext), + DECL(alcDestroyContext), + DECL(alcGetCurrentContext), + DECL(alcGetContextsDevice), + DECL(alcOpenDevice), + DECL(alcCloseDevice), + DECL(alcGetError), + DECL(alcIsExtensionPresent), + DECL(alcGetProcAddress), + DECL(alcGetEnumValue), + DECL(alcGetString), + DECL(alcGetIntegerv), + DECL(alcCaptureOpenDevice), + DECL(alcCaptureCloseDevice), + DECL(alcCaptureStart), + DECL(alcCaptureStop), + DECL(alcCaptureSamples), + + DECL(alcSetThreadContext), + DECL(alcGetThreadContext), + + DECL(alcLoopbackOpenDeviceSOFT), + DECL(alcIsRenderFormatSupportedSOFT), + DECL(alcRenderSamplesSOFT), + + DECL(alcDevicePauseSOFT), + DECL(alcDeviceResumeSOFT), + + DECL(alcGetStringiSOFT), + DECL(alcResetDeviceSOFT), + + DECL(alcGetInteger64vSOFT), + + DECL(alcReopenDeviceSOFT), + + DECL(alEnable), + DECL(alDisable), + DECL(alIsEnabled), + DECL(alGetString), + DECL(alGetBooleanv), + DECL(alGetIntegerv), + DECL(alGetFloatv), + DECL(alGetDoublev), + DECL(alGetBoolean), + DECL(alGetInteger), + DECL(alGetFloat), + DECL(alGetDouble), + DECL(alGetError), + DECL(alIsExtensionPresent), + DECL(alGetProcAddress), + DECL(alGetEnumValue), + DECL(alListenerf), + DECL(alListener3f), + DECL(alListenerfv), + DECL(alListeneri), + DECL(alListener3i), + DECL(alListeneriv), + DECL(alGetListenerf), + DECL(alGetListener3f), + DECL(alGetListenerfv), + DECL(alGetListeneri), + DECL(alGetListener3i), + DECL(alGetListeneriv), + DECL(alGenSources), + DECL(alDeleteSources), + DECL(alIsSource), + DECL(alSourcef), + DECL(alSource3f), + DECL(alSourcefv), + DECL(alSourcei), + DECL(alSource3i), + DECL(alSourceiv), + DECL(alGetSourcef), + DECL(alGetSource3f), + DECL(alGetSourcefv), + DECL(alGetSourcei), + DECL(alGetSource3i), + DECL(alGetSourceiv), + DECL(alSourcePlayv), + DECL(alSourceStopv), + DECL(alSourceRewindv), + DECL(alSourcePausev), + DECL(alSourcePlay), + DECL(alSourceStop), + DECL(alSourceRewind), + DECL(alSourcePause), + DECL(alSourceQueueBuffers), + DECL(alSourceUnqueueBuffers), + DECL(alGenBuffers), + DECL(alDeleteBuffers), + DECL(alIsBuffer), + DECL(alBufferData), + DECL(alBufferf), + DECL(alBuffer3f), + DECL(alBufferfv), + DECL(alBufferi), + DECL(alBuffer3i), + DECL(alBufferiv), + DECL(alGetBufferf), + DECL(alGetBuffer3f), + DECL(alGetBufferfv), + DECL(alGetBufferi), + DECL(alGetBuffer3i), + DECL(alGetBufferiv), + DECL(alDopplerFactor), + DECL(alDopplerVelocity), + DECL(alSpeedOfSound), + DECL(alDistanceModel), + + DECL(alGenFilters), + DECL(alDeleteFilters), + DECL(alIsFilter), + DECL(alFilteri), + DECL(alFilteriv), + DECL(alFilterf), + DECL(alFilterfv), + DECL(alGetFilteri), + DECL(alGetFilteriv), + DECL(alGetFilterf), + DECL(alGetFilterfv), + DECL(alGenEffects), + DECL(alDeleteEffects), + DECL(alIsEffect), + DECL(alEffecti), + DECL(alEffectiv), + DECL(alEffectf), + DECL(alEffectfv), + DECL(alGetEffecti), + DECL(alGetEffectiv), + DECL(alGetEffectf), + DECL(alGetEffectfv), + DECL(alGenAuxiliaryEffectSlots), + DECL(alDeleteAuxiliaryEffectSlots), + DECL(alIsAuxiliaryEffectSlot), + DECL(alAuxiliaryEffectSloti), + DECL(alAuxiliaryEffectSlotiv), + DECL(alAuxiliaryEffectSlotf), + DECL(alAuxiliaryEffectSlotfv), + DECL(alGetAuxiliaryEffectSloti), + DECL(alGetAuxiliaryEffectSlotiv), + DECL(alGetAuxiliaryEffectSlotf), + DECL(alGetAuxiliaryEffectSlotfv), + + DECL(alDeferUpdatesSOFT), + DECL(alProcessUpdatesSOFT), + + DECL(alSourcedSOFT), + DECL(alSource3dSOFT), + DECL(alSourcedvSOFT), + DECL(alGetSourcedSOFT), + DECL(alGetSource3dSOFT), + DECL(alGetSourcedvSOFT), + DECL(alSourcei64SOFT), + DECL(alSource3i64SOFT), + DECL(alSourcei64vSOFT), + DECL(alGetSourcei64SOFT), + DECL(alGetSource3i64SOFT), + DECL(alGetSourcei64vSOFT), + + DECL(alGetStringiSOFT), + + DECL(alBufferStorageSOFT), + DECL(alMapBufferSOFT), + DECL(alUnmapBufferSOFT), + DECL(alFlushMappedBufferSOFT), + + DECL(alEventControlSOFT), + DECL(alEventCallbackSOFT), + DECL(alGetPointerSOFT), + DECL(alGetPointervSOFT), + + DECL(alBufferCallbackSOFT), + DECL(alGetBufferPtrSOFT), + DECL(alGetBuffer3PtrSOFT), + DECL(alGetBufferPtrvSOFT), + + DECL(alAuxiliaryEffectSlotPlaySOFT), + DECL(alAuxiliaryEffectSlotPlayvSOFT), + DECL(alAuxiliaryEffectSlotStopSOFT), + DECL(alAuxiliaryEffectSlotStopvSOFT), + + DECL(alSourcePlayAtTimeSOFT), + DECL(alSourcePlayAtTimevSOFT), + + DECL(alBufferSubDataSOFT), + + DECL(alBufferDataStatic), + + DECL(alDebugMessageCallbackEXT), + DECL(alDebugMessageInsertEXT), + DECL(alDebugMessageControlEXT), + DECL(alPushDebugGroupEXT), + DECL(alPopDebugGroupEXT), + DECL(alGetDebugMessageLogEXT), + + /* Direct Context functions */ + DECL(alEnableDirect), + DECL(alDisableDirect), + DECL(alIsEnabledDirect), + DECL(alDopplerFactorDirect), + DECL(alSpeedOfSoundDirect), + DECL(alDistanceModelDirect), + DECL(alGetStringDirect), + DECL(alGetBooleanvDirect), + DECL(alGetIntegervDirect), + DECL(alGetFloatvDirect), + DECL(alGetDoublevDirect), + DECL(alGetBooleanDirect), + DECL(alGetIntegerDirect), + DECL(alGetFloatDirect), + DECL(alGetDoubleDirect), + + DECL(alGetErrorDirect), + DECL(alIsExtensionPresentDirect), + DECL(alGetProcAddress), + DECL(alGetEnumValueDirect), + + DECL(alListeneriDirect), + DECL(alListener3iDirect), + DECL(alListenerivDirect), + DECL(alListenerfDirect), + DECL(alListener3fDirect), + DECL(alListenerfvDirect), + DECL(alGetListeneriDirect), + DECL(alGetListener3iDirect), + DECL(alGetListenerivDirect), + DECL(alGetListenerfDirect), + DECL(alGetListener3fDirect), + DECL(alGetListenerfvDirect), + + DECL(alGenBuffersDirect), + DECL(alDeleteBuffersDirect), + DECL(alIsBufferDirect), + DECL(alBufferDataDirect), + DECL(alBufferiDirect), + DECL(alBuffer3iDirect), + DECL(alBufferivDirect), + DECL(alBufferfDirect), + DECL(alBuffer3fDirect), + DECL(alBufferfvDirect), + DECL(alGetBufferiDirect), + DECL(alGetBuffer3iDirect), + DECL(alGetBufferivDirect), + DECL(alGetBufferfDirect), + DECL(alGetBuffer3fDirect), + DECL(alGetBufferfvDirect), + + DECL(alGenSourcesDirect), + DECL(alDeleteSourcesDirect), + DECL(alIsSourceDirect), + DECL(alSourcePlayDirect), + DECL(alSourceStopDirect), + DECL(alSourcePauseDirect), + DECL(alSourceRewindDirect), + DECL(alSourcePlayvDirect), + DECL(alSourceStopvDirect), + DECL(alSourcePausevDirect), + DECL(alSourceRewindvDirect), + DECL(alSourceiDirect), + DECL(alSource3iDirect), + DECL(alSourceivDirect), + DECL(alSourcefDirect), + DECL(alSource3fDirect), + DECL(alSourcefvDirect), + DECL(alGetSourceiDirect), + DECL(alGetSource3iDirect), + DECL(alGetSourceivDirect), + DECL(alGetSourcefDirect), + DECL(alGetSource3fDirect), + DECL(alGetSourcefvDirect), + DECL(alSourceQueueBuffersDirect), + DECL(alSourceUnqueueBuffersDirect), + + DECL(alGenFiltersDirect), + DECL(alDeleteFiltersDirect), + DECL(alIsFilterDirect), + DECL(alFilteriDirect), + DECL(alFilterivDirect), + DECL(alFilterfDirect), + DECL(alFilterfvDirect), + DECL(alGetFilteriDirect), + DECL(alGetFilterivDirect), + DECL(alGetFilterfDirect), + DECL(alGetFilterfvDirect), + DECL(alGenEffectsDirect), + DECL(alDeleteEffectsDirect), + DECL(alIsEffectDirect), + DECL(alEffectiDirect), + DECL(alEffectivDirect), + DECL(alEffectfDirect), + DECL(alEffectfvDirect), + DECL(alGetEffectiDirect), + DECL(alGetEffectivDirect), + DECL(alGetEffectfDirect), + DECL(alGetEffectfvDirect), + DECL(alGenAuxiliaryEffectSlotsDirect), + DECL(alDeleteAuxiliaryEffectSlotsDirect), + DECL(alIsAuxiliaryEffectSlotDirect), + DECL(alAuxiliaryEffectSlotiDirect), + DECL(alAuxiliaryEffectSlotivDirect), + DECL(alAuxiliaryEffectSlotfDirect), + DECL(alAuxiliaryEffectSlotfvDirect), + DECL(alGetAuxiliaryEffectSlotiDirect), + DECL(alGetAuxiliaryEffectSlotivDirect), + DECL(alGetAuxiliaryEffectSlotfDirect), + DECL(alGetAuxiliaryEffectSlotfvDirect), + + DECL(alDeferUpdatesDirectSOFT), + DECL(alProcessUpdatesDirectSOFT), + DECL(alGetStringiDirectSOFT), + + DECL(alBufferDataStaticDirect), + DECL(alBufferCallbackDirectSOFT), + DECL(alBufferSubDataDirectSOFT), + DECL(alBufferStorageDirectSOFT), + DECL(alMapBufferDirectSOFT), + DECL(alUnmapBufferDirectSOFT), + DECL(alFlushMappedBufferDirectSOFT), + + DECL(alSourcei64DirectSOFT), + DECL(alSource3i64DirectSOFT), + DECL(alSourcei64vDirectSOFT), + DECL(alSourcedDirectSOFT), + DECL(alSource3dDirectSOFT), + DECL(alSourcedvDirectSOFT), + DECL(alGetSourcei64DirectSOFT), + DECL(alGetSource3i64DirectSOFT), + DECL(alGetSourcei64vDirectSOFT), + DECL(alGetSourcedDirectSOFT), + DECL(alGetSource3dDirectSOFT), + DECL(alGetSourcedvDirectSOFT), + DECL(alSourcePlayAtTimeDirectSOFT), + DECL(alSourcePlayAtTimevDirectSOFT), + + DECL(alEventControlDirectSOFT), + DECL(alEventCallbackDirectSOFT), + + DECL(alDebugMessageCallbackDirectEXT), + DECL(alDebugMessageInsertDirectEXT), + DECL(alDebugMessageControlDirectEXT), + DECL(alPushDebugGroupDirectEXT), + DECL(alPopDebugGroupDirectEXT), + DECL(alGetDebugMessageLogDirectEXT), + + DECL(alcEventControlSOFT), + DECL(alcEventCallbackSOFT), +#ifdef ALSOFT_EAX +}, eaxFunctions[]{ + DECL(EAXGet), + DECL(EAXSet), + DECL(EAXGetBufferMode), + DECL(EAXSetBufferMode), + + DECL(EAXGetDirect), + DECL(EAXSetDirect), + DECL(EAXGetBufferModeDirect), + DECL(EAXSetBufferModeDirect), +#endif +}; +#undef DECL + +struct EnumExport { + const char *enumName; + int value; +}; +#define DECL(x) { #x, (x) } +inline const EnumExport alcEnumerations[]{ + DECL(ALC_INVALID), + DECL(ALC_FALSE), + DECL(ALC_TRUE), + + DECL(ALC_MAJOR_VERSION), + DECL(ALC_MINOR_VERSION), + DECL(ALC_ATTRIBUTES_SIZE), + DECL(ALC_ALL_ATTRIBUTES), + DECL(ALC_DEFAULT_DEVICE_SPECIFIER), + DECL(ALC_DEVICE_SPECIFIER), + DECL(ALC_ALL_DEVICES_SPECIFIER), + DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER), + DECL(ALC_EXTENSIONS), + DECL(ALC_FREQUENCY), + DECL(ALC_REFRESH), + DECL(ALC_SYNC), + DECL(ALC_MONO_SOURCES), + DECL(ALC_STEREO_SOURCES), + DECL(ALC_CAPTURE_DEVICE_SPECIFIER), + DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER), + DECL(ALC_CAPTURE_SAMPLES), + DECL(ALC_CONNECTED), + + DECL(ALC_EFX_MAJOR_VERSION), + DECL(ALC_EFX_MINOR_VERSION), + DECL(ALC_MAX_AUXILIARY_SENDS), + + DECL(ALC_FORMAT_CHANNELS_SOFT), + DECL(ALC_FORMAT_TYPE_SOFT), + + DECL(ALC_MONO_SOFT), + DECL(ALC_STEREO_SOFT), + DECL(ALC_QUAD_SOFT), + 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), + DECL(ALC_SHORT_SOFT), + DECL(ALC_UNSIGNED_SHORT_SOFT), + DECL(ALC_INT_SOFT), + DECL(ALC_UNSIGNED_INT_SOFT), + DECL(ALC_FLOAT_SOFT), + + DECL(ALC_HRTF_SOFT), + DECL(ALC_DONT_CARE_SOFT), + DECL(ALC_HRTF_STATUS_SOFT), + DECL(ALC_HRTF_DISABLED_SOFT), + DECL(ALC_HRTF_ENABLED_SOFT), + DECL(ALC_HRTF_DENIED_SOFT), + DECL(ALC_HRTF_REQUIRED_SOFT), + DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT), + DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT), + DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT), + 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_OUTPUT_LIMITER_SOFT), + + DECL(ALC_DEVICE_CLOCK_SOFT), + DECL(ALC_DEVICE_LATENCY_SOFT), + DECL(ALC_DEVICE_CLOCK_LATENCY_SOFT), + DECL(AL_SAMPLE_OFFSET_CLOCK_SOFT), + DECL(AL_SEC_OFFSET_CLOCK_SOFT), + + DECL(ALC_OUTPUT_MODE_SOFT), + DECL(ALC_ANY_SOFT), + DECL(ALC_STEREO_BASIC_SOFT), + DECL(ALC_STEREO_UHJ_SOFT), + DECL(ALC_STEREO_HRTF_SOFT), + DECL(ALC_SURROUND_5_1_SOFT), + DECL(ALC_SURROUND_6_1_SOFT), + DECL(ALC_SURROUND_7_1_SOFT), + + DECL(ALC_NO_ERROR), + DECL(ALC_INVALID_DEVICE), + DECL(ALC_INVALID_CONTEXT), + DECL(ALC_INVALID_ENUM), + DECL(ALC_INVALID_VALUE), + DECL(ALC_OUT_OF_MEMORY), + + DECL(ALC_CONTEXT_FLAGS_EXT), + DECL(ALC_CONTEXT_DEBUG_BIT_EXT), + + + DECL(AL_INVALID), + DECL(AL_NONE), + DECL(AL_FALSE), + DECL(AL_TRUE), + + DECL(AL_SOURCE_RELATIVE), + DECL(AL_CONE_INNER_ANGLE), + DECL(AL_CONE_OUTER_ANGLE), + DECL(AL_PITCH), + DECL(AL_POSITION), + DECL(AL_DIRECTION), + DECL(AL_VELOCITY), + DECL(AL_LOOPING), + DECL(AL_BUFFER), + DECL(AL_GAIN), + DECL(AL_MIN_GAIN), + DECL(AL_MAX_GAIN), + DECL(AL_ORIENTATION), + DECL(AL_REFERENCE_DISTANCE), + DECL(AL_ROLLOFF_FACTOR), + DECL(AL_CONE_OUTER_GAIN), + DECL(AL_MAX_DISTANCE), + DECL(AL_SEC_OFFSET), + DECL(AL_SAMPLE_OFFSET), + DECL(AL_BYTE_OFFSET), + DECL(AL_SOURCE_TYPE), + DECL(AL_STATIC), + DECL(AL_STREAMING), + DECL(AL_UNDETERMINED), + DECL(AL_METERS_PER_UNIT), + DECL(AL_LOOP_POINTS_SOFT), + DECL(AL_DIRECT_CHANNELS_SOFT), + + DECL(AL_DIRECT_FILTER), + DECL(AL_AUXILIARY_SEND_FILTER), + DECL(AL_AIR_ABSORPTION_FACTOR), + DECL(AL_ROOM_ROLLOFF_FACTOR), + DECL(AL_CONE_OUTER_GAINHF), + DECL(AL_DIRECT_FILTER_GAINHF_AUTO), + DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO), + DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO), + + DECL(AL_SOURCE_STATE), + DECL(AL_INITIAL), + DECL(AL_PLAYING), + DECL(AL_PAUSED), + DECL(AL_STOPPED), + + DECL(AL_BUFFERS_QUEUED), + DECL(AL_BUFFERS_PROCESSED), + + DECL(AL_FORMAT_MONO8), + DECL(AL_FORMAT_MONO16), + DECL(AL_FORMAT_MONO_FLOAT32), + DECL(AL_FORMAT_MONO_DOUBLE_EXT), + DECL(AL_FORMAT_STEREO8), + DECL(AL_FORMAT_STEREO16), + DECL(AL_FORMAT_STEREO_FLOAT32), + DECL(AL_FORMAT_STEREO_DOUBLE_EXT), + DECL(AL_FORMAT_MONO_IMA4), + DECL(AL_FORMAT_STEREO_IMA4), + DECL(AL_FORMAT_MONO_MSADPCM_SOFT), + DECL(AL_FORMAT_STEREO_MSADPCM_SOFT), + DECL(AL_FORMAT_QUAD8_LOKI), + DECL(AL_FORMAT_QUAD16_LOKI), + DECL(AL_FORMAT_QUAD8), + DECL(AL_FORMAT_QUAD16), + DECL(AL_FORMAT_QUAD32), + DECL(AL_FORMAT_51CHN8), + DECL(AL_FORMAT_51CHN16), + DECL(AL_FORMAT_51CHN32), + DECL(AL_FORMAT_61CHN8), + DECL(AL_FORMAT_61CHN16), + DECL(AL_FORMAT_61CHN32), + DECL(AL_FORMAT_71CHN8), + DECL(AL_FORMAT_71CHN16), + DECL(AL_FORMAT_71CHN32), + DECL(AL_FORMAT_REAR8), + DECL(AL_FORMAT_REAR16), + DECL(AL_FORMAT_REAR32), + DECL(AL_FORMAT_MONO_MULAW), + DECL(AL_FORMAT_MONO_MULAW_EXT), + DECL(AL_FORMAT_STEREO_MULAW), + DECL(AL_FORMAT_STEREO_MULAW_EXT), + DECL(AL_FORMAT_QUAD_MULAW), + DECL(AL_FORMAT_51CHN_MULAW), + DECL(AL_FORMAT_61CHN_MULAW), + DECL(AL_FORMAT_71CHN_MULAW), + DECL(AL_FORMAT_REAR_MULAW), + DECL(AL_FORMAT_MONO_ALAW_EXT), + DECL(AL_FORMAT_STEREO_ALAW_EXT), + + DECL(AL_FORMAT_BFORMAT2D_8), + DECL(AL_FORMAT_BFORMAT2D_16), + DECL(AL_FORMAT_BFORMAT2D_FLOAT32), + DECL(AL_FORMAT_BFORMAT2D_MULAW), + DECL(AL_FORMAT_BFORMAT3D_8), + DECL(AL_FORMAT_BFORMAT3D_16), + DECL(AL_FORMAT_BFORMAT3D_FLOAT32), + DECL(AL_FORMAT_BFORMAT3D_MULAW), + + DECL(AL_FREQUENCY), + DECL(AL_BITS), + DECL(AL_CHANNELS), + DECL(AL_SIZE), + DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT), + DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT), + + DECL(AL_SOURCE_RADIUS), + + DECL(AL_SAMPLE_OFFSET_LATENCY_SOFT), + DECL(AL_SEC_OFFSET_LATENCY_SOFT), + + DECL(AL_STEREO_ANGLES), + + DECL(AL_UNUSED), + DECL(AL_PENDING), + DECL(AL_PROCESSED), + + DECL(AL_NO_ERROR), + DECL(AL_INVALID_NAME), + DECL(AL_INVALID_ENUM), + DECL(AL_INVALID_VALUE), + DECL(AL_INVALID_OPERATION), + DECL(AL_OUT_OF_MEMORY), + + DECL(AL_VENDOR), + DECL(AL_VERSION), + DECL(AL_RENDERER), + DECL(AL_EXTENSIONS), + + DECL(AL_DOPPLER_FACTOR), + DECL(AL_DOPPLER_VELOCITY), + DECL(AL_DISTANCE_MODEL), + DECL(AL_SPEED_OF_SOUND), + DECL(AL_SOURCE_DISTANCE_MODEL), + DECL(AL_DEFERRED_UPDATES_SOFT), + DECL(AL_GAIN_LIMIT_SOFT), + + DECL(AL_INVERSE_DISTANCE), + DECL(AL_INVERSE_DISTANCE_CLAMPED), + DECL(AL_LINEAR_DISTANCE), + DECL(AL_LINEAR_DISTANCE_CLAMPED), + DECL(AL_EXPONENT_DISTANCE), + DECL(AL_EXPONENT_DISTANCE_CLAMPED), + + DECL(AL_FILTER_TYPE), + DECL(AL_FILTER_NULL), + DECL(AL_FILTER_LOWPASS), + DECL(AL_FILTER_HIGHPASS), + DECL(AL_FILTER_BANDPASS), + + DECL(AL_LOWPASS_GAIN), + DECL(AL_LOWPASS_GAINHF), + + DECL(AL_HIGHPASS_GAIN), + DECL(AL_HIGHPASS_GAINLF), + + DECL(AL_BANDPASS_GAIN), + DECL(AL_BANDPASS_GAINHF), + DECL(AL_BANDPASS_GAINLF), + + DECL(AL_EFFECT_TYPE), + DECL(AL_EFFECT_NULL), + DECL(AL_EFFECT_REVERB), + DECL(AL_EFFECT_EAXREVERB), + DECL(AL_EFFECT_CHORUS), + DECL(AL_EFFECT_DISTORTION), + DECL(AL_EFFECT_ECHO), + DECL(AL_EFFECT_FLANGER), + DECL(AL_EFFECT_PITCH_SHIFTER), + DECL(AL_EFFECT_FREQUENCY_SHIFTER), + DECL(AL_EFFECT_VOCAL_MORPHER), + DECL(AL_EFFECT_RING_MODULATOR), + DECL(AL_EFFECT_AUTOWAH), + DECL(AL_EFFECT_COMPRESSOR), + DECL(AL_EFFECT_EQUALIZER), + DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT), + DECL(AL_EFFECT_DEDICATED_DIALOGUE), + + DECL(AL_EFFECTSLOT_EFFECT), + DECL(AL_EFFECTSLOT_GAIN), + DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO), + DECL(AL_EFFECTSLOT_NULL), + + DECL(AL_EAXREVERB_DENSITY), + DECL(AL_EAXREVERB_DIFFUSION), + DECL(AL_EAXREVERB_GAIN), + DECL(AL_EAXREVERB_GAINHF), + DECL(AL_EAXREVERB_GAINLF), + DECL(AL_EAXREVERB_DECAY_TIME), + DECL(AL_EAXREVERB_DECAY_HFRATIO), + DECL(AL_EAXREVERB_DECAY_LFRATIO), + DECL(AL_EAXREVERB_REFLECTIONS_GAIN), + DECL(AL_EAXREVERB_REFLECTIONS_DELAY), + DECL(AL_EAXREVERB_REFLECTIONS_PAN), + DECL(AL_EAXREVERB_LATE_REVERB_GAIN), + DECL(AL_EAXREVERB_LATE_REVERB_DELAY), + DECL(AL_EAXREVERB_LATE_REVERB_PAN), + DECL(AL_EAXREVERB_ECHO_TIME), + DECL(AL_EAXREVERB_ECHO_DEPTH), + DECL(AL_EAXREVERB_MODULATION_TIME), + DECL(AL_EAXREVERB_MODULATION_DEPTH), + DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF), + DECL(AL_EAXREVERB_HFREFERENCE), + DECL(AL_EAXREVERB_LFREFERENCE), + DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR), + DECL(AL_EAXREVERB_DECAY_HFLIMIT), + + DECL(AL_REVERB_DENSITY), + DECL(AL_REVERB_DIFFUSION), + DECL(AL_REVERB_GAIN), + DECL(AL_REVERB_GAINHF), + DECL(AL_REVERB_DECAY_TIME), + DECL(AL_REVERB_DECAY_HFRATIO), + DECL(AL_REVERB_REFLECTIONS_GAIN), + DECL(AL_REVERB_REFLECTIONS_DELAY), + DECL(AL_REVERB_LATE_REVERB_GAIN), + DECL(AL_REVERB_LATE_REVERB_DELAY), + DECL(AL_REVERB_AIR_ABSORPTION_GAINHF), + DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR), + DECL(AL_REVERB_DECAY_HFLIMIT), + + DECL(AL_CHORUS_WAVEFORM), + DECL(AL_CHORUS_PHASE), + DECL(AL_CHORUS_RATE), + DECL(AL_CHORUS_DEPTH), + DECL(AL_CHORUS_FEEDBACK), + DECL(AL_CHORUS_DELAY), + + DECL(AL_DISTORTION_EDGE), + DECL(AL_DISTORTION_GAIN), + DECL(AL_DISTORTION_LOWPASS_CUTOFF), + DECL(AL_DISTORTION_EQCENTER), + DECL(AL_DISTORTION_EQBANDWIDTH), + + DECL(AL_ECHO_DELAY), + DECL(AL_ECHO_LRDELAY), + DECL(AL_ECHO_DAMPING), + DECL(AL_ECHO_FEEDBACK), + DECL(AL_ECHO_SPREAD), + + DECL(AL_FLANGER_WAVEFORM), + DECL(AL_FLANGER_PHASE), + DECL(AL_FLANGER_RATE), + DECL(AL_FLANGER_DEPTH), + DECL(AL_FLANGER_FEEDBACK), + DECL(AL_FLANGER_DELAY), + + DECL(AL_FREQUENCY_SHIFTER_FREQUENCY), + DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION), + DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION), + + DECL(AL_RING_MODULATOR_FREQUENCY), + DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF), + DECL(AL_RING_MODULATOR_WAVEFORM), + + DECL(AL_PITCH_SHIFTER_COARSE_TUNE), + DECL(AL_PITCH_SHIFTER_FINE_TUNE), + + DECL(AL_COMPRESSOR_ONOFF), + + DECL(AL_EQUALIZER_LOW_GAIN), + DECL(AL_EQUALIZER_LOW_CUTOFF), + DECL(AL_EQUALIZER_MID1_GAIN), + DECL(AL_EQUALIZER_MID1_CENTER), + DECL(AL_EQUALIZER_MID1_WIDTH), + DECL(AL_EQUALIZER_MID2_GAIN), + DECL(AL_EQUALIZER_MID2_CENTER), + DECL(AL_EQUALIZER_MID2_WIDTH), + DECL(AL_EQUALIZER_HIGH_GAIN), + DECL(AL_EQUALIZER_HIGH_CUTOFF), + + DECL(AL_DEDICATED_GAIN), + + DECL(AL_AUTOWAH_ATTACK_TIME), + DECL(AL_AUTOWAH_RELEASE_TIME), + DECL(AL_AUTOWAH_RESONANCE), + DECL(AL_AUTOWAH_PEAK_GAIN), + + DECL(AL_VOCAL_MORPHER_PHONEMEA), + DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING), + DECL(AL_VOCAL_MORPHER_PHONEMEB), + DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING), + DECL(AL_VOCAL_MORPHER_WAVEFORM), + DECL(AL_VOCAL_MORPHER_RATE), + + DECL(AL_EFFECTSLOT_TARGET_SOFT), + + DECL(AL_NUM_RESAMPLERS_SOFT), + DECL(AL_DEFAULT_RESAMPLER_SOFT), + DECL(AL_SOURCE_RESAMPLER_SOFT), + DECL(AL_RESAMPLER_NAME_SOFT), + + DECL(AL_SOURCE_SPATIALIZE_SOFT), + DECL(AL_AUTO_SOFT), + + DECL(AL_MAP_READ_BIT_SOFT), + DECL(AL_MAP_WRITE_BIT_SOFT), + DECL(AL_MAP_PERSISTENT_BIT_SOFT), + DECL(AL_PRESERVE_DATA_BIT_SOFT), + + DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT), + DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT), + DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT), + DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT), + DECL(AL_EVENT_TYPE_DISCONNECTED_SOFT), + + DECL(AL_DROP_UNMATCHED_SOFT), + DECL(AL_REMIX_UNMATCHED_SOFT), + + DECL(AL_AMBISONIC_LAYOUT_SOFT), + DECL(AL_AMBISONIC_SCALING_SOFT), + DECL(AL_FUMA_SOFT), + DECL(AL_ACN_SOFT), + DECL(AL_SN3D_SOFT), + DECL(AL_N3D_SOFT), + + DECL(AL_BUFFER_CALLBACK_FUNCTION_SOFT), + DECL(AL_BUFFER_CALLBACK_USER_PARAM_SOFT), + + DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT), + + DECL(AL_EFFECT_CONVOLUTION_REVERB_SOFT), + DECL(AL_EFFECTSLOT_STATE_SOFT), + + DECL(AL_FORMAT_UHJ2CHN8_SOFT), + DECL(AL_FORMAT_UHJ2CHN16_SOFT), + DECL(AL_FORMAT_UHJ2CHN_FLOAT32_SOFT), + DECL(AL_FORMAT_UHJ3CHN8_SOFT), + DECL(AL_FORMAT_UHJ3CHN16_SOFT), + DECL(AL_FORMAT_UHJ3CHN_FLOAT32_SOFT), + DECL(AL_FORMAT_UHJ4CHN8_SOFT), + DECL(AL_FORMAT_UHJ4CHN16_SOFT), + DECL(AL_FORMAT_UHJ4CHN_FLOAT32_SOFT), + DECL(AL_STEREO_MODE_SOFT), + DECL(AL_NORMAL_SOFT), + DECL(AL_SUPER_STEREO_SOFT), + DECL(AL_SUPER_STEREO_WIDTH_SOFT), + + DECL(AL_FORMAT_UHJ2CHN_MULAW_SOFT), + DECL(AL_FORMAT_UHJ2CHN_ALAW_SOFT), + DECL(AL_FORMAT_UHJ2CHN_IMA4_SOFT), + DECL(AL_FORMAT_UHJ2CHN_MSADPCM_SOFT), + DECL(AL_FORMAT_UHJ3CHN_MULAW_SOFT), + DECL(AL_FORMAT_UHJ3CHN_ALAW_SOFT), + DECL(AL_FORMAT_UHJ4CHN_MULAW_SOFT), + DECL(AL_FORMAT_UHJ4CHN_ALAW_SOFT), + + DECL(AL_DONT_CARE_EXT), + DECL(AL_DEBUG_OUTPUT_EXT), + DECL(AL_DEBUG_CALLBACK_FUNCTION_EXT), + DECL(AL_DEBUG_CALLBACK_USER_PARAM_EXT), + DECL(AL_DEBUG_SOURCE_API_EXT), + DECL(AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT), + DECL(AL_DEBUG_SOURCE_THIRD_PARTY_EXT), + DECL(AL_DEBUG_SOURCE_APPLICATION_EXT), + DECL(AL_DEBUG_SOURCE_OTHER_EXT), + DECL(AL_DEBUG_TYPE_ERROR_EXT), + DECL(AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT), + DECL(AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT), + DECL(AL_DEBUG_TYPE_PORTABILITY_EXT), + DECL(AL_DEBUG_TYPE_PERFORMANCE_EXT), + DECL(AL_DEBUG_TYPE_MARKER_EXT), + DECL(AL_DEBUG_TYPE_PUSH_GROUP_EXT), + DECL(AL_DEBUG_TYPE_POP_GROUP_EXT), + DECL(AL_DEBUG_TYPE_OTHER_EXT), + DECL(AL_DEBUG_SEVERITY_HIGH_EXT), + DECL(AL_DEBUG_SEVERITY_MEDIUM_EXT), + DECL(AL_DEBUG_SEVERITY_LOW_EXT), + DECL(AL_DEBUG_SEVERITY_NOTIFICATION_EXT), + DECL(AL_DEBUG_LOGGED_MESSAGES_EXT), + DECL(AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT), + DECL(AL_MAX_DEBUG_MESSAGE_LENGTH_EXT), + DECL(AL_MAX_DEBUG_LOGGED_MESSAGES_EXT), + DECL(AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT), + DECL(AL_STACK_OVERFLOW_EXT), + DECL(AL_STACK_UNDERFLOW_EXT), + + DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), +#ifdef ALSOFT_EAX +}, eaxEnumerations[]{ + DECL(AL_EAX_RAM_SIZE), + DECL(AL_EAX_RAM_FREE), + DECL(AL_STORAGE_AUTOMATIC), + DECL(AL_STORAGE_HARDWARE), + DECL(AL_STORAGE_ACCESSIBLE), +#endif // ALSOFT_EAX +}; +#undef DECL + +#endif /* ALC_EXPORT_LIST_H */ -- cgit v1.2.3 From cd27f8551dc593cc4fb29e1093ae45a57e6ca58e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 30 May 2023 23:02:08 -0700 Subject: Fix alc::Event declaration --- alc/events.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'alc') diff --git a/alc/events.h b/alc/events.h index 51f32e57..3b22a4c4 100644 --- a/alc/events.h +++ b/alc/events.h @@ -26,9 +26,9 @@ inline std::mutex EventMutex; inline ALCEVENTPROCTYPESOFT EventCallback{}; inline void *EventUserPtr{}; -void Event(ALCenum eventType, ALCdevice *device, std::string_view message) noexcept; +void Event(alc::EventType eventType, ALCdevice *device, std::string_view message) noexcept; -inline void Event(ALCenum eventType, std::string_view message) noexcept +inline void Event(alc::EventType eventType, std::string_view message) noexcept { Event(eventType, nullptr, message); } } // namespace alc -- cgit v1.2.3 From 3caadcf616074c6bedcd45e8af2854379f08e275 Mon Sep 17 00:00:00 2001 From: "Deal(一线灵)" Date: Wed, 31 May 2023 15:24:11 +0800 Subject: Improve wasapi backend UWP support (#853) * Improve wasapi, support uwp build * Fix compile errors * [UWP] Support ReadALConfig from app roaming * [UWP] Post disconnect event when default device changed * [UWP] Fix appveyor ci * [WIN32] Default device change notification support * Fix warnings * Add event to notify the app when the default device changes - Event type: AL_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT=0x19A7 - Event callback parameters: void _onALSoftEvent(ALenum eventType, ALuint object, // dataFlow: 0(render), 1(capture) ALuint param, // 0 ALsizei length, // 0 const ALchar* message, // Default device changed: void* userParam); * Fix warnings * Fire default device changed event in mixerProc thread * Fix compile warning * [UWP] Improve cmake * Revert changes * Notify default device change by system event callback * Revert insignificant change * Remove duplicate call --- .github/workflows/ci.yml | 10 + CMakeLists.txt | 84 ++++-- alc/alconfig.cpp | 10 +- alc/backends/wasapi.cpp | 689 +++++++++++++++++++++++++++++++++++------------ config.h.in | 3 + core/async_event.h | 1 - core/helpers.cpp | 25 +- core/uiddefs.cpp | 2 +- router/router.cpp | 4 +- 9 files changed, 620 insertions(+), 208 deletions(-) (limited to 'alc') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a94c760..5309e1f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,6 +50,16 @@ jobs: -DALSOFT_REQUIRE_WASAPI=ON", build_type: "Debug" } + - { + name: "Win64-UWP", + os: windows-latest, + cmake_opts: "-A x64 \ + -DCMAKE_SYSTEM_NAME=WindowsStore \ + \"-DCMAKE_SYSTEM_VERSION=10.0\" \ + -DALSOFT_BUILD_ROUTER=ON \ + -DALSOFT_REQUIRE_WASAPI=ON", + build_type: "Release" + } - { name: "macOS-Release", os: macos-latest, diff --git a/CMakeLists.txt b/CMakeLists.txt index 8df4be2a..02bf81b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS") FORCE) endif() endif() +elseif(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + set(ALSOFT_UWP TRUE) endif() set(CMAKE_C_VISIBILITY_PRESET hidden) @@ -148,6 +150,8 @@ set(CPP_DEFS ) # C pre-processor, not C++ set(INC_PATHS ) set(C_FLAGS ) set(LINKER_FLAGS ) +set(LINKER_FLAGS_DEBUG ) +set(LINKER_FLAGS_RELEASE ) set(EXTRA_LIBS ) if(WIN32) @@ -1010,37 +1014,39 @@ endif() # Check Windows-only backends if(WIN32) - # Check MMSystem backend - option(ALSOFT_BACKEND_WINMM "Enable Windows Multimedia backend" ON) - option(ALSOFT_REQUIRE_WINMM "Require Windows Multimedia backend" OFF) - if(ALSOFT_BACKEND_WINMM) - set(HAVE_WINMM 1) - set(BACKENDS "${BACKENDS} WinMM,") - set(ALC_OBJS ${ALC_OBJS} alc/backends/winmm.cpp alc/backends/winmm.h) - # There doesn't seem to be good way to search for winmm.lib for MSVC. - # find_library doesn't find it without being told to look in a specific - # place in the WindowsSDK, but it links anyway. If there ends up being - # Windows targets without this, another means to detect it is needed. - set(EXTRA_LIBS winmm ${EXTRA_LIBS}) - endif() - - # Check DSound backend - option(ALSOFT_BACKEND_DSOUND "Enable DirectSound backend" ON) - option(ALSOFT_REQUIRE_DSOUND "Require DirectSound backend" OFF) - if(ALSOFT_BACKEND_DSOUND) - check_include_file(dsound.h HAVE_DSOUND_H) - if(DXSDK_DIR) - find_path(DSOUND_INCLUDE_DIR NAMES "dsound.h" - PATHS "${DXSDK_DIR}" PATH_SUFFIXES include - DOC "The DirectSound include directory") + if (NOT ALSOFT_UWP) + # Check MMSystem backend + option(ALSOFT_BACKEND_WINMM "Enable Windows Multimedia backend" ON) + option(ALSOFT_REQUIRE_WINMM "Require Windows Multimedia backend" OFF) + if(ALSOFT_BACKEND_WINMM) + set(HAVE_WINMM 1) + set(BACKENDS "${BACKENDS} WinMM,") + set(ALC_OBJS ${ALC_OBJS} alc/backends/winmm.cpp alc/backends/winmm.h) + # There doesn't seem to be good way to search for winmm.lib for MSVC. + # find_library doesn't find it without being told to look in a specific + # place in the WindowsSDK, but it links anyway. If there ends up being + # Windows targets without this, another means to detect it is needed. + set(EXTRA_LIBS winmm ${EXTRA_LIBS}) endif() - if(HAVE_DSOUND_H OR DSOUND_INCLUDE_DIR) - set(HAVE_DSOUND 1) - set(BACKENDS "${BACKENDS} DirectSound,") - set(ALC_OBJS ${ALC_OBJS} alc/backends/dsound.cpp alc/backends/dsound.h) - if(NOT HAVE_DSOUND_H) - set(INC_PATHS ${INC_PATHS} ${DSOUND_INCLUDE_DIR}) + # Check DSound backend + option(ALSOFT_BACKEND_DSOUND "Enable DirectSound backend" ON) + option(ALSOFT_REQUIRE_DSOUND "Require DirectSound backend" OFF) + if(ALSOFT_BACKEND_DSOUND) + check_include_file(dsound.h HAVE_DSOUND_H) + if(DXSDK_DIR) + find_path(DSOUND_INCLUDE_DIR NAMES "dsound.h" + PATHS "${DXSDK_DIR}" PATH_SUFFIXES include + DOC "The DirectSound include directory") + endif() + if(HAVE_DSOUND_H OR DSOUND_INCLUDE_DIR) + set(HAVE_DSOUND 1) + set(BACKENDS "${BACKENDS} DirectSound,") + set(ALC_OBJS ${ALC_OBJS} alc/backends/dsound.cpp alc/backends/dsound.h) + + if(NOT HAVE_DSOUND_H) + set(INC_PATHS ${INC_PATHS} ${DSOUND_INCLUDE_DIR}) + endif() endif() endif() endif() @@ -1054,8 +1060,19 @@ if(WIN32) set(HAVE_WASAPI 1) set(BACKENDS "${BACKENDS} WASAPI,") set(ALC_OBJS ${ALC_OBJS} alc/backends/wasapi.cpp alc/backends/wasapi.h) + if(ALSOFT_UWP) + set_source_files_properties(alc/backends/wasapi.cpp alc/alconfig.cpp PROPERTIES COMPILE_FLAGS /ZW) + endif() endif() endif() + + # Setup properly link flags for UWP + if(ALSOFT_UWP AND HAVE_WASAPI) + # Add compile and link flags required C++/CX + set(C_FLAGS "/Zc:twoPhase-" ${C_FLAGS}) + set(LINKER_FLAGS_DEBUG "/nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib ${LINKER_FLAGS_DEBUG}") + set(LINKER_FLAGS_RELEASE "/nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib ${LINKER_FLAGS_RELEASE}") + endif() endif() if(ALSOFT_REQUIRE_WINMM AND NOT HAVE_WINMM) message(FATAL_ERROR "Failed to enabled required WinMM backend") @@ -1399,6 +1416,15 @@ else() endif() target_link_libraries(${IMPL_TARGET} PRIVATE common ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB}) + if (WIN32) + set_target_properties(${IMPL_TARGET} PROPERTIES + LINK_FLAGS_DEBUG "${LINKER_FLAGS_DEBUG}" + LINK_FLAGS_RELEASE "${LINKER_FLAGS_RELEASE}" + LINK_FLAGS_MINSIZEREL "${LINKER_FLAGS_RELEASE}" + LINK_FLAGS_RELWITHDEBINFO "${LINKER_FLAGS_RELEASE}" + ) + endif() + if(NOT WIN32 AND NOT APPLE) # FIXME: This doesn't put a dependency on the version script. Changing # the version script will not cause a relink as it should. diff --git a/alc/alconfig.cpp b/alc/alconfig.cpp index 56cad9e0..3c9a9777 100644 --- a/alc/alconfig.cpp +++ b/alc/alconfig.cpp @@ -329,9 +329,14 @@ const char *GetConfigValue(const char *devName, const char *blockName, const cha #ifdef _WIN32 void ReadALConfig() { - WCHAR buffer[MAX_PATH]; - if(SHGetSpecialFolderPathW(nullptr, buffer, CSIDL_APPDATA, FALSE) != FALSE) { +#if !defined(ALSOFT_UWP) + WCHAR buffer[MAX_PATH]; + if (!SHGetSpecialFolderPathW(nullptr, buffer, CSIDL_APPDATA, FALSE)) + return; +#else + auto buffer = Windows::Storage::ApplicationData::Current->RoamingFolder->Path->Data(); +#endif std::string filepath{wstr_to_utf8(buffer)}; filepath += "\\alsoft.ini"; @@ -341,6 +346,7 @@ void ReadALConfig() LoadConfigFromFile(f); } + std::string ppath{GetProcBinary().path}; if(!ppath.empty()) { diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index d4ad38e2..c8c03e8a 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -58,6 +58,7 @@ #include "albit.h" #include "alc/alconfig.h" +#include "alc/events.h" #include "alnumeric.h" #include "alspan.h" #include "comptr.h" @@ -69,6 +70,14 @@ #include "strutils.h" #include "threads.h" +#if defined(ALSOFT_UWP) +#include +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Media::Devices; +using namespace Windows::Devices::Enumeration; +using namespace Windows::Media::Devices; +#endif /* Some headers seem to define these as macros for __uuidof, which is annoying * since some headers don't declare them at all. Hopefully the ifdef is enough @@ -80,11 +89,11 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x #ifndef KSDATAFORMAT_SUBTYPE_IEEE_FLOAT DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); #endif - +#if !defined(ALSOFT_UWP) DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14); DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x8c,0x23, 0xe0,0xc0,0xff,0xee,0x7f,0x0e, 0); DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23,0xe0, 0xc0,0xff,0xee,0x7f,0x0e, 4 ); - +#endif namespace { @@ -190,159 +199,504 @@ bool checkName(const al::span list, const std::string &name) std::vector PlaybackDevices; std::vector CaptureDevices; - -using NameGUIDPair = std::pair; -NameGUIDPair get_device_name_and_guid(IMMDevice *device) +#if defined(ALSOFT_UWP) +enum EDataFlow { - static constexpr char UnknownName[]{"Unknown Device Name"}; - static constexpr char UnknownGuid[]{"Unknown Device GUID"}; - std::string name, guid; + eRender = 0, + eCapture = (eRender + 1), + eAll = (eCapture + 1), + EDataFlow_enum_count = (eAll + 1) +}; +#endif - ComPtr ps; - HRESULT hr = device->OpenPropertyStore(STGM_READ, al::out_ptr(ps)); - if(FAILED(hr)) +#if defined(ALSOFT_UWP) +struct DeviceHandle +{ + DeviceHandle& operator=(std::nullptr_t) { - WARN("OpenPropertyStore failed: 0x%08lx\n", hr); - return std::make_pair(UnknownName, UnknownGuid); + value = nullptr; + return *this; } + DeviceInformation^ value{nullptr}; +}; +using EventRegistrationToken = Windows::Foundation::EventRegistrationToken; +#else +using DeviceHandle = ComPtr; +using EventRegistrationToken = void*; +#endif - PropVariant pvprop; - hr = ps->GetValue(al::bit_cast(DEVPKEY_Device_FriendlyName), pvprop.get()); - if(FAILED(hr)) - { - WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); - name += UnknownName; +#if defined(ALSOFT_UWP) +struct DeviceHelper final : public IActivateAudioInterfaceCompletionHandler +#else +struct DeviceHelper final : public IMMNotificationClient +#endif +{ +public: + DeviceHelper() + { +#if defined(ALSOFT_UWP) + mActiveClientEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr); +#else + HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, + al::out_ptr(mEnumerator)); + if (SUCCEEDED(hr)) + mEnumerator->RegisterEndpointNotificationCallback(this); + else + WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); +#endif } - else if(pvprop->vt == VT_LPWSTR) - name += wstr_to_utf8(pvprop->pwszVal); - else + ~DeviceHelper() { - WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvprop->vt); - name += UnknownName; +#if defined(ALSOFT_UWP) + if (mActiveClientEvent != nullptr) + CloseHandle(mActiveClientEvent); + mActiveClientEvent = nullptr; +#else + if (mEnumerator) + mEnumerator->UnregisterEndpointNotificationCallback(this); + mEnumerator = nullptr; +#endif } - pvprop.clear(); - hr = ps->GetValue(al::bit_cast(PKEY_AudioEndpoint_GUID), pvprop.get()); - if(FAILED(hr)) + /** -------------------------- IUnkonwn ----------------------------- */ + LONG mRefCount{1}; + ULONG STDMETHODCALLTYPE AddRef() override { return InterlockedIncrement(&mRefCount); } + + ULONG STDMETHODCALLTYPE Release() override { - WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); - guid = UnknownGuid; + ULONG ulRef = InterlockedDecrement(&mRefCount); + if (0 == ulRef) + { + delete this; + } + return ulRef; } - else if(pvprop->vt == VT_LPWSTR) - guid = wstr_to_utf8(pvprop->pwszVal); - else + + HRESULT STDMETHODCALLTYPE QueryInterface(const IID& IId, void** UnknownPtrPtr) override { - WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvprop->vt); - guid = UnknownGuid; - } + // Three rules of QueryInterface: + // https://docs.microsoft.com/en-us/windows/win32/com/rules-for-implementing-queryinterface + // 1. Objects must have identity. + // 2. The set of interfaces on an object instance must be static. + // 3. It must be possible to query successfully for any interface on an object from any other interface. - return std::make_pair(std::move(name), std::move(guid)); -} + // If ppvObject(the address) is nullptr, then this method returns E_POINTER. + if (!UnknownPtrPtr) + { + return E_POINTER; + } -EndpointFormFactor get_device_formfactor(IMMDevice *device) -{ - ComPtr ps; - HRESULT hr{device->OpenPropertyStore(STGM_READ, al::out_ptr(ps))}; - if(FAILED(hr)) - { - WARN("OpenPropertyStore failed: 0x%08lx\n", hr); - return UnknownFormFactor; + // https://docs.microsoft.com/en-us/windows/win32/com/implementing-reference-counting + // Whenever a client calls a method(or API function), such as QueryInterface, that returns a new interface + // pointer, the method being called is responsible for incrementing the reference count through the returned + // pointer. For example, when a client first creates an object, it receives an interface pointer to an object + // that, from the client's point of view, has a reference count of one. If the client then calls AddRef on the + // interface pointer, the reference count becomes two. The client must call Release twice on the interface + // pointer to drop all of its references to the object. +#if defined(ALSOFT_UWP) + if (IId == __uuidof(IActivateAudioInterfaceCompletionHandler)) + { + *UnknownPtrPtr = (IActivateAudioInterfaceCompletionHandler*)(this); + AddRef(); + return S_OK; + } +#else + if (IId == __uuidof(IMMNotificationClient)) + { + *UnknownPtrPtr = (IMMNotificationClient*)(this); + AddRef(); + return S_OK; + } +#endif + else if (IId == __uuidof(IAgileObject) || IId == __uuidof(IUnknown)) + { + *UnknownPtrPtr = (IUnknown*)(this); + AddRef(); + return S_OK; + } + + // This method returns S_OK if the interface is supported, and E_NOINTERFACE otherwise. + *UnknownPtrPtr = nullptr; + return E_NOINTERFACE; } - EndpointFormFactor formfactor{UnknownFormFactor}; - PropVariant pvform; - hr = ps->GetValue(PKEY_AudioEndpoint_FormFactor, pvform.get()); - if(FAILED(hr)) - WARN("GetValue AudioEndpoint_FormFactor failed: 0x%08lx\n", hr); - else if(pvform->vt == VT_UI4) - formfactor = static_cast(pvform->ulVal); - else if(pvform->vt != VT_EMPTY) - WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform->vt); - return formfactor; -} +#if defined(ALSOFT_UWP) + /** ----------------------- IActivateAudioInterfaceCompletionHandler ------------ */ + HRESULT ActivateCompleted(IActivateAudioInterfaceAsyncOperation* operation) override + { + HRESULT hrActivateResult = S_OK; + IUnknown* punkAudioInterface = nullptr; + HRESULT hr = operation->GetActivateResult(&hrActivateResult, &punkAudioInterface); + // Check for a successful activation result + if (SUCCEEDED(hr) && SUCCEEDED(hrActivateResult)) + { + if (mPPV) + { + // Get the pointer for the Audio Client + IAudioClient3* audioClient; + punkAudioInterface->QueryInterface(IID_PPV_ARGS(&audioClient)); + *mPPV = audioClient; + } + } -void add_device(IMMDevice *device, const WCHAR *devid, std::vector &list) -{ - for(auto &entry : list) + SetEvent(mActiveClientEvent); + + // Need to return S_OK + return S_OK; + } +#else + /** ----------------------- IMMNotificationClient ------------ */ + STDMETHOD(OnDeviceStateChanged(LPCWSTR /*pwstrDeviceId*/, DWORD /*dwNewState*/)) override { return S_OK; } + STDMETHOD(OnDeviceAdded(LPCWSTR /*pwstrDeviceId*/)) override { return S_OK; } + STDMETHOD(OnDeviceRemoved(LPCWSTR /*pwstrDeviceId*/)) override { return S_OK; } + STDMETHOD(OnPropertyValueChanged(LPCWSTR /*pwstrDeviceId*/, const PROPERTYKEY /*key*/)) override { return S_OK; } + STDMETHOD(OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId)) override { - if(entry.devid == devid) - return; + if (role == eMultimedia && (flow == eRender || flow == eCapture)) + { + std::lock_guard lck(mDefaultChangeHandlersMtx); + for (auto& handlerItem : mDefaultChangeHandlers) + { + if (handlerItem.second.first == flow) + handlerItem.second.second(pwstrDefaultDeviceId); + } + } + return S_OK; } +#endif - auto name_guid = get_device_name_and_guid(device); + /** -------------------------- DeviceHelper ----------------------------- */ + HRESULT OpenDevice(LPCWSTR devid, EDataFlow flow, DeviceHandle& device) + { +#if !defined(ALSOFT_UWP) + HRESULT hr = E_POINTER; + if (mEnumerator) + { + if (!devid) + hr = mEnumerator->GetDefaultAudioEndpoint(flow, eMultimedia, al::out_ptr(device)); + else + hr = mEnumerator->GetDevice(devid, al::out_ptr(device)); + } + if (FAILED(hr)) + { + return hr; + } +#else + const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; + Platform::String^ devIfPath = + !devid ? (flow == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole)) + : ref new Platform::String(devid); + + Concurrency::task createDeviceOp( + DeviceInformation::CreateFromIdAsync(devIfPath, nullptr, DeviceInformationKind::DeviceInterface)); + auto status = createDeviceOp.then([&](DeviceInformation^ deviceInfo) { + device.value = deviceInfo; + }).wait(); + if (status != Concurrency::task_status::completed) + { + return E_NOINTERFACE; + } +#endif + return S_OK; + } - int count{1}; - std::string newname{name_guid.first}; - while(checkName(list, newname)) + HRESULT ActivateAudioClient(_In_ DeviceHandle& device, + void** ppv) { - newname = name_guid.first; - newname += " #"; - newname += std::to_string(++count); +#if !defined(ALSOFT_UWP) + HRESULT hr{device->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER, nullptr, ppv)}; +#else + HRESULT hr{ActivateAudioInterface(device.value->Id->Data(), + __uuidof(IAudioClient3), nullptr, ppv)}; +#endif + return hr; } - list.emplace_back(std::move(newname), std::move(name_guid.second), devid); - const DevMap &newentry = list.back(); - TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", newentry.name.c_str(), - newentry.endpoint_guid.c_str(), newentry.devid.c_str()); -} + HRESULT probe_devices(EDataFlow flowdir, std::vector& list) + { + std::vector{}.swap(list); -WCHAR *get_device_id(IMMDevice *device) -{ - WCHAR *devid; +#if !defined(ALSOFT_UWP) + ComPtr coll; + HRESULT hr{mEnumerator->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, al::out_ptr(coll))}; + if (FAILED(hr)) + { + ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); + return hr; + } - const HRESULT hr{device->GetId(&devid)}; - if(FAILED(hr)) - { - ERR("Failed to get device id: %lx\n", hr); - return nullptr; - } + UINT count{0}; + hr = coll->GetCount(&count); + if (SUCCEEDED(hr) && count > 0) + list.reserve(count); - return devid; -} + ComPtr device; + hr = mEnumerator->GetDefaultAudioEndpoint(flowdir, eMultimedia, al::out_ptr(device)); + if (SUCCEEDED(hr)) + { + if (WCHAR * devid{get_device_id(device.get())}) + { + add_device(device, devid, list); + CoTaskMemFree(devid); + } + device = nullptr; + } -void probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, std::vector &list) -{ - std::vector{}.swap(list); + for (UINT i{0}; i < count; ++i) + { + hr = coll->Item(i, al::out_ptr(device)); + if (FAILED(hr)) + continue; - ComPtr coll; - HRESULT hr{devenum->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, al::out_ptr(coll))}; - if(FAILED(hr)) - { - ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); - return; + if (WCHAR * devid{get_device_id(device.get())}) + { + add_device(device, devid, list); + CoTaskMemFree(devid); + } + device = nullptr; + } + + return S_OK; +#else + const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; + auto DefaultAudioId = flowdir == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) + : MediaDevice::GetDefaultAudioCaptureId(deviceRole); + Concurrency::task createDefaultOp(DeviceInformation::CreateFromIdAsync(DefaultAudioId, nullptr, DeviceInformationKind::DeviceInterface)); + auto task_status = createDefaultOp + .then([this, &list](DeviceInformation ^ deviceInfo) { + if (deviceInfo) + add_device(DeviceHandle{deviceInfo}, deviceInfo->Id->Data(), list); + }).wait(); + if (task_status != Concurrency::task_group_status::completed) + return E_FAIL; + + // Get the string identifier of the audio renderer + auto AudioSelector = flowdir == eRender ? MediaDevice::GetAudioRenderSelector() : MediaDevice::GetAudioCaptureSelector(); + + // Setup the asynchronous callback + Concurrency::task enumOperation( + DeviceInformation::FindAllAsync(AudioSelector, /*PropertyList*/nullptr, DeviceInformationKind::DeviceInterface)); + task_status = enumOperation + .then([this, &list](DeviceInformationCollection ^ DeviceInfoCollection) { + if (DeviceInfoCollection) + { + try + { + auto deviceCount = DeviceInfoCollection->Size; + for (unsigned int i = 0; i < deviceCount; ++i) + { + DeviceInformation ^ deviceInfo = DeviceInfoCollection->GetAt(i); + if (deviceInfo) + add_device(DeviceHandle{deviceInfo}, deviceInfo->Id->Data(), list); + } + } + catch (Platform::Exception ^ e) + { + } + } + }).wait(); + + return task_status == Concurrency::task_group_status::completed ? S_OK : E_FAIL; +#endif } - UINT count{0}; - hr = coll->GetCount(&count); - if(SUCCEEDED(hr) && count > 0) - list.reserve(count); + using NameGUIDPair = std::pair; + static NameGUIDPair get_device_name_and_guid(const DeviceHandle& device) + { +#if !defined(ALSOFT_UWP) + static constexpr char UnknownName[]{"Unknown Device Name"}; + static constexpr char UnknownGuid[]{"Unknown Device GUID"}; + std::string name, guid; - ComPtr device; - hr = devenum->GetDefaultAudioEndpoint(flowdir, eMultimedia, al::out_ptr(device)); - if(SUCCEEDED(hr)) + ComPtr ps; + HRESULT hr = device->OpenPropertyStore(STGM_READ, al::out_ptr(ps)); + if (FAILED(hr)) + { + WARN("OpenPropertyStore failed: 0x%08lx\n", hr); + return std::make_pair(UnknownName, UnknownGuid); + } + + PropVariant pvprop; + hr = ps->GetValue(al::bit_cast(DEVPKEY_Device_FriendlyName), pvprop.get()); + if (FAILED(hr)) + { + WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); + name += UnknownName; + } + else if (pvprop->vt == VT_LPWSTR) + name += wstr_to_utf8(pvprop->pwszVal); + else + { + WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvprop->vt); + name += UnknownName; + } + + pvprop.clear(); + hr = ps->GetValue(al::bit_cast(PKEY_AudioEndpoint_GUID), pvprop.get()); + if (FAILED(hr)) + { + WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); + guid = UnknownGuid; + } + else if (pvprop->vt == VT_LPWSTR) + guid = wstr_to_utf8(pvprop->pwszVal); + else + { + WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvprop->vt); + guid = UnknownGuid; + } + +#else + auto devInfo = device.value; + std::string name = wstr_to_utf8(devInfo->Name->Data()); + std::string guid; + // devInfo->Id is DeviceInterfacePath: \\?\SWD#MMDEVAPI#{0.0.0.00000000}.{a21c17a0-fc1d-405e-ab5a-b513422b57d1}#{e6327cad-dcec-4949-ae8a-991e976a79d2} + Platform::String ^ devIfPath = devInfo->Id; + auto wcsDevIfPath = devIfPath->Data(); + auto devIdStart = wcsstr(wcsDevIfPath, L"}."); + if (devIdStart) + { + devIdStart += 2; // L"}." + auto devIdStartEnd = wcschr(devIdStart, L'#'); + if (devIdStartEnd) + { + std::wstring wDevId{devIdStart, static_cast(devIdStartEnd - devIdStart)}; + guid = wstr_to_utf8(wDevId.c_str()); + std::transform(guid.begin(), guid.end(), guid.begin(), [](char ch) { return static_cast(std::toupper(ch)); }); + } + } +#endif + return std::make_pair(std::move(name), std::move(guid)); + } + + static void add_device(const DeviceHandle& device, const WCHAR* devid, std::vector& list) { - if(WCHAR *devid{get_device_id(device.get())}) + for (auto& entry : list) { - add_device(device.get(), devid, list); - CoTaskMemFree(devid); + if (entry.devid == devid) + return; } + + auto name_guid = get_device_name_and_guid(device); + int count{1}; + std::string newname{name_guid.first}; + while (checkName(list, newname)) + { + newname = name_guid.first; + newname += " #"; + newname += std::to_string(++count); + } + list.emplace_back(std::move(newname), std::move(name_guid.second), devid); + const DevMap& newentry = list.back(); + + TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", newentry.name.c_str(), newentry.endpoint_guid.c_str(), + newentry.devid.c_str()); } - for(UINT i{0};i < count;++i) +#if !defined(ALSOFT_UWP) + static WCHAR* get_device_id(IMMDevice* device) { - device = nullptr; - hr = coll->Item(i, al::out_ptr(device)); - if(FAILED(hr)) continue; + WCHAR* devid; - if(WCHAR *devid{get_device_id(device.get())}) + const HRESULT hr{device->GetId(&devid)}; + if (FAILED(hr)) { - add_device(device.get(), devid, list); - CoTaskMemFree(devid); + ERR("Failed to get device id: %lx\n", hr); + return nullptr; } + + return devid; } -} + static EndpointFormFactor get_device_formfactor(IMMDevice* device) + { + ComPtr ps; + HRESULT hr{device->OpenPropertyStore(STGM_READ, al::out_ptr(ps))}; + if (FAILED(hr)) + { + WARN("OpenPropertyStore failed: 0x%08lx\n", hr); + return UnknownFormFactor; + } + + EndpointFormFactor formfactor{UnknownFormFactor}; + PropVariant pvform; + hr = ps->GetValue(PKEY_AudioEndpoint_FormFactor, pvform.get()); + if (FAILED(hr)) + WARN("GetValue AudioEndpoint_FormFactor failed: 0x%08lx\n", hr); + else if (pvform->vt == VT_UI4) + formfactor = static_cast(pvform->ulVal); + else if (pvform->vt != VT_EMPTY) + WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform->vt); + return formfactor; + } +#endif + + template + EventRegistrationToken RegisterDefaultChangeHandler(EDataFlow flow, void* target, _Fty&& cb) + { +#if defined(ALSOFT_UWP) + (void)target; + if (flow == eRender) + return MediaDevice::DefaultAudioRenderDeviceChanged += + ref new TypedEventHandler( + [this, cb](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { + if (args->Role == AudioDeviceRole::Default) + cb(args->Id->Data()); + }); + else + return MediaDevice::DefaultAudioCaptureDeviceChanged += + ref new TypedEventHandler( + [this, cb](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { + if (args->Role == AudioDeviceRole::Default) + cb(args->Id->Data()); + }); +#else + std::lock_guard lck(mDefaultChangeHandlersMtx); + if (mDefaultChangeHandlers.emplace(target, std::make_pair(flow, cb)).second) + return target; + return nullptr; +#endif + } + + void UnregisterDefaultChangeHandler(EventRegistrationToken handler) + { +#if defined(ALSOFT_UWP) + MediaDevice::DefaultAudioRenderDeviceChanged -= handler; +#else + std::lock_guard lck(mDefaultChangeHandlersMtx); + mDefaultChangeHandlers.erase(handler); +#endif + } +private: +#if defined(ALSOFT_UWP) + HRESULT ActivateAudioInterface(_In_ LPCWSTR deviceInterfacePath, + _In_ REFIID riid, + _In_opt_ PROPVARIANT* activationParams, + void** ppv) + { + IActivateAudioInterfaceAsyncOperation* asyncOp{nullptr}; + mPPV = ppv; + HRESULT hr = ActivateAudioInterfaceAsync(deviceInterfacePath, riid, activationParams, this, &asyncOp); + if (FAILED(hr)) + return hr; + if (asyncOp) + asyncOp->Release(); + + DWORD res{WaitForSingleObjectEx(mActiveClientEvent, 2000, FALSE)}; + if (res != WAIT_OBJECT_0) + ERR("WaitForSingleObjectEx error: 0x%lx\n", res); + return res; + } + + HANDLE mActiveClientEvent{nullptr}; + void** mPPV{nullptr}; +#else + ComPtr mEnumerator{nullptr}; + std::mutex mDefaultChangeHandlersMtx; + std::unordered_map>> mDefaultChangeHandlers; +#endif +}; bool MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX *in) { @@ -473,6 +827,8 @@ struct WasapiProxy { static std::mutex sThreadLock; static size_t sInitCount; + static ComPtr sDeviceHelper; + std::future pushMessage(MsgType type, const char *param=nullptr) { std::promise promise; @@ -544,6 +900,7 @@ std::deque WasapiProxy::mMsgQueue; std::mutex WasapiProxy::mMsgQueueLock; std::condition_variable WasapiProxy::mMsgQueueCond; std::mutex WasapiProxy::sThreadLock; +ComPtr WasapiProxy::sDeviceHelper; size_t WasapiProxy::sInitCount{0}; int WasapiProxy::messageHandler(std::promise *promise) @@ -560,6 +917,8 @@ int WasapiProxy::messageHandler(std::promise *promise) promise->set_value(S_OK); promise = nullptr; + sDeviceHelper.reset(new DeviceHelper()); + TRACE("Starting message loop\n"); while(Msg msg{popMessage()}) { @@ -597,19 +956,12 @@ int WasapiProxy::messageHandler(std::promise *promise) case MsgType::EnumeratePlayback: case MsgType::EnumerateCapture: { - ComPtr devenum; - hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, al::out_ptr(devenum)); - if(FAILED(hr)) - msg.mPromise.set_value(hr); - else - { - if(msg.mType == MsgType::EnumeratePlayback) - probe_devices(devenum.get(), eRender, PlaybackDevices); - else if(msg.mType == MsgType::EnumerateCapture) - probe_devices(devenum.get(), eCapture, CaptureDevices); - msg.mPromise.set_value(S_OK); - } + if (msg.mType == MsgType::EnumeratePlayback) + msg.mPromise.set_value(sDeviceHelper->probe_devices(eRender, PlaybackDevices)); + else if (msg.mType == MsgType::EnumerateCapture) + msg.mPromise.set_value(sDeviceHelper->probe_devices(eCapture, CaptureDevices)); + else + msg.mPromise.set_value(E_FAIL); continue; } @@ -625,7 +977,6 @@ int WasapiProxy::messageHandler(std::promise *promise) return 0; } - struct WasapiPlayback final : public BackendBase, WasapiProxy { WasapiPlayback(DeviceBase *device) noexcept : BackendBase{device} { } ~WasapiPlayback() override; @@ -646,7 +997,7 @@ struct WasapiPlayback final : public BackendBase, WasapiProxy { ClockLatency getClockLatency() override; HRESULT mOpenStatus{E_FAIL}; - ComPtr mMMDev{nullptr}; + DeviceHandle mMMDev{nullptr}; ComPtr mClient{nullptr}; ComPtr mRender{nullptr}; HANDLE mNotifyEvent{nullptr}; @@ -664,6 +1015,9 @@ struct WasapiPlayback final : public BackendBase, WasapiProxy { std::atomic mKillNow{true}; std::thread mThread; + std::string mDefaultDeviceId; + EventRegistrationToken mDefaultChangeHandler{}; + DEF_NEWDEL(WasapiPlayback) }; @@ -838,33 +1192,29 @@ HRESULT WasapiPlayback::openProxy(const char *name) devid = iter->devid.c_str(); } - ComPtr enumerator; - ComPtr mmdev; - HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, al::out_ptr(enumerator))}; - if(SUCCEEDED(hr)) - { - if(!devid) - hr = enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, al::out_ptr(mmdev)); - else - hr = enumerator->GetDevice(devid, al::out_ptr(mmdev)); - } - if(FAILED(hr)) + HRESULT hr{sDeviceHelper->OpenDevice(devid, eRender, mMMDev)}; + if (FAILED(hr)) { - WARN("Failed to open device \"%s\"\n", name?name:"(default)"); + WARN("Failed to open device \"%s\"\n", name ? name : "(default)"); return hr; } - mClient = nullptr; - mMMDev = std::move(mmdev); - if(name) mDevice->DeviceName = std::string{DevNameHead} + name; - else mDevice->DeviceName = DevNameHead + get_device_name_and_guid(mMMDev.get()).first; + if (name) + mDevice->DeviceName = std::string{DevNameHead} + name; + else + mDevice->DeviceName = DevNameHead + DeviceHelper::get_device_name_and_guid(mMMDev).first; - return hr; + mDefaultChangeHandler = sDeviceHelper->RegisterDefaultChangeHandler(eRender, this, [this](LPCWSTR devid) { + mDefaultDeviceId = wstr_to_utf8(devid); + alc::Event(alc::EventType::DefaultDeviceChanged, (ALCdevice*)mDevice, mDefaultDeviceId); + }); + + return S_OK; } void WasapiPlayback::closeProxy() { + sDeviceHelper->UnregisterDefaultChangeHandler(mDefaultChangeHandler); mClient = nullptr; mMMDev = nullptr; } @@ -881,9 +1231,7 @@ bool WasapiPlayback::reset() HRESULT WasapiPlayback::resetProxy() { mClient = nullptr; - - HRESULT hr{mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, - al::out_ptr(mClient))}; + HRESULT hr{sDeviceHelper->ActivateAudioClient(mMMDev, al::out_ptr(mClient))}; if(FAILED(hr)) { ERR("Failed to reactivate audio client: 0x%08lx\n", hr); @@ -1154,9 +1502,12 @@ HRESULT WasapiPlayback::resetProxy() } mFormat = OutputType; - const EndpointFormFactor formfactor{get_device_formfactor(mMMDev.get())}; +#if !defined(ALSOFT_UWP) + const EndpointFormFactor formfactor{DeviceHelper::get_device_formfactor(mMMDev.get())}; mDevice->Flags.set(DirectEar, (formfactor == Headphones || formfactor == Headset)); - +#else + mDevice->Flags.set(DirectEar, false); +#endif setDefaultWFXChannelOrder(); hr = mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, @@ -1313,7 +1664,7 @@ struct WasapiCapture final : public BackendBase, WasapiProxy { uint availableSamples() override; HRESULT mOpenStatus{E_FAIL}; - ComPtr mMMDev{nullptr}; + DeviceHandle mMMDev{nullptr}; ComPtr mClient{nullptr}; ComPtr mCapture{nullptr}; HANDLE mNotifyEvent{nullptr}; @@ -1325,6 +1676,9 @@ struct WasapiCapture final : public BackendBase, WasapiProxy { std::atomic mKillNow{true}; std::thread mThread; + std::string mDefaultDeviceId; + EventRegistrationToken mDefaultChangeHandler{}; + DEF_NEWDEL(WasapiCapture) }; @@ -1509,31 +1863,28 @@ HRESULT WasapiCapture::openProxy(const char *name) devid = iter->devid.c_str(); } - ComPtr enumerator; - HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, al::out_ptr(enumerator))}; - if(SUCCEEDED(hr)) - { - if(!devid) - hr = enumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, al::out_ptr(mMMDev)); - else - hr = enumerator->GetDevice(devid, al::out_ptr(mMMDev)); - } - if(FAILED(hr)) + HRESULT hr{sDeviceHelper->OpenDevice(devid, eCapture, mMMDev)}; + if (FAILED(hr)) { - WARN("Failed to open device \"%s\"\n", name?name:"(default)"); + WARN("Failed to open device \"%s\"\n", name ? name : "(default)"); return hr; } - mClient = nullptr; - if(name) mDevice->DeviceName = std::string{DevNameHead} + name; - else mDevice->DeviceName = DevNameHead + get_device_name_and_guid(mMMDev.get()).first; + if (name) + mDevice->DeviceName = std::string{ DevNameHead } + name; + else + mDevice->DeviceName = DevNameHead + DeviceHelper::get_device_name_and_guid(mMMDev).first; - return hr; + mDefaultChangeHandler = sDeviceHelper->RegisterDefaultChangeHandler(eCapture, this, [this](LPCWSTR devid) { + mDefaultDeviceId = wstr_to_utf8(devid); + alc::Event(alc::EventType::DefaultDeviceChanged, (ALCdevice*)mDevice, mDefaultDeviceId); + }); + return S_OK; } void WasapiCapture::closeProxy() { + sDeviceHelper->UnregisterDefaultChangeHandler(mDefaultChangeHandler); mClient = nullptr; mMMDev = nullptr; } @@ -1542,8 +1893,7 @@ HRESULT WasapiCapture::resetProxy() { mClient = nullptr; - HRESULT hr{mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, - al::out_ptr(mClient))}; + HRESULT hr{sDeviceHelper->ActivateAudioClient(mMMDev, al::out_ptr(mClient))}; if(FAILED(hr)) { ERR("Failed to reactivate audio client: 0x%08lx\n", hr); @@ -1904,13 +2254,14 @@ bool WasapiBackendFactory::init() WARN("Failed to initialize COM: 0x%08lx\n", hr); return hr; } - +#if !defined(ALSOFT_UWP) ComPtr enumerator; hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, al::out_ptr(enumerator)); if(FAILED(hr)) WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); enumerator = nullptr; +#endif CoUninitialize(); return hr; diff --git a/config.h.in b/config.h.in index 477d8c77..d1cf0395 100644 --- a/config.h.in +++ b/config.h.in @@ -117,3 +117,6 @@ /* Define the installation data directory */ #cmakedefine ALSOFT_INSTALL_DATADIR "@ALSOFT_INSTALL_DATADIR@" + +/* Define whether build alsoft for winuwp */ +#cmakedefine ALSOFT_UWP diff --git a/core/async_event.h b/core/async_event.h index c049fa02..f1ca0c7b 100644 --- a/core/async_event.h +++ b/core/async_event.h @@ -15,7 +15,6 @@ enum class AsyncEnableBits : uint8_t { SourceState, BufferCompleted, Disconnected, - Count }; diff --git a/core/helpers.cpp b/core/helpers.cpp index 58cc74e5..f9de25cf 100644 --- a/core/helpers.cpp +++ b/core/helpers.cpp @@ -3,6 +3,11 @@ #include "helpers.h" +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +#endif + #include #include #include @@ -40,7 +45,7 @@ const PathNamePair &GetProcBinary() { static std::optional procbin; if(procbin) return *procbin; - +#if !defined(ALSOFT_UWP) auto fullpath = std::vector(256); DWORD len{GetModuleFileNameW(nullptr, fullpath.data(), static_cast(fullpath.size()))}; while(len == fullpath.size()) @@ -58,7 +63,16 @@ const PathNamePair &GetProcBinary() fullpath.resize(len); if(fullpath.back() != 0) fullpath.push_back(0); - +#else + auto exePath = __wargv[0]; + if (!exePath) + { + ERR("Failed to get process name: error %lu\n", GetLastError()); + procbin.emplace(); + return *procbin; + } + std::vector fullpath{exePath, exePath + wcslen(exePath) + 1}; +#endif std::replace(fullpath.begin(), fullpath.end(), '/', '\\'); auto sep = std::find(fullpath.rbegin()+1, fullpath.rend(), '\\'); if(sep != fullpath.rend()) @@ -84,7 +98,7 @@ void DirectorySearch(const char *path, const char *ext, std::vector std::wstring wpath{utf8_to_wstr(pathstr.c_str())}; WIN32_FIND_DATAW fdata; - HANDLE hdl{FindFirstFileW(wpath.c_str(), &fdata)}; + HANDLE hdl{FindFirstFileExW(wpath.c_str(), FindExInfoStandard, &fdata, FindExSearchNameMatch, NULL, 0)}; if(hdl == INVALID_HANDLE_VALUE) return; const auto base = results->size(); @@ -97,7 +111,6 @@ void DirectorySearch(const char *path, const char *ext, std::vector str += wstr_to_utf8(fdata.cFileName); } while(FindNextFileW(hdl, &fdata)); FindClose(hdl); - const al::span newlist{results->data()+base, results->size()-base}; std::sort(newlist.begin(), newlist.end()); for(const auto &name : newlist) @@ -149,6 +162,7 @@ std::vector SearchDataFiles(const char *ext, const char *subdir) std::replace(path.begin(), path.end(), '/', '\\'); DirectorySearch(path.c_str(), ext, &results); +#if !defined(ALSOFT_UWP) /* Search the local and global data dirs. */ static const int ids[2]{ CSIDL_APPDATA, CSIDL_COMMON_APPDATA }; for(int id : ids) @@ -165,17 +179,20 @@ std::vector SearchDataFiles(const char *ext, const char *subdir) DirectorySearch(path.c_str(), ext, &results); } +#endif return results; } void SetRTPriority(void) { +#if !defined(ALSOFT_UWP) if(RTPrioLevel > 0) { if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) ERR("Failed to set priority level for thread\n"); } +#endif } #else diff --git a/core/uiddefs.cpp b/core/uiddefs.cpp index 244c01a5..833150f5 100644 --- a/core/uiddefs.cpp +++ b/core/uiddefs.cpp @@ -24,7 +24,7 @@ DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2); DEFINE_GUID(IID_IAudioCaptureClient, 0xc8adbd64, 0xe71e, 0x48a0, 0xa4,0xde, 0x18,0x5c,0x39,0x5c,0xd3,0x17); -#ifdef HAVE_WASAPI +#if defined(HAVE_WASAPI) && !defined(ALSOFT_UWP) #include #include #include diff --git a/router/router.cpp b/router/router.cpp index 3c891053..18ecf9b4 100644 --- a/router/router.cpp +++ b/router/router.cpp @@ -334,7 +334,7 @@ void LoadDriverList(void) TRACE("Got DLL path %ls\n", dll_path); GetCurrentDirectoryW(MAX_PATH, cwd_path); - len = lstrlenW(cwd_path); + len = wcslen(cwd_path); if(len > 0 && (cwd_path[len-1] == '\\' || cwd_path[len-1] == '/')) cwd_path[len-1] = '\0'; TRACE("Got current working directory %ls\n", cwd_path); @@ -343,7 +343,7 @@ void LoadDriverList(void) TRACE("Got proc path %ls\n", proc_path); GetSystemDirectoryW(sys_path, MAX_PATH); - len = lstrlenW(sys_path); + len = wcslen(sys_path); if(len > 0 && (sys_path[len-1] == '\\' || sys_path[len-1] == '/')) sys_path[len-1] = '\0'; TRACE("Got system path %ls\n", sys_path); -- cgit v1.2.3 From 23f90b854a51eeaf6f70383beeef42944b675ce0 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 31 May 2023 01:35:35 -0700 Subject: Don't register per-device default change handlers It's global state with a global callback. No need to associate it with each open device. --- alc/backends/wasapi.cpp | 211 +++++++++++++++++++----------------------------- 1 file changed, 83 insertions(+), 128 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index c8c03e8a..a11f8ae9 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -228,7 +228,7 @@ using EventRegistrationToken = void*; #if defined(ALSOFT_UWP) struct DeviceHelper final : public IActivateAudioInterfaceCompletionHandler #else -struct DeviceHelper final : public IMMNotificationClient +struct DeviceHelper final : private IMMNotificationClient #endif { public: @@ -236,10 +236,29 @@ public: { #if defined(ALSOFT_UWP) mActiveClientEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr); + + auto cb = [](const WCHAR *devid) + { + const std::string msg{"Default device changed: "+wstr_to_utf8(devid)}; + alc::Event(alc::EventType::DefaultDeviceChanged, msg); + }; + + mRenderDeviceChangedToken = MediaDevice::DefaultAudioRenderDeviceChanged += + ref new TypedEventHandler( + [this,cb](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { + if (args->Role == AudioDeviceRole::Default) + cb(args->Id->Data()); + }); + mCaptureDeviceChangedToken = MediaDevice::DefaultAudioCaptureDeviceChanged += + ref new TypedEventHandler( + [this,cb](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { + if (args->Role == AudioDeviceRole::Default) + cb(args->Id->Data()); + }); #else - HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, - al::out_ptr(mEnumerator)); - if (SUCCEEDED(hr)) + HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, + IID_IMMDeviceEnumerator, al::out_ptr(mEnumerator))}; + if(SUCCEEDED(hr)) mEnumerator->RegisterEndpointNotificationCallback(this); else WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); @@ -248,31 +267,31 @@ public: ~DeviceHelper() { #if defined(ALSOFT_UWP) - if (mActiveClientEvent != nullptr) + MediaDevice::DefaultAudioRenderDeviceChanged -= mRenderDeviceChangedToken; + MediaDevice::DefaultAudioCaptureDeviceChanged -= mCaptureDeviceChangedToken; + + if(mActiveClientEvent != nullptr) CloseHandle(mActiveClientEvent); mActiveClientEvent = nullptr; #else - if (mEnumerator) + if(mEnumerator) mEnumerator->UnregisterEndpointNotificationCallback(this); mEnumerator = nullptr; #endif } /** -------------------------- IUnkonwn ----------------------------- */ - LONG mRefCount{1}; - ULONG STDMETHODCALLTYPE AddRef() override { return InterlockedIncrement(&mRefCount); } + std::atomic mRefCount{1}; + STDMETHODIMP_(ULONG) AddRef() noexcept override { return mRefCount.fetch_add(1u) + 1u; } - ULONG STDMETHODCALLTYPE Release() override + STDMETHODIMP_(ULONG) Release() noexcept override { - ULONG ulRef = InterlockedDecrement(&mRefCount); - if (0 == ulRef) - { - delete this; - } - return ulRef; + auto ret = mRefCount.fetch_sub(1u) - 1u; + if(!ret) delete this; + return ret; } - HRESULT STDMETHODCALLTYPE QueryInterface(const IID& IId, void** UnknownPtrPtr) override + STDMETHODIMP QueryInterface(const IID& IId, void **UnknownPtrPtr) noexcept override { // Three rules of QueryInterface: // https://docs.microsoft.com/en-us/windows/win32/com/rules-for-implementing-queryinterface @@ -281,10 +300,8 @@ public: // 3. It must be possible to query successfully for any interface on an object from any other interface. // If ppvObject(the address) is nullptr, then this method returns E_POINTER. - if (!UnknownPtrPtr) - { + if(!UnknownPtrPtr) return E_POINTER; - } // https://docs.microsoft.com/en-us/windows/win32/com/implementing-reference-counting // Whenever a client calls a method(or API function), such as QueryInterface, that returns a new interface @@ -294,23 +311,23 @@ public: // interface pointer, the reference count becomes two. The client must call Release twice on the interface // pointer to drop all of its references to the object. #if defined(ALSOFT_UWP) - if (IId == __uuidof(IActivateAudioInterfaceCompletionHandler)) + if(IId == __uuidof(IActivateAudioInterfaceCompletionHandler)) { - *UnknownPtrPtr = (IActivateAudioInterfaceCompletionHandler*)(this); + *UnknownPtrPtr = static_cast(this); AddRef(); return S_OK; } #else - if (IId == __uuidof(IMMNotificationClient)) + if(IId == __uuidof(IMMNotificationClient)) { - *UnknownPtrPtr = (IMMNotificationClient*)(this); + *UnknownPtrPtr = static_cast(this); AddRef(); return S_OK; } #endif - else if (IId == __uuidof(IAgileObject) || IId == __uuidof(IUnknown)) + else if(IId == __uuidof(IAgileObject) || IId == __uuidof(IUnknown)) { - *UnknownPtrPtr = (IUnknown*)(this); + *UnknownPtrPtr = static_cast(this); AddRef(); return S_OK; } @@ -347,20 +364,16 @@ public: } #else /** ----------------------- IMMNotificationClient ------------ */ - STDMETHOD(OnDeviceStateChanged(LPCWSTR /*pwstrDeviceId*/, DWORD /*dwNewState*/)) override { return S_OK; } - STDMETHOD(OnDeviceAdded(LPCWSTR /*pwstrDeviceId*/)) override { return S_OK; } - STDMETHOD(OnDeviceRemoved(LPCWSTR /*pwstrDeviceId*/)) override { return S_OK; } - STDMETHOD(OnPropertyValueChanged(LPCWSTR /*pwstrDeviceId*/, const PROPERTYKEY /*key*/)) override { return S_OK; } - STDMETHOD(OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId)) override + STDMETHODIMP OnDeviceStateChanged(LPCWSTR /*pwstrDeviceId*/, DWORD /*dwNewState*/) noexcept override { return S_OK; } + STDMETHODIMP OnDeviceAdded(LPCWSTR /*pwstrDeviceId*/) noexcept override { return S_OK; } + STDMETHODIMP OnDeviceRemoved(LPCWSTR /*pwstrDeviceId*/) noexcept override { return S_OK; } + STDMETHODIMP OnPropertyValueChanged(LPCWSTR /*pwstrDeviceId*/, const PROPERTYKEY /*key*/) noexcept override { return S_OK; } + STDMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) noexcept override { - if (role == eMultimedia && (flow == eRender || flow == eCapture)) + if(role == eMultimedia && (flow == eRender || flow == eCapture)) { - std::lock_guard lck(mDefaultChangeHandlersMtx); - for (auto& handlerItem : mDefaultChangeHandlers) - { - if (handlerItem.second.first == flow) - handlerItem.second.second(pwstrDefaultDeviceId); - } + const std::string msg{"Default device changed: "+wstr_to_utf8(pwstrDefaultDeviceId)}; + alc::Event(alc::EventType::DefaultDeviceChanged, msg); } return S_OK; } @@ -370,18 +383,15 @@ public: HRESULT OpenDevice(LPCWSTR devid, EDataFlow flow, DeviceHandle& device) { #if !defined(ALSOFT_UWP) - HRESULT hr = E_POINTER; - if (mEnumerator) + HRESULT hr{E_POINTER}; + if(mEnumerator) { if (!devid) hr = mEnumerator->GetDefaultAudioEndpoint(flow, eMultimedia, al::out_ptr(device)); else hr = mEnumerator->GetDevice(devid, al::out_ptr(device)); } - if (FAILED(hr)) - { - return hr; - } + return hr; #else const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; Platform::String^ devIfPath = @@ -397,18 +407,17 @@ public: { return E_NOINTERFACE; } -#endif return S_OK; +#endif } - HRESULT ActivateAudioClient(_In_ DeviceHandle& device, - void** ppv) + HRESULT ActivateAudioClient(_In_ DeviceHandle& device, void **ppv) { #if !defined(ALSOFT_UWP) HRESULT hr{device->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER, nullptr, ppv)}; #else - HRESULT hr{ActivateAudioInterface(device.value->Id->Data(), - __uuidof(IAudioClient3), nullptr, ppv)}; + HRESULT hr{ActivateAudioInterface(device.value->Id->Data(), __uuidof(IAudioClient3), + nullptr, ppv)}; #endif return hr; } @@ -419,8 +428,9 @@ public: #if !defined(ALSOFT_UWP) ComPtr coll; - HRESULT hr{mEnumerator->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, al::out_ptr(coll))}; - if (FAILED(hr)) + HRESULT hr{mEnumerator->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, + al::out_ptr(coll))}; + if(FAILED(hr)) { ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); return hr; @@ -428,14 +438,14 @@ public: UINT count{0}; hr = coll->GetCount(&count); - if (SUCCEEDED(hr) && count > 0) + if(SUCCEEDED(hr) && count > 0) list.reserve(count); ComPtr device; hr = mEnumerator->GetDefaultAudioEndpoint(flowdir, eMultimedia, al::out_ptr(device)); - if (SUCCEEDED(hr)) + if(SUCCEEDED(hr)) { - if (WCHAR * devid{get_device_id(device.get())}) + if(WCHAR *devid{get_device_id(device.get())}) { add_device(device, devid, list); CoTaskMemFree(devid); @@ -443,13 +453,13 @@ public: device = nullptr; } - for (UINT i{0}; i < count; ++i) + for(UINT i{0};i < count;++i) { hr = coll->Item(i, al::out_ptr(device)); - if (FAILED(hr)) + if(FAILED(hr)) continue; - if (WCHAR * devid{get_device_id(device.get())}) + if(WCHAR *devid{get_device_id(device.get())}) { add_device(device, devid, list); CoTaskMemFree(devid); @@ -595,12 +605,12 @@ public: } #if !defined(ALSOFT_UWP) - static WCHAR* get_device_id(IMMDevice* device) + static WCHAR *get_device_id(IMMDevice* device) { - WCHAR* devid; + WCHAR *devid; const HRESULT hr{device->GetId(&devid)}; - if (FAILED(hr)) + if(FAILED(hr)) { ERR("Failed to get device id: %lx\n", hr); return nullptr; @@ -612,7 +622,7 @@ public: { ComPtr ps; HRESULT hr{device->OpenPropertyStore(STGM_READ, al::out_ptr(ps))}; - if (FAILED(hr)) + if(FAILED(hr)) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); return UnknownFormFactor; @@ -621,52 +631,16 @@ public: EndpointFormFactor formfactor{UnknownFormFactor}; PropVariant pvform; hr = ps->GetValue(PKEY_AudioEndpoint_FormFactor, pvform.get()); - if (FAILED(hr)) + if(FAILED(hr)) WARN("GetValue AudioEndpoint_FormFactor failed: 0x%08lx\n", hr); - else if (pvform->vt == VT_UI4) + else if(pvform->vt == VT_UI4) formfactor = static_cast(pvform->ulVal); - else if (pvform->vt != VT_EMPTY) + else if(pvform->vt != VT_EMPTY) WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform->vt); return formfactor; } #endif - template - EventRegistrationToken RegisterDefaultChangeHandler(EDataFlow flow, void* target, _Fty&& cb) - { -#if defined(ALSOFT_UWP) - (void)target; - if (flow == eRender) - return MediaDevice::DefaultAudioRenderDeviceChanged += - ref new TypedEventHandler( - [this, cb](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { - if (args->Role == AudioDeviceRole::Default) - cb(args->Id->Data()); - }); - else - return MediaDevice::DefaultAudioCaptureDeviceChanged += - ref new TypedEventHandler( - [this, cb](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { - if (args->Role == AudioDeviceRole::Default) - cb(args->Id->Data()); - }); -#else - std::lock_guard lck(mDefaultChangeHandlersMtx); - if (mDefaultChangeHandlers.emplace(target, std::make_pair(flow, cb)).second) - return target; - return nullptr; -#endif - } - - void UnregisterDefaultChangeHandler(EventRegistrationToken handler) - { -#if defined(ALSOFT_UWP) - MediaDevice::DefaultAudioRenderDeviceChanged -= handler; -#else - std::lock_guard lck(mDefaultChangeHandlersMtx); - mDefaultChangeHandlers.erase(handler); -#endif - } private: #if defined(ALSOFT_UWP) HRESULT ActivateAudioInterface(_In_ LPCWSTR deviceInterfacePath, @@ -677,24 +651,24 @@ private: IActivateAudioInterfaceAsyncOperation* asyncOp{nullptr}; mPPV = ppv; HRESULT hr = ActivateAudioInterfaceAsync(deviceInterfacePath, riid, activationParams, this, &asyncOp); - if (FAILED(hr)) + if(FAILED(hr)) return hr; - if (asyncOp) + if(asyncOp) asyncOp->Release(); DWORD res{WaitForSingleObjectEx(mActiveClientEvent, 2000, FALSE)}; - if (res != WAIT_OBJECT_0) + if(res != WAIT_OBJECT_0) ERR("WaitForSingleObjectEx error: 0x%lx\n", res); return res; } HANDLE mActiveClientEvent{nullptr}; void** mPPV{nullptr}; + + EventRegistrationToken mRenderDeviceChangedToken; + EventRegistrationToken mCaptureDeviceChangedToken; #else ComPtr mEnumerator{nullptr}; - - std::mutex mDefaultChangeHandlersMtx; - std::unordered_map>> mDefaultChangeHandlers; #endif }; @@ -917,7 +891,7 @@ int WasapiProxy::messageHandler(std::promise *promise) promise->set_value(S_OK); promise = nullptr; - sDeviceHelper.reset(new DeviceHelper()); + sDeviceHelper.reset(new DeviceHelper{}); TRACE("Starting message loop\n"); while(Msg msg{popMessage()}) @@ -955,15 +929,13 @@ int WasapiProxy::messageHandler(std::promise *promise) case MsgType::EnumeratePlayback: case MsgType::EnumerateCapture: - { - if (msg.mType == MsgType::EnumeratePlayback) + if(msg.mType == MsgType::EnumeratePlayback) msg.mPromise.set_value(sDeviceHelper->probe_devices(eRender, PlaybackDevices)); - else if (msg.mType == MsgType::EnumerateCapture) + else if(msg.mType == MsgType::EnumerateCapture) msg.mPromise.set_value(sDeviceHelper->probe_devices(eCapture, CaptureDevices)); else msg.mPromise.set_value(E_FAIL); - continue; - } + continue; case MsgType::QuitThread: break; @@ -1015,9 +987,6 @@ struct WasapiPlayback final : public BackendBase, WasapiProxy { std::atomic mKillNow{true}; std::thread mThread; - std::string mDefaultDeviceId; - EventRegistrationToken mDefaultChangeHandler{}; - DEF_NEWDEL(WasapiPlayback) }; @@ -1204,17 +1173,11 @@ HRESULT WasapiPlayback::openProxy(const char *name) else mDevice->DeviceName = DevNameHead + DeviceHelper::get_device_name_and_guid(mMMDev).first; - mDefaultChangeHandler = sDeviceHelper->RegisterDefaultChangeHandler(eRender, this, [this](LPCWSTR devid) { - mDefaultDeviceId = wstr_to_utf8(devid); - alc::Event(alc::EventType::DefaultDeviceChanged, (ALCdevice*)mDevice, mDefaultDeviceId); - }); - return S_OK; } void WasapiPlayback::closeProxy() { - sDeviceHelper->UnregisterDefaultChangeHandler(mDefaultChangeHandler); mClient = nullptr; mMMDev = nullptr; } @@ -1676,9 +1639,6 @@ struct WasapiCapture final : public BackendBase, WasapiProxy { std::atomic mKillNow{true}; std::thread mThread; - std::string mDefaultDeviceId; - EventRegistrationToken mDefaultChangeHandler{}; - DEF_NEWDEL(WasapiCapture) }; @@ -1875,16 +1835,11 @@ HRESULT WasapiCapture::openProxy(const char *name) else mDevice->DeviceName = DevNameHead + DeviceHelper::get_device_name_and_guid(mMMDev).first; - mDefaultChangeHandler = sDeviceHelper->RegisterDefaultChangeHandler(eCapture, this, [this](LPCWSTR devid) { - mDefaultDeviceId = wstr_to_utf8(devid); - alc::Event(alc::EventType::DefaultDeviceChanged, (ALCdevice*)mDevice, mDefaultDeviceId); - }); return S_OK; } void WasapiCapture::closeProxy() { - sDeviceHelper->UnregisterDefaultChangeHandler(mDefaultChangeHandler); mClient = nullptr; mMMDev = nullptr; } -- cgit v1.2.3 From 1a583b016a7b5e22f370e2f425722e3dc240a7dd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 31 May 2023 02:15:43 -0700 Subject: Initialize the WASAPI device helper earlier --- CMakeLists.txt | 13 ++++++++----- alc/backends/wasapi.cpp | 5 +++-- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index 02bf81b4..ae21a83e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1061,11 +1061,11 @@ if(WIN32) set(BACKENDS "${BACKENDS} WASAPI,") set(ALC_OBJS ${ALC_OBJS} alc/backends/wasapi.cpp alc/backends/wasapi.h) if(ALSOFT_UWP) - set_source_files_properties(alc/backends/wasapi.cpp alc/alconfig.cpp PROPERTIES COMPILE_FLAGS /ZW) + set_source_files_properties(alc/backends/wasapi.cpp alc/alconfig.cpp PROPERTIES COMPILE_FLAGS /ZW) endif() endif() endif() - + # Setup properly link flags for UWP if(ALSOFT_UWP AND HAVE_WASAPI) # Add compile and link flags required C++/CX @@ -1416,8 +1416,8 @@ else() endif() target_link_libraries(${IMPL_TARGET} PRIVATE common ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB}) - if (WIN32) - set_target_properties(${IMPL_TARGET} PROPERTIES + if(ALSOFT_UWP AND HAVE_WASAPI) + set_target_properties(${IMPL_TARGET} PROPERTIES LINK_FLAGS_DEBUG "${LINKER_FLAGS_DEBUG}" LINK_FLAGS_RELEASE "${LINKER_FLAGS_RELEASE}" LINK_FLAGS_MINSIZEREL "${LINKER_FLAGS_RELEASE}" @@ -1538,7 +1538,10 @@ if(FPMATH_SET) message(STATUS "Building with SSE${FPMATH_SET} codegen") message(STATUS "") endif() - +if(ALSOFT_UWP) + message(STATUS "Building with UWP support") + message(STATUS "") +endif() if(ALSOFT_EAX) message(STATUS "Building with legacy EAX extension support") message(STATUS "") diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index a11f8ae9..ccdc54e7 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -891,8 +891,6 @@ int WasapiProxy::messageHandler(std::promise *promise) promise->set_value(S_OK); promise = nullptr; - sDeviceHelper.reset(new DeviceHelper{}); - TRACE("Starting message loop\n"); while(Msg msg{popMessage()}) { @@ -2217,6 +2215,9 @@ bool WasapiBackendFactory::init() WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); enumerator = nullptr; #endif + if(SUCCEEDED(hr)) + WasapiProxy::sDeviceHelper.reset(new DeviceHelper{}); + CoUninitialize(); return hr; -- cgit v1.2.3 From b93c425126de67bef30f9ee9cc112d4278c04954 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 31 May 2023 04:05:44 -0700 Subject: Report device change events from PipeWire --- alc/backends/pipewire.cpp | 125 +++++++++++++++++++++++++++++++++------------- 1 file changed, 91 insertions(+), 34 deletions(-) (limited to 'alc') diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index bb7fc2f2..30dc7a87 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -40,6 +40,7 @@ #include "albit.h" #include "alc/alconfig.h" +#include "alc/events.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -472,16 +473,19 @@ struct EventManager { auto lock() const { return mLoop.lock(); } auto unlock() const { return mLoop.unlock(); } + inline bool initIsDone(std::memory_order m=std::memory_order_seq_cst) noexcept + { return mInitDone.load(m); } + /** * Waits for initialization to finish. The event manager must *NOT* be * locked when calling this. */ void waitForInit() { - if(!mInitDone.load(std::memory_order_acquire)) UNLIKELY + if(!initIsDone(std::memory_order_acquire)) UNLIKELY { MainloopUniqueLock plock{mLoop}; - plock.wait([this](){ return mInitDone.load(std::memory_order_acquire); }); + plock.wait([this](){ return initIsDone(std::memory_order_acquire); }); } } @@ -497,7 +501,7 @@ struct EventManager { plock.wait([this,&has_audio]() { has_audio = mHasAudio.load(std::memory_order_acquire); - return has_audio || mInitDone.load(std::memory_order_acquire); + return has_audio || initIsDone(std::memory_order_acquire); }); return has_audio; } @@ -507,38 +511,34 @@ struct EventManager { /* If initialization isn't done, update the sequence ID so it won't * complete until after currently scheduled events. */ - if(!mInitDone.load(std::memory_order_relaxed)) + if(!initIsDone(std::memory_order_relaxed)) mInitSeq = ppw_core_sync(mCore.get(), PW_ID_CORE, mInitSeq); } void addCallback(uint32_t id, uint32_t permissions, const char *type, uint32_t version, - const spa_dict *props); - static void addCallbackC(void *object, uint32_t id, uint32_t permissions, const char *type, - uint32_t version, const spa_dict *props) - { static_cast(object)->addCallback(id, permissions, type, version, props); } + const spa_dict *props) noexcept; - void removeCallback(uint32_t id); - static void removeCallbackC(void *object, uint32_t id) - { static_cast(object)->removeCallback(id); } + void removeCallback(uint32_t id) noexcept; static constexpr pw_registry_events CreateRegistryEvents() { pw_registry_events ret{}; ret.version = PW_VERSION_REGISTRY_EVENTS; - ret.global = &EventManager::addCallbackC; - ret.global_remove = &EventManager::removeCallbackC; + ret.global = [](void *object, uint32_t id, uint32_t permissions, const char *type, uint32_t version, const spa_dict *props) noexcept + { static_cast(object)->addCallback(id, permissions, type, version, props); }; + ret.global_remove = [](void *object, uint32_t id) noexcept + { static_cast(object)->removeCallback(id); }; return ret; } - void coreCallback(uint32_t id, int seq); - static void coreCallbackC(void *object, uint32_t id, int seq) - { static_cast(object)->coreCallback(id, seq); } + void coreCallback(uint32_t id, int seq) noexcept; static constexpr pw_core_events CreateCoreEvents() { pw_core_events ret{}; ret.version = PW_VERSION_CORE_EVENTS; - ret.done = &EventManager::coreCallbackC; + ret.done = [](void *object, uint32_t id, int seq) noexcept + { static_cast(object)->coreCallback(id, seq); }; return ret; } }; @@ -571,6 +571,7 @@ struct DeviceNode { static std::vector sList; static DeviceNode &Add(uint32_t id); static DeviceNode *Find(uint32_t id); + static DeviceNode *FindByDevName(std::string_view devname); static void Remove(uint32_t id); static std::vector &GetList() noexcept { return sList; } @@ -619,6 +620,17 @@ DeviceNode *DeviceNode::Find(uint32_t id) return nullptr; } +DeviceNode *DeviceNode::FindByDevName(std::string_view devname) +{ + auto match_id = [devname](DeviceNode &n) noexcept -> bool + { return n.mDevName == devname; }; + + auto match = std::find_if(sList.begin(), sList.end(), match_id); + if(match != sList.end()) return al::to_address(match); + + return nullptr; +} + void DeviceNode::Remove(uint32_t id) { auto match_id = [id](DeviceNode &n) noexcept -> bool @@ -626,6 +638,11 @@ void DeviceNode::Remove(uint32_t id) if(n.mId != id) return false; TRACE("Removing device \"%s\"\n", n.mDevName.c_str()); + if(gEventHandler.initIsDone(std::memory_order_relaxed)) + { + const std::string msg{"Device removed: "+n.mName}; + alc::Event(alc::EventType::DeviceRemoved, msg); + } return true; }; @@ -815,9 +832,9 @@ struct NodeProxy { { pw_node_events ret{}; ret.version = PW_VERSION_NODE_EVENTS; - ret.info = [](void *object, const pw_node_info *info) + ret.info = [](void *object, const pw_node_info *info) noexcept { static_cast(object)->infoCallback(info); }; - ret.param = [](void *object, int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) + ret.param = [](void *object, int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) noexcept { static_cast(object)->paramCallback(seq, id, index, next, param); }; return ret; } @@ -843,12 +860,12 @@ struct NodeProxy { { spa_hook_remove(&mListener); } - void infoCallback(const pw_node_info *info); + void infoCallback(const pw_node_info *info) noexcept; - void paramCallback(int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param); + void paramCallback(int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) noexcept; }; -void NodeProxy::infoCallback(const pw_node_info *info) +void NodeProxy::infoCallback(const pw_node_info *info) noexcept { /* We only care about property changes here (media class, name/desc). * Format changes will automatically invoke the param callback. @@ -896,15 +913,31 @@ void NodeProxy::infoCallback(const pw_node_info *info) } #endif + std::string name; + if(nodeName && *nodeName) name = nodeName; + else name = "PipeWire node #"+std::to_string(info->id); + const char *form_factor{spa_dict_lookup(info->props, PW_KEY_DEVICE_FORM_FACTOR)}; TRACE("Got %s device \"%s\"%s%s%s\n", AsString(ntype), devName ? devName : "(nil)", form_factor?" (":"", form_factor?form_factor:"", form_factor?")":""); - TRACE(" \"%s\" = ID %" PRIu64 "\n", nodeName ? nodeName : "(nil)", serial_id); + TRACE(" \"%s\" = ID %" PRIu64 "\n", name.c_str(), serial_id); DeviceNode &node = DeviceNode::Add(info->id); node.mSerial = serial_id; - if(nodeName && *nodeName) node.mName = nodeName; - else node.mName = "PipeWire node #"+std::to_string(info->id); + if(node.mName != name) + { + if(gEventHandler.mInitDone.load(std::memory_order_relaxed)) + { + if(!node.mName.empty()) + { + const std::string msg{"Device removed: "+node.mName}; + alc::Event(alc::EventType::DeviceRemoved, msg); + } + const std::string msg{"Device added: "+name}; + alc::Event(alc::EventType::DeviceAdded, msg); + } + node.mName = std::move(name); + } node.mDevName = devName ? devName : ""; node.mType = ntype; node.mIsHeadphones = form_factor && (al::strcasecmp(form_factor, "headphones") == 0 @@ -912,7 +945,7 @@ void NodeProxy::infoCallback(const pw_node_info *info) } } -void NodeProxy::paramCallback(int, uint32_t id, uint32_t, uint32_t, const spa_pod *param) +void NodeProxy::paramCallback(int, uint32_t id, uint32_t, uint32_t, const spa_pod *param) noexcept { if(id == SPA_PARAM_EnumFormat) { @@ -936,7 +969,7 @@ struct MetadataProxy { { pw_metadata_events ret{}; ret.version = PW_VERSION_METADATA_EVENTS; - ret.property = [](void *object, uint32_t id, const char *key, const char *type, const char *value) + ret.property = [](void *object, uint32_t id, const char *key, const char *type, const char *value) noexcept { return static_cast(object)->propertyCallback(id, key, type, value); }; return ret; } @@ -955,11 +988,11 @@ struct MetadataProxy { ~MetadataProxy() { spa_hook_remove(&mListener); } - int propertyCallback(uint32_t id, const char *key, const char *type, const char *value); + int propertyCallback(uint32_t id, const char *key, const char *type, const char *value) noexcept; }; int MetadataProxy::propertyCallback(uint32_t id, const char *key, const char *type, - const char *value) + const char *value) noexcept { if(id != PW_ID_CORE) return 0; @@ -1015,9 +1048,33 @@ int MetadataProxy::propertyCallback(uint32_t id, const char *key, const char *ty TRACE("Got default %s device \"%s\"\n", isCapture ? "capture" : "playback", propValue->c_str()); if(!isCapture) - DefaultSinkDevice = std::move(*propValue); + { + if(DefaultSinkDevice != *propValue) + { + if(gEventHandler.mInitDone.load(std::memory_order_relaxed)) + { + auto entry = DeviceNode::FindByDevName(*propValue); + const std::string msg{"Default playback device changed: "+ + (entry ? entry->mName : std::string{})}; + alc::Event(alc::EventType::DefaultDeviceChanged, msg); + } + DefaultSinkDevice = std::move(*propValue); + } + } else - DefaultSourceDevice = std::move(*propValue); + { + if(DefaultSourceDevice != *propValue) + { + if(gEventHandler.mInitDone.load(std::memory_order_relaxed)) + { + auto entry = DeviceNode::FindByDevName(*propValue); + const std::string msg{"Default capture device changed: "+ + (entry ? entry->mName : std::string{})}; + alc::Event(alc::EventType::DefaultDeviceChanged, msg); + } + DefaultSourceDevice = std::move(*propValue); + } + } } else { @@ -1108,7 +1165,7 @@ void EventManager::kill() } void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t version, - const spa_dict *props) + const spa_dict *props) noexcept { /* We're only interested in interface nodes. */ if(std::strcmp(type, PW_TYPE_INTERFACE_Node) == 0) @@ -1183,7 +1240,7 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t } } -void EventManager::removeCallback(uint32_t id) +void EventManager::removeCallback(uint32_t id) noexcept { DeviceNode::Remove(id); @@ -1204,7 +1261,7 @@ void EventManager::removeCallback(uint32_t id) } } -void EventManager::coreCallback(uint32_t id, int seq) +void EventManager::coreCallback(uint32_t id, int seq) noexcept { if(id == PW_ID_CORE && seq == mInitSeq) { -- cgit v1.2.3 From 456e1e828235a721bfab6930fe0c0157fd0d8277 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 31 May 2023 16:12:49 -0700 Subject: Include IOAudioTypes.h only when needed --- alc/backends/coreaudio.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'alc') diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index 521f085d..13665a4c 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -41,17 +41,16 @@ #include #include -#include - - -namespace { #if TARGET_OS_IOS || TARGET_OS_TV #define CAN_ENUMERATE 0 #else +#include #define CAN_ENUMERATE 1 #endif +namespace { + constexpr auto OutputElement = 0; constexpr auto InputElement = 1; -- cgit v1.2.3 From 5f88fe54a06fda76cf16c2dec1d242cdb5e4a8ae Mon Sep 17 00:00:00 2001 From: "Deal(一线灵)" Date: Thu, 1 Jun 2023 21:30:03 +0800 Subject: Report device change events from CoreAudio (#856) * Report device change events from CoreAudio * Fix compile error * Use optional * Use optional, no unique_ptr --- alc/backends/coreaudio.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index 13665a4c..a9419e3d 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -32,12 +32,14 @@ #include #include #include +#include #include "alnumeric.h" #include "core/converter.h" #include "core/device.h" #include "core/logging.h" #include "ringbuffer.h" +#include "alc/events.h" #include #include @@ -271,6 +273,47 @@ void EnumerateDevices(std::vector &list, bool isCapture) newdevs.swap(list); } +struct DeviceHelper +{ +public: + DeviceHelper() + { + AudioObjectPropertyAddress addr = {kAudioHardwarePropertyDefaultOutputDevice, + kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain}; + OSStatus status = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &addr, DeviceListenerProc, nil); + if (status != noErr) + ERR("AudioObjectAddPropertyListener fail: %d", status); + } + ~DeviceHelper() + { + AudioObjectPropertyAddress addr = {kAudioHardwarePropertyDefaultOutputDevice, + kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain}; + OSStatus status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &addr, DeviceListenerProc, nil); + if (status != noErr) + ERR("AudioObjectRemovePropertyListener fail: %d", status); + } + + static OSStatus DeviceListenerProc(AudioObjectID /*inObjectID*/, + UInt32 inNumberAddresses, + const AudioObjectPropertyAddress *inAddresses, + void* /*inClientData*/) + { + for (UInt32 i = 0; i < inNumberAddresses; ++i) + { + switch (inAddresses[i].mSelector) + { + case kAudioHardwarePropertyDefaultOutputDevice: + case kAudioHardwarePropertyDefaultSystemOutputDevice: + case kAudioHardwarePropertyDefaultInputDevice: + alc::Event(alc::EventType::DefaultDeviceChanged, "Default device changed: "+std::to_string(inAddresses[i].mSelector)); + break; + } + } + } +}; + +static std::optional sDeviceHelper; + #else static constexpr char ca_device[] = "CoreAudio Default"; @@ -915,7 +958,13 @@ BackendFactory &CoreAudioBackendFactory::getFactory() return factory; } -bool CoreAudioBackendFactory::init() { return true; } +bool CoreAudioBackendFactory::init() +{ +#if CAN_ENUMERATE + sDeviceHelper.emplace(); +#endif + return true; +} bool CoreAudioBackendFactory::querySupport(BackendType type) { return type == BackendType::Playback || type == BackendType::Capture; } -- cgit v1.2.3 From b5323af956dab2c27153568ef82facda33fff25a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 31 May 2023 17:15:53 -0700 Subject: Add a comment explaining the DeviceAdded logic for PipeWire --- alc/backends/pipewire.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 30dc7a87..fad64f01 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -924,9 +924,18 @@ void NodeProxy::infoCallback(const pw_node_info *info) noexcept DeviceNode &node = DeviceNode::Add(info->id); node.mSerial = serial_id; + /* This method is called both to notify about a new sink/source node, + * and update properties for the node. It's unclear what properties can + * change for an existing node without being removed first, so err on + * the side of caution: send a DeviceAdded event when the name differs, + * and send a DeviceRemoved event if it had a name that's being + * replaced. + * + * This is overkill if the name or devname can't change. + */ if(node.mName != name) { - if(gEventHandler.mInitDone.load(std::memory_order_relaxed)) + if(gEventHandler.initIsDone(std::memory_order_relaxed)) { if(!node.mName.empty()) { -- cgit v1.2.3 From f8d8a1a3900fd51dc3bffb91f88c7725982a7ccc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 31 May 2023 19:03:24 -0700 Subject: Add a context to PulseMainloop --- alc/backends/pulseaudio.cpp | 148 +++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 84 deletions(-) (limited to 'alc') diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index d2883f5c..7554b467 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -291,13 +291,14 @@ pa_context_flags_t pulse_ctx_flags; class PulseMainloop { pa_threaded_mainloop *mLoop{}; + pa_context *mContext{}; public: PulseMainloop() = default; PulseMainloop(const PulseMainloop&) = delete; PulseMainloop(PulseMainloop&& rhs) noexcept : mLoop{rhs.mLoop} { rhs.mLoop = nullptr; } explicit PulseMainloop(pa_threaded_mainloop *loop) noexcept : mLoop{loop} { } - ~PulseMainloop() { if(mLoop) pa_threaded_mainloop_free(mLoop); } + ~PulseMainloop(); PulseMainloop& operator=(const PulseMainloop&) = delete; PulseMainloop& operator=(PulseMainloop&& rhs) noexcept @@ -316,6 +317,7 @@ public: auto stop() const { return pa_threaded_mainloop_stop(mLoop); } auto getApi() const { return pa_threaded_mainloop_get_api(mLoop); } + auto getContext() const noexcept { return mContext; } auto lock() const { return pa_threaded_mainloop_lock(mLoop); } auto unlock() const { return pa_threaded_mainloop_unlock(mLoop); } @@ -329,7 +331,7 @@ public: static void streamSuccessCallbackC(pa_stream *stream, int success, void *pdata) noexcept { static_cast(pdata)->streamSuccessCallback(stream, success); } - void close(pa_context *context, pa_stream *stream=nullptr); + void close(pa_stream *stream=nullptr); void deviceSinkCallback(pa_context*, const pa_sink_info *info, int eol) noexcept @@ -434,31 +436,46 @@ struct MainloopUniqueLock : public std::unique_lock { mutex()->signal(); } - pa_context *connectContext(); - pa_stream *connectStream(const char *device_name, pa_context *context, pa_stream_flags_t flags, + void connectContext(); + pa_stream *connectStream(const char *device_name, pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec, pa_channel_map *chanmap, BackendType type); }; using MainloopLockGuard = std::lock_guard; +PulseMainloop::~PulseMainloop() +{ + if(mContext) + { + MainloopUniqueLock _{*this}; + pa_context_disconnect(mContext); + pa_context_unref(mContext); + } + if(mLoop) + pa_threaded_mainloop_free(mLoop); +} -pa_context *MainloopUniqueLock::connectContext() + +void MainloopUniqueLock::connectContext() { - pa_context *context{pa_context_new(mutex()->getApi(), nullptr)}; - if(!context) throw al::backend_exception{al::backend_error::OutOfMemory, + if(mutex()->mContext) + return; + + mutex()->mContext = pa_context_new(mutex()->getApi(), nullptr); + if(!mutex()->mContext) throw al::backend_exception{al::backend_error::OutOfMemory, "pa_context_new() failed"}; - pa_context_set_state_callback(context, [](pa_context *ctx, void *pdata) noexcept + pa_context_set_state_callback(mutex()->mContext, [](pa_context *ctx, void *pdata) noexcept { return static_cast(pdata)->contextStateCallback(ctx); }, this); int err; - if((err=pa_context_connect(context, nullptr, pulse_ctx_flags, nullptr)) >= 0) + if((err=pa_context_connect(mutex()->mContext, nullptr, pulse_ctx_flags, nullptr)) >= 0) { pa_context_state_t state; - while((state=pa_context_get_state(context)) != PA_CONTEXT_READY) + while((state=pa_context_get_state(mutex()->mContext)) != PA_CONTEXT_READY) { if(!PA_CONTEXT_IS_GOOD(state)) { - err = pa_context_errno(context); + err = pa_context_errno(mutex()->mContext); if(err > 0) err = -err; break; } @@ -466,27 +483,25 @@ pa_context *MainloopUniqueLock::connectContext() wait(); } } - pa_context_set_state_callback(context, nullptr, nullptr); + pa_context_set_state_callback(mutex()->mContext, nullptr, nullptr); if(err < 0) { - pa_context_unref(context); + pa_context_unref(mutex()->mContext); + mutex()->mContext = nullptr; throw al::backend_exception{al::backend_error::DeviceError, "Context did not connect (%s)", pa_strerror(err)}; } - - return context; } -pa_stream *MainloopUniqueLock::connectStream(const char *device_name, pa_context *context, - pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec, pa_channel_map *chanmap, - BackendType type) +pa_stream *MainloopUniqueLock::connectStream(const char *device_name, pa_stream_flags_t flags, + pa_buffer_attr *attr, pa_sample_spec *spec, pa_channel_map *chanmap, BackendType type) { const char *stream_id{(type==BackendType::Playback) ? "Playback Stream" : "Capture Stream"}; - pa_stream *stream{pa_stream_new(context, stream_id, spec, chanmap)}; + pa_stream *stream{pa_stream_new(mutex()->mContext, stream_id, spec, chanmap)}; if(!stream) throw al::backend_exception{al::backend_error::OutOfMemory, "pa_stream_new() failed (%s)", - pa_strerror(pa_context_errno(context))}; + pa_strerror(pa_context_errno(mutex()->mContext))}; pa_stream_set_state_callback(stream, [](pa_stream *strm, void *pdata) noexcept { return static_cast(pdata)->streamStateCallback(strm); }, this); @@ -506,7 +521,7 @@ pa_stream *MainloopUniqueLock::connectStream(const char *device_name, pa_context { if(!PA_STREAM_IS_GOOD(state)) { - err = pa_context_errno(context); + err = pa_context_errno(mutex()->mContext); pa_stream_unref(stream); throw al::backend_exception{al::backend_error::DeviceError, "%s did not get ready (%s)", stream_id, pa_strerror(err)}; @@ -519,75 +534,57 @@ pa_stream *MainloopUniqueLock::connectStream(const char *device_name, pa_context return stream; } -void PulseMainloop::close(pa_context *context, pa_stream *stream) +void PulseMainloop::close(pa_stream *stream) { - MainloopUniqueLock _{*this}; - if(stream) - { - pa_stream_set_state_callback(stream, nullptr, nullptr); - pa_stream_set_moved_callback(stream, nullptr, nullptr); - pa_stream_set_write_callback(stream, nullptr, nullptr); - pa_stream_set_buffer_attr_callback(stream, nullptr, nullptr); - pa_stream_disconnect(stream); - pa_stream_unref(stream); - } + if(!stream) + return; - pa_context_disconnect(context); - pa_context_unref(context); + MainloopUniqueLock _{*this}; + pa_stream_set_state_callback(stream, nullptr, nullptr); + pa_stream_set_moved_callback(stream, nullptr, nullptr); + pa_stream_set_write_callback(stream, nullptr, nullptr); + pa_stream_set_buffer_attr_callback(stream, nullptr, nullptr); + pa_stream_disconnect(stream); + pa_stream_unref(stream); } void PulseMainloop::probePlaybackDevices() { - pa_context *context{}; - PlaybackDevices.clear(); try { MainloopUniqueLock plock{*this}; auto sink_callback = [](pa_context *ctx, const pa_sink_info *info, int eol, void *pdata) noexcept { return static_cast(pdata)->deviceSinkCallback(ctx, info, eol); }; - context = plock.connectContext(); - pa_operation *op{pa_context_get_sink_info_by_name(context, nullptr, sink_callback, this)}; + pa_operation *op{pa_context_get_sink_info_by_name(mContext, nullptr, sink_callback, this)}; plock.waitForOperation(op); - op = pa_context_get_sink_info_list(context, sink_callback, this); + op = pa_context_get_sink_info_list(mContext, sink_callback, this); plock.waitForOperation(op); - - pa_context_disconnect(context); - pa_context_unref(context); - context = nullptr; } catch(std::exception &e) { ERR("Error enumerating devices: %s\n", e.what()); - if(context) close(context); } } void PulseMainloop::probeCaptureDevices() { - pa_context *context{}; - CaptureDevices.clear(); try { MainloopUniqueLock plock{*this}; auto src_callback = [](pa_context *ctx, const pa_source_info *info, int eol, void *pdata) noexcept { return static_cast(pdata)->deviceSourceCallback(ctx, info, eol); }; - context = plock.connectContext(); - pa_operation *op{pa_context_get_source_info_by_name(context, nullptr, src_callback, this)}; + pa_operation *op{pa_context_get_source_info_by_name(mContext, nullptr, src_callback, + this)}; plock.waitForOperation(op); - op = pa_context_get_source_info_list(context, src_callback, this); + op = pa_context_get_source_info_list(mContext, src_callback, this); plock.waitForOperation(op); - - pa_context_disconnect(context); - pa_context_unref(context); - context = nullptr; } catch(std::exception &e) { ERR("Error enumerating devices: %s\n", e.what()); - if(context) close(context); } } @@ -622,7 +619,6 @@ struct PulsePlayback final : public BackendBase { pa_sample_spec mSpec; pa_stream *mStream{nullptr}; - pa_context *mContext{nullptr}; uint mFrameSize{0u}; @@ -630,14 +626,7 @@ struct PulsePlayback final : public BackendBase { }; PulsePlayback::~PulsePlayback() -{ - if(!mContext) - return; - - mMainloop.close(mContext, mStream); - mContext = nullptr; - mStream = nullptr; -} +{ if(mStream) mMainloop.close(mStream); } void PulsePlayback::bufferAttrCallback(pa_stream *stream) noexcept @@ -772,7 +761,7 @@ void PulsePlayback::open(const char *name) } MainloopUniqueLock plock{mMainloop}; - mContext = plock.connectContext(); + plock.connectContext(); pa_stream_flags_t flags{PA_STREAM_START_CORKED | PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE | PA_STREAM_FIX_CHANNELS}; @@ -790,7 +779,7 @@ void PulsePlayback::open(const char *name) if(defname) pulse_name = defname->c_str(); } TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)"); - mStream = plock.connectStream(pulse_name, mContext, flags, nullptr, &spec, nullptr, + mStream = plock.connectStream(pulse_name, flags, nullptr, &spec, nullptr, BackendType::Playback); pa_stream_set_moved_callback(mStream, [](pa_stream *stream, void *pdata) noexcept @@ -803,7 +792,7 @@ void PulsePlayback::open(const char *name) { auto name_callback = [](pa_context *context, const pa_sink_info *info, int eol, void *pdata) noexcept { return static_cast(pdata)->sinkNameCallback(context, info, eol); }; - pa_operation *op{pa_context_get_sink_info_by_name(mContext, + pa_operation *op{pa_context_get_sink_info_by_name(mMainloop.getContext(), pa_stream_get_device_name(mStream), name_callback, this)}; plock.waitForOperation(op); } @@ -829,7 +818,8 @@ bool PulsePlayback::reset() auto info_callback = [](pa_context *context, const pa_sink_info *info, int eol, void *pdata) noexcept { return static_cast(pdata)->sinkInfoCallback(context, info, eol); }; - pa_operation *op{pa_context_get_sink_info_by_name(mContext, deviceName, info_callback, this)}; + pa_operation *op{pa_context_get_sink_info_by_name(mMainloop.getContext(), deviceName, + info_callback, this)}; plock.waitForOperation(op); pa_stream_flags_t flags{PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | @@ -916,7 +906,7 @@ bool PulsePlayback::reset() mAttr.minreq = mDevice->UpdateSize * frame_size; mAttr.fragsize = ~0u; - mStream = plock.connectStream(deviceName, mContext, flags, &mAttr, &mSpec, &chanmap, + mStream = plock.connectStream(deviceName, flags, &mAttr, &mSpec, &chanmap, BackendType::Playback); pa_stream_set_state_callback(mStream, [](pa_stream *stream, void *pdata) noexcept @@ -1055,20 +1045,12 @@ struct PulseCapture final : public BackendBase { pa_sample_spec mSpec{}; pa_stream *mStream{nullptr}; - pa_context *mContext{nullptr}; DEF_NEWDEL(PulseCapture) }; PulseCapture::~PulseCapture() -{ - if(!mContext) - return; - - mMainloop.close(mContext, mStream); - mContext = nullptr; - mStream = nullptr; -} +{ if(mStream) mMainloop.close(mStream); } void PulseCapture::streamStateCallback(pa_stream *stream) noexcept @@ -1122,7 +1104,7 @@ void PulseCapture::open(const char *name) } MainloopUniqueLock plock{mMainloop}; - mContext = plock.connectContext(); + plock.connectContext(); pa_channel_map chanmap{}; switch(mDevice->FmtChans) @@ -1194,7 +1176,7 @@ void PulseCapture::open(const char *name) flags |= PA_STREAM_DONT_MOVE; TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)"); - mStream = plock.connectStream(pulse_name, mContext, flags, &mAttr, &mSpec, &chanmap, + mStream = plock.connectStream(pulse_name, flags, &mAttr, &mSpec, &chanmap, BackendType::Capture); pa_stream_set_moved_callback(mStream, [](pa_stream *stream, void *pdata) noexcept @@ -1208,7 +1190,7 @@ void PulseCapture::open(const char *name) { auto name_callback = [](pa_context *context, const pa_source_info *info, int eol, void *pdata) noexcept { return static_cast(pdata)->sourceNameCallback(context, info, eol); }; - pa_operation *op{pa_context_get_source_info_by_name(mContext, + pa_operation *op{pa_context_get_source_info_by_name(mMainloop.getContext(), pa_stream_get_device_name(mStream), name_callback, this)}; plock.waitForOperation(op); } @@ -1281,7 +1263,7 @@ void PulseCapture::captureSamples(std::byte *buffer, uint samples) if(pa_stream_peek(mStream, &capbuf, &caplen) < 0) UNLIKELY { mDevice->handleDisconnect("Failed retrieving capture samples: %s", - pa_strerror(pa_context_errno(mContext))); + pa_strerror(pa_context_errno(mMainloop.getContext()))); break; } plock.unlock(); @@ -1412,9 +1394,7 @@ bool PulseBackendFactory::init() } MainloopUniqueLock plock{gGlobalMainloop}; - pa_context *context{plock.connectContext()}; - pa_context_disconnect(context); - pa_context_unref(context); + plock.connectContext(); return true; } catch(...) { -- cgit v1.2.3 From 360fdcbc721644e7b07aab7cbea4fc11bfa144d8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 31 May 2023 20:55:16 -0700 Subject: Handle device added/removed events with PulseAudio --- alc/backends/pulseaudio.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'alc') diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index 7554b467..16a2450f 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -41,6 +41,7 @@ #include "albit.h" #include "alc/alconfig.h" +#include "alc/events.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -65,6 +66,8 @@ using uint = unsigned int; MAGIC(pa_context_get_state); \ MAGIC(pa_context_disconnect); \ MAGIC(pa_context_set_state_callback); \ + MAGIC(pa_context_set_subscribe_callback); \ + MAGIC(pa_context_subscribe); \ MAGIC(pa_context_errno); \ MAGIC(pa_context_connect); \ MAGIC(pa_context_get_server_info); \ @@ -136,6 +139,8 @@ PULSE_FUNCS(MAKE_FUNC) #define pa_context_get_state ppa_context_get_state #define pa_context_disconnect ppa_context_disconnect #define pa_context_set_state_callback ppa_context_set_state_callback +#define pa_context_set_subscribe_callback ppa_context_set_subscribe_callback +#define pa_context_subscribe ppa_context_subscribe #define pa_context_errno ppa_context_errno #define pa_context_connect ppa_context_connect #define pa_context_get_server_info ppa_context_get_server_info @@ -270,6 +275,9 @@ constexpr pa_context_flags_t& operator|=(pa_context_flags_t &lhs, pa_context_fla return lhs; } +constexpr pa_subscription_mask_t operator|(pa_subscription_mask_t lhs, pa_subscription_mask_t rhs) +{ return pa_subscription_mask_t(lhs | al::to_underlying(rhs)); } + struct DevMap { std::string name; @@ -422,6 +430,39 @@ struct MainloopUniqueLock : public std::unique_lock { } + void setEventHandler() + { + pa_operation *op{pa_context_subscribe(mutex()->mContext, + PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, + [](pa_context*, int, void *pdata) noexcept + { static_cast(pdata)->signal(); }, + mutex())}; + waitForOperation(op); + + /* Watch for device added/removed events. + * + * TODO: Also track the "default" device, in as much as PulseAudio has + * the concept of a default device (whatever device is opened when not + * specifying a specific sink or source name). There doesn't seem to be + * an event for this. + */ + auto handler = [](pa_context*, pa_subscription_event_type_t t, uint32_t, void*) noexcept + { + const auto eventFacility = (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK); + if(eventFacility == PA_SUBSCRIPTION_EVENT_SINK + || eventFacility == PA_SUBSCRIPTION_EVENT_SOURCE) + { + const auto eventType = (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK); + if(eventType == PA_SUBSCRIPTION_EVENT_NEW) + alc::Event(alc::EventType::DeviceAdded, "Device added"); + else if(eventType == PA_SUBSCRIPTION_EVENT_REMOVE) + alc::Event(alc::EventType::DeviceRemoved, "Device removed"); + } + }; + pa_context_set_subscribe_callback(mutex()->mContext, handler, nullptr); + } + + void contextStateCallback(pa_context *context) noexcept { pa_context_state_t state{pa_context_get_state(context)}; @@ -1395,6 +1436,7 @@ bool PulseBackendFactory::init() MainloopUniqueLock plock{gGlobalMainloop}; plock.connectContext(); + plock.setEventHandler(); return true; } catch(...) { -- cgit v1.2.3 From edc20c87d3cd37608e8fa50556d718cd32755f3d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 31 May 2023 22:11:15 -0700 Subject: Specify the device type for the event callback --- alc/backends/coreaudio.cpp | 28 ++++++++++++++-------------- alc/backends/pipewire.cpp | 22 +++++++++++++++++----- alc/backends/pulseaudio.cpp | 6 ++++-- alc/backends/wasapi.cpp | 38 +++++++++++++++++++++++++++++--------- alc/events.cpp | 10 +++++----- alc/events.h | 11 ++++++++--- alc/inprogext.h | 16 +++++++++------- 7 files changed, 86 insertions(+), 45 deletions(-) (limited to 'alc') diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index a9419e3d..1e8423b7 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -273,39 +273,39 @@ void EnumerateDevices(std::vector &list, bool isCapture) newdevs.swap(list); } -struct DeviceHelper -{ -public: +struct DeviceHelper { DeviceHelper() { - AudioObjectPropertyAddress addr = {kAudioHardwarePropertyDefaultOutputDevice, - kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain}; + AudioObjectPropertyAddress addr{kAudioHardwarePropertyDefaultOutputDevice, + kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain}; OSStatus status = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &addr, DeviceListenerProc, nil); if (status != noErr) ERR("AudioObjectAddPropertyListener fail: %d", status); } ~DeviceHelper() { - AudioObjectPropertyAddress addr = {kAudioHardwarePropertyDefaultOutputDevice, - kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain}; + AudioObjectPropertyAddress addr{kAudioHardwarePropertyDefaultOutputDevice, + kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain}; OSStatus status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &addr, DeviceListenerProc, nil); if (status != noErr) ERR("AudioObjectRemovePropertyListener fail: %d", status); } - static OSStatus DeviceListenerProc(AudioObjectID /*inObjectID*/, - UInt32 inNumberAddresses, - const AudioObjectPropertyAddress *inAddresses, - void* /*inClientData*/) + static OSStatus DeviceListenerProc(AudioObjectID /*inObjectID*/, UInt32 inNumberAddresses, + const AudioObjectPropertyAddress *inAddresses, void* /*inClientData*/) { - for (UInt32 i = 0; i < inNumberAddresses; ++i) + for(UInt32 i = 0; i < inNumberAddresses; ++i) { - switch (inAddresses[i].mSelector) + switch(inAddresses[i].mSelector) { case kAudioHardwarePropertyDefaultOutputDevice: case kAudioHardwarePropertyDefaultSystemOutputDevice: + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, + "Default playback device changed: "+std::to_string(inAddresses[i].mSelector)); + break; case kAudioHardwarePropertyDefaultInputDevice: - alc::Event(alc::EventType::DefaultDeviceChanged, "Default device changed: "+std::to_string(inAddresses[i].mSelector)); + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, + "Default capture device changed: "+std::to_string(inAddresses[i].mSelector)); break; } } diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index fad64f01..2bee4d7d 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -578,6 +578,16 @@ struct DeviceNode { void parseSampleRate(const spa_pod *value) noexcept; void parsePositions(const spa_pod *value) noexcept; void parseChannelCount(const spa_pod *value) noexcept; + + void callEvent(alc::EventType type, std::string_view message) + { + /* Source nodes aren't recognized for playback, only Sink and Duplex + * nodes are. All node types are recognized for capture. + */ + if(mType != NodeType::Source) + alc::Event(type, alc::DeviceType::Playback, message); + alc::Event(type, alc::DeviceType::Capture, message); + } }; std::vector DeviceNode::sList; std::string DefaultSinkDevice; @@ -641,7 +651,7 @@ void DeviceNode::Remove(uint32_t id) if(gEventHandler.initIsDone(std::memory_order_relaxed)) { const std::string msg{"Device removed: "+n.mName}; - alc::Event(alc::EventType::DeviceRemoved, msg); + n.callEvent(alc::EventType::DeviceRemoved, msg); } return true; }; @@ -940,10 +950,10 @@ void NodeProxy::infoCallback(const pw_node_info *info) noexcept if(!node.mName.empty()) { const std::string msg{"Device removed: "+node.mName}; - alc::Event(alc::EventType::DeviceRemoved, msg); + node.callEvent(alc::EventType::DeviceRemoved, msg); } const std::string msg{"Device added: "+name}; - alc::Event(alc::EventType::DeviceAdded, msg); + node.callEvent(alc::EventType::DeviceAdded, msg); } node.mName = std::move(name); } @@ -1065,7 +1075,8 @@ int MetadataProxy::propertyCallback(uint32_t id, const char *key, const char *ty auto entry = DeviceNode::FindByDevName(*propValue); const std::string msg{"Default playback device changed: "+ (entry ? entry->mName : std::string{})}; - alc::Event(alc::EventType::DefaultDeviceChanged, msg); + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, + msg); } DefaultSinkDevice = std::move(*propValue); } @@ -1079,7 +1090,8 @@ int MetadataProxy::propertyCallback(uint32_t id, const char *key, const char *ty auto entry = DeviceNode::FindByDevName(*propValue); const std::string msg{"Default capture device changed: "+ (entry ? entry->mName : std::string{})}; - alc::Event(alc::EventType::DefaultDeviceChanged, msg); + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, + msg); } DefaultSourceDevice = std::move(*propValue); } diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index 16a2450f..8c6cc4d3 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -452,11 +452,13 @@ struct MainloopUniqueLock : public std::unique_lock { if(eventFacility == PA_SUBSCRIPTION_EVENT_SINK || eventFacility == PA_SUBSCRIPTION_EVENT_SOURCE) { + const auto deviceType = (eventFacility == PA_SUBSCRIPTION_EVENT_SINK) + ? alc::DeviceType::Playback : alc::DeviceType::Capture; const auto eventType = (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK); if(eventType == PA_SUBSCRIPTION_EVENT_NEW) - alc::Event(alc::EventType::DeviceAdded, "Device added"); + alc::Event(alc::EventType::DeviceAdded, deviceType, "Device added"); else if(eventType == PA_SUBSCRIPTION_EVENT_REMOVE) - alc::Event(alc::EventType::DeviceRemoved, "Device removed"); + alc::Event(alc::EventType::DeviceRemoved, deviceType, "Device removed"); } }; pa_context_set_subscribe_callback(mutex()->mContext, handler, nullptr); diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index ccdc54e7..32a4334d 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -237,23 +237,33 @@ public: #if defined(ALSOFT_UWP) mActiveClientEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr); - auto cb = [](const WCHAR *devid) + auto cb = [](alc::DeviceType type, const WCHAR *devid) { const std::string msg{"Default device changed: "+wstr_to_utf8(devid)}; - alc::Event(alc::EventType::DefaultDeviceChanged, msg); + alc::Event(alc::EventType::DefaultDeviceChanged, type, msg); }; mRenderDeviceChangedToken = MediaDevice::DefaultAudioRenderDeviceChanged += ref new TypedEventHandler( [this,cb](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { - if (args->Role == AudioDeviceRole::Default) - cb(args->Id->Data()); + if(args->Role == AudioDeviceRole::Default) + { + const std::string msg{"Default playback device changed: "+ + wstr_to_utf8(args->Id->Data())}; + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, + msg); + } }); mCaptureDeviceChangedToken = MediaDevice::DefaultAudioCaptureDeviceChanged += ref new TypedEventHandler( [this,cb](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { - if (args->Role == AudioDeviceRole::Default) - cb(args->Id->Data()); + if(args->Role == AudioDeviceRole::Default) + { + const std::string msg{"Default capture device changed: "+ + wstr_to_utf8(args->Id->Data())}; + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, + msg); + } }); #else HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, @@ -370,10 +380,20 @@ public: STDMETHODIMP OnPropertyValueChanged(LPCWSTR /*pwstrDeviceId*/, const PROPERTYKEY /*key*/) noexcept override { return S_OK; } STDMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) noexcept override { - if(role == eMultimedia && (flow == eRender || flow == eCapture)) + if(role != eMultimedia) + return S_OK; + + if(flow == eRender) + { + const std::string msg{"Default playback device changed: "+ + wstr_to_utf8(pwstrDefaultDeviceId)}; + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, msg); + } + else if(flow == eCapture) { - const std::string msg{"Default device changed: "+wstr_to_utf8(pwstrDefaultDeviceId)}; - alc::Event(alc::EventType::DefaultDeviceChanged, msg); + const std::string msg{"Default capture device changed: "+ + wstr_to_utf8(pwstrDefaultDeviceId)}; + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, msg); } return S_OK; } diff --git a/alc/events.cpp b/alc/events.cpp index 3c9c59ee..b5b65cb1 100644 --- a/alc/events.cpp +++ b/alc/events.cpp @@ -40,17 +40,17 @@ ALCenum EnumFromEventType(const alc::EventType type) namespace alc { -void Event(EventType eventType, ALCdevice *device, std::string_view message) noexcept +void Event(EventType eventType, DeviceType deviceType, ALCdevice *device, std::string_view message) noexcept { auto eventlock = std::unique_lock{EventMutex}; if(EventCallback && EventsEnabled.test(al::to_underlying(eventType))) - EventCallback(EnumFromEventType(eventType), device, + EventCallback(EnumFromEventType(eventType), al::to_underlying(deviceType), device, static_cast(message.length()), message.data(), EventUserPtr); } } // namespace alc -FORCE_ALIGN ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *types, +FORCE_ALIGN ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *events, ALCboolean enable) noexcept { if(enable != ALC_FALSE && enable != ALC_TRUE) @@ -65,14 +65,14 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const AL } if(count == 0) return ALC_TRUE; - if(!types) + if(!events) { alcSetError(nullptr, ALC_INVALID_VALUE); return ALC_FALSE; } std::bitset eventSet{0}; - for(ALCenum type : al::span{types, static_cast(count)}) + for(ALCenum type : al::span{events, static_cast(count)}) { auto etype = GetEventType(type); if(!etype) diff --git a/alc/events.h b/alc/events.h index 3b22a4c4..ddb3808a 100644 --- a/alc/events.h +++ b/alc/events.h @@ -19,6 +19,11 @@ enum class EventType : uint8_t { Count }; +enum class DeviceType : ALCenum { + Playback = ALC_PLAYBACK_DEVICE_SOFT, + Capture = ALC_CAPTURE_DEVICE_SOFT, +}; + inline std::bitset EventsEnabled{0}; inline std::mutex EventMutex; @@ -26,10 +31,10 @@ inline std::mutex EventMutex; inline ALCEVENTPROCTYPESOFT EventCallback{}; inline void *EventUserPtr{}; -void Event(alc::EventType eventType, ALCdevice *device, std::string_view message) noexcept; +void Event(EventType eventType, DeviceType deviceType, ALCdevice *device, std::string_view message) noexcept; -inline void Event(alc::EventType eventType, std::string_view message) noexcept -{ Event(eventType, nullptr, message); } +inline void Event(EventType eventType, DeviceType deviceType, std::string_view message) noexcept +{ Event(eventType, deviceType, nullptr, message); } } // namespace alc diff --git a/alc/inprogext.h b/alc/inprogext.h index 7cf49868..65e34ea4 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -445,15 +445,17 @@ ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, AL #ifndef ALC_SOFT_system_events #define ALC_SOFT_system_events -#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19CF -#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D0 -#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D1 -typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCdevice *device, - ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17; -typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *types, ALCboolean enable) ALC_API_NOEXCEPT17; +#define ALC_PLAYBACK_DEVICE_SOFT 0x19CF +#define ALC_CAPTURE_DEVICE_SOFT 0x19D0 +#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D1 +#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D2 +#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D3 +typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCenum deviceType, + ALCdevice *device, ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT17; typedef void (ALC_APIENTRY*LPALCEVENTCALLBACKSOFT)(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES -ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *types, ALCboolean enable) ALC_API_NOEXCEPT; +ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT; void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT; #endif #endif -- cgit v1.2.3 From 650a14631226b1b9423c961b1f53b5db673cc88f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 1 Jun 2023 17:07:25 -0700 Subject: Define FORCE_ALIGN in config.h --- CMakeLists.txt | 2 ++ alc/alc.cpp | 12 +++++++++--- common/threads.h | 13 ------------- config.h.in | 3 +++ 4 files changed, 14 insertions(+), 16 deletions(-) (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index ae21a83e..e4d3776d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -470,6 +470,7 @@ if(ALSOFT_REQUIRE_NEON AND NOT HAVE_NEON) endif() +set(ALSOFT_FORCE_ALIGN ) set(SSE_FLAGS ) set(FPMATH_SET "0") if(CMAKE_SIZEOF_VOID_P MATCHES "4" AND HAVE_SSE2) @@ -494,6 +495,7 @@ if(CMAKE_SIZEOF_VOID_P MATCHES "4" AND HAVE_SSE2) # OSs don't guarantee this on 32-bit, so externally-callable # functions need to ensure an aligned stack. set(EXPORT_DECL "${EXPORT_DECL}__attribute__((force_align_arg_pointer))") + set(ALSOFT_FORCE_ALIGN "__attribute__((force_align_arg_pointer))") endif() endif() endif() diff --git a/alc/alc.cpp b/alc/alc.cpp index 299a1ee9..128b3d7e 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -3228,11 +3228,17 @@ ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device * Renders some samples into a buffer, using the format last set by the * attributes given to alcCreateContext. */ -FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) noexcept +#if defined(__GNUC__) && defined(__i386__) +/* Needed on x86-32 even without SSE codegen, since the mixer may still use SSE + * and GCC assumes the stack is aligned (x86-64 ABI guarantees alignment). + */ +[[gnu::force_align_arg_pointer]] +#endif +ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) noexcept { - if(!device || device->Type != DeviceType::Loopback) + if(!device || device->Type != DeviceType::Loopback) UNLIKELY alcSetError(device, ALC_INVALID_DEVICE); - else if(samples < 0 || (samples > 0 && buffer == nullptr)) + else if(samples < 0 || (samples > 0 && buffer == nullptr)) UNLIKELY alcSetError(device, ALC_INVALID_VALUE); else device->renderSamples(buffer, static_cast(samples), device->channelsFromFmt()); diff --git a/common/threads.h b/common/threads.h index 62d80828..1ef037bb 100644 --- a/common/threads.h +++ b/common/threads.h @@ -1,19 +1,6 @@ #ifndef AL_THREADS_H #define AL_THREADS_H -#if defined(__GNUC__) && defined(__i386__) -/* force_align_arg_pointer may be required for proper stack alignment when SSE - * code is used. GCC generates code with the assumption the stack pointer is - * suitably aligned, while some systems (Windows, QNX) do not guarantee non- - * exported functions will be properly aligned when called externally, and - * older apps for other systems may have been built with a lower stack - * alignment than expected by newer builds. - */ -#define FORCE_ALIGN __attribute__((force_align_arg_pointer)) -#else -#define FORCE_ALIGN -#endif - #if defined(__APPLE__) #include #include diff --git a/config.h.in b/config.h.in index d1cf0395..20df5b46 100644 --- a/config.h.in +++ b/config.h.in @@ -1,3 +1,6 @@ +/* Define the alignment attribute for externally callable functions. */ +#define FORCE_ALIGN @ALSOFT_FORCE_ALIGN@ + /* Define if deprecated EAX extensions are enabled */ #cmakedefine ALSOFT_EAX -- cgit v1.2.3 From c200eb73a7cf47dbd1a4a3785be471adfb3513d8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 1 Jun 2023 17:31:31 -0700 Subject: Move althrd_setname to its own source --- CMakeLists.txt | 2 ++ alc/backends/alsa.cpp | 2 +- alc/backends/dsound.cpp | 2 +- alc/backends/jack.cpp | 1 + alc/backends/null.cpp | 4 +-- alc/backends/opensl.cpp | 1 + alc/backends/oss.cpp | 2 +- alc/backends/sndio.cpp | 2 +- alc/backends/solaris.cpp | 2 +- alc/backends/wasapi.cpp | 2 +- alc/backends/wave.cpp | 2 +- alc/backends/winmm.cpp | 1 + common/althrd_setname.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++++++ common/althrd_setname.h | 6 ++++ common/threads.cpp | 66 ---------------------------------------- common/threads.h | 2 -- 16 files changed, 96 insertions(+), 77 deletions(-) create mode 100644 common/althrd_setname.cpp create mode 100644 common/althrd_setname.h (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index e4d3776d..63a213c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -621,6 +621,8 @@ set(COMMON_OBJS common/alspan.h common/alstring.cpp common/alstring.h + common/althrd_setname.cpp + common/althrd_setname.h common/altraits.h common/atomic.h common/comptr.h diff --git a/alc/backends/alsa.cpp b/alc/backends/alsa.cpp index ce368f5e..83eef183 100644 --- a/alc/backends/alsa.cpp +++ b/alc/backends/alsa.cpp @@ -41,12 +41,12 @@ #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" +#include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "dynload.h" #include "ringbuffer.h" -#include "threads.h" #include diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index 5fc8a1c7..54fac898 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -47,6 +47,7 @@ #include "albit.h" #include "alnumeric.h" #include "alspan.h" +#include "althrd_setname.h" #include "comptr.h" #include "core/device.h" #include "core/helpers.h" @@ -54,7 +55,6 @@ #include "dynload.h" #include "ringbuffer.h" #include "strutils.h" -#include "threads.h" /* MinGW-w64 needs this for some unknown reason now. */ using LPCWAVEFORMATEX = const WAVEFORMATEX*; diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp index 9e023e21..b8325b05 100644 --- a/alc/backends/jack.cpp +++ b/alc/backends/jack.cpp @@ -35,6 +35,7 @@ #include "albit.h" #include "alc/alconfig.h" #include "alnumeric.h" +#include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" diff --git a/alc/backends/null.cpp b/alc/backends/null.cpp index 5a8fc255..73420ad3 100644 --- a/alc/backends/null.cpp +++ b/alc/backends/null.cpp @@ -30,10 +30,10 @@ #include #include -#include "core/device.h" +#include "althrd_setname.h" #include "almalloc.h" +#include "core/device.h" #include "core/helpers.h" -#include "threads.h" namespace { diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp index c9053816..a3b70791 100644 --- a/alc/backends/opensl.cpp +++ b/alc/backends/opensl.cpp @@ -35,6 +35,7 @@ #include "albit.h" #include "alnumeric.h" +#include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" diff --git a/alc/backends/oss.cpp b/alc/backends/oss.cpp index dc18c4c3..554ccc24 100644 --- a/alc/backends/oss.cpp +++ b/alc/backends/oss.cpp @@ -43,11 +43,11 @@ #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" +#include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "ringbuffer.h" -#include "threads.h" #include diff --git a/alc/backends/sndio.cpp b/alc/backends/sndio.cpp index 2040dd3a..84c54c62 100644 --- a/alc/backends/sndio.cpp +++ b/alc/backends/sndio.cpp @@ -32,11 +32,11 @@ #include #include "alnumeric.h" +#include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "ringbuffer.h" -#include "threads.h" #include diff --git a/alc/backends/solaris.cpp b/alc/backends/solaris.cpp index ae87e7eb..15dcc98f 100644 --- a/alc/backends/solaris.cpp +++ b/alc/backends/solaris.cpp @@ -41,10 +41,10 @@ #include #include "alc/alconfig.h" +#include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" -#include "threads.h" #include diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 32a4334d..2b88aa96 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -61,6 +61,7 @@ #include "alc/events.h" #include "alnumeric.h" #include "alspan.h" +#include "althrd_setname.h" #include "comptr.h" #include "core/converter.h" #include "core/device.h" @@ -68,7 +69,6 @@ #include "core/logging.h" #include "ringbuffer.h" #include "strutils.h" -#include "threads.h" #if defined(ALSOFT_UWP) #include diff --git a/alc/backends/wave.cpp b/alc/backends/wave.cpp index 1ee2fe51..40592ee7 100644 --- a/alc/backends/wave.cpp +++ b/alc/backends/wave.cpp @@ -38,12 +38,12 @@ #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" +#include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "opthelpers.h" #include "strutils.h" -#include "threads.h" namespace { diff --git a/alc/backends/winmm.cpp b/alc/backends/winmm.cpp index 0345fe10..fa5bf22a 100644 --- a/alc/backends/winmm.cpp +++ b/alc/backends/winmm.cpp @@ -39,6 +39,7 @@ #include #include "alnumeric.h" +#include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" diff --git a/common/althrd_setname.cpp b/common/althrd_setname.cpp new file mode 100644 index 00000000..22d33092 --- /dev/null +++ b/common/althrd_setname.cpp @@ -0,0 +1,76 @@ + +#include "config.h" + +#include "althrd_setname.h" + + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +void althrd_setname(const char *name [[maybe_unused]]) +{ +#if defined(_MSC_VER) && !defined(_M_ARM) + +#define MS_VC_EXCEPTION 0x406D1388 +#pragma pack(push,8) + struct { + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. + } info; +#pragma pack(pop) + info.dwType = 0x1000; + info.szName = name; + info.dwThreadID = ~DWORD{0}; + info.dwFlags = 0; + + /* FIXME: How to do this on MinGW? */ + __try { + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except(EXCEPTION_CONTINUE_EXECUTION) { + } +#undef MS_VC_EXCEPTION +#endif +} + +#else + +#include +#ifdef HAVE_PTHREAD_NP_H +#include +#endif + +namespace { + +using setname_t1 = int(*)(const char*); +using setname_t2 = int(*)(pthread_t, const char*); +using setname_t3 = void(*)(pthread_t, const char*); +using setname_t4 = int(*)(pthread_t, const char*, void*); + +[[maybe_unused]] void setname_caller(setname_t1 func, const char *name) +{ func(name); } + +[[maybe_unused]] void setname_caller(setname_t2 func, const char *name) +{ func(pthread_self(), name); } + +[[maybe_unused]] void setname_caller(setname_t3 func, const char *name) +{ func(pthread_self(), name); } + +[[maybe_unused]] void setname_caller(setname_t4 func, const char *name) +{ func(pthread_self(), "%s", static_cast(const_cast(name))); } + +} // namespace + +void althrd_setname(const char *name [[maybe_unused]]) +{ +#if defined(HAVE_PTHREAD_SET_NAME_NP) + setname_caller(pthread_set_name_np, name); +#elif defined(HAVE_PTHREAD_SETNAME_NP) + setname_caller(pthread_setname_np, name); +#endif +} + +#endif diff --git a/common/althrd_setname.h b/common/althrd_setname.h new file mode 100644 index 00000000..0e22c0a9 --- /dev/null +++ b/common/althrd_setname.h @@ -0,0 +1,6 @@ +#ifndef COMMON_ALTHRD_SETNAME_H +#define COMMON_ALTHRD_SETNAME_H + +void althrd_setname(const char *name); + +#endif /* COMMON_ALTHRD_SETNAME_H */ diff --git a/common/threads.cpp b/common/threads.cpp index c1d9e8b0..c176f5af 100644 --- a/common/threads.cpp +++ b/common/threads.cpp @@ -32,37 +32,6 @@ #include -void althrd_setname(const char *name) -{ -#if defined(_MSC_VER) && !defined(_M_ARM) - -#define MS_VC_EXCEPTION 0x406D1388 -#pragma pack(push,8) - struct { - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. - } info; -#pragma pack(pop) - info.dwType = 0x1000; - info.szName = name; - info.dwThreadID = ~DWORD{0}; - info.dwFlags = 0; - - __try { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); - } - __except(EXCEPTION_CONTINUE_EXECUTION) { - } -#undef MS_VC_EXCEPTION - -#else - - (void)name; -#endif -} - namespace al { semaphore::semaphore(unsigned int initial) @@ -93,41 +62,6 @@ bool semaphore::try_wait() noexcept #else -#include -#ifdef HAVE_PTHREAD_NP_H -#include -#endif - -namespace { - -using setname_t1 = int(*)(const char*); -using setname_t2 = int(*)(pthread_t, const char*); -using setname_t3 = void(*)(pthread_t, const char*); -using setname_t4 = int(*)(pthread_t, const char*, void*); - -[[maybe_unused]] void setname_caller(setname_t1 func, const char *name) -{ func(name); } - -[[maybe_unused]] void setname_caller(setname_t2 func, const char *name) -{ func(pthread_self(), name); } - -[[maybe_unused]] void setname_caller(setname_t3 func, const char *name) -{ func(pthread_self(), name); } - -[[maybe_unused]] void setname_caller(setname_t4 func, const char *name) -{ func(pthread_self(), "%s", static_cast(const_cast(name))); } - -} // namespace - -void althrd_setname(const char *name [[maybe_unused]]) -{ -#if defined(HAVE_PTHREAD_SET_NAME_NP) - setname_caller(pthread_set_name_np, name); -#elif defined(HAVE_PTHREAD_SETNAME_NP) - setname_caller(pthread_setname_np, name); -#endif -} - /* Do not try using libdispatch on systems where it is absent. */ #if defined(AL_APPLE_HAVE_DISPATCH) diff --git a/common/threads.h b/common/threads.h index 1ef037bb..703d50d4 100644 --- a/common/threads.h +++ b/common/threads.h @@ -14,8 +14,6 @@ #include #endif -void althrd_setname(const char *name); - namespace al { class semaphore { -- cgit v1.2.3 From 2b7ab0b75086f3d73a7ffe9bc05a80e5d9c625f5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 1 Jun 2023 18:16:17 -0700 Subject: Rename threads.cpp/h to alsem.cpp/h --- CMakeLists.txt | 4 +- al/debug.cpp | 1 - al/event.cpp | 1 - al/source.cpp | 1 - alc/alc.cpp | 1 - alc/alu.cpp | 1 - alc/backends/jack.cpp | 2 +- alc/backends/opensl.cpp | 2 +- alc/backends/winmm.cpp | 2 +- alc/context.cpp | 1 - alc/events.cpp | 1 - common/alsem.cpp | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ common/alsem.h | 43 +++++++++++++++++ common/threads.cpp | 125 ----------------------------------------------- common/threads.h | 43 ----------------- core/context.h | 2 +- 16 files changed, 175 insertions(+), 181 deletions(-) create mode 100644 common/alsem.cpp create mode 100644 common/alsem.h delete mode 100644 common/threads.cpp delete mode 100644 common/threads.h (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index 63a213c9..c73dee55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -618,6 +618,8 @@ set(COMMON_OBJS common/almalloc.h common/alnumbers.h common/alnumeric.h + common/alsem.cpp + common/alsem.h common/alspan.h common/alstring.cpp common/alstring.h @@ -638,8 +640,6 @@ set(COMMON_OBJS common/ringbuffer.h common/strutils.cpp common/strutils.h - common/threads.cpp - common/threads.h common/vecmat.h common/vector.h) diff --git a/al/debug.cpp b/al/debug.cpp index 56705c65..af67859a 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -20,7 +20,6 @@ #include "core/logging.h" #include "direct_defs.h" #include "opthelpers.h" -#include "threads.h" namespace { diff --git a/al/event.cpp b/al/event.cpp index a5b5fdc5..ef58f86d 100644 --- a/al/event.cpp +++ b/al/event.cpp @@ -30,7 +30,6 @@ #include "direct_defs.h" #include "opthelpers.h" #include "ringbuffer.h" -#include "threads.h" namespace { diff --git a/al/source.cpp b/al/source.cpp index 8dbbbcd8..8f4d4d48 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -73,7 +73,6 @@ #include "filter.h" #include "opthelpers.h" #include "ringbuffer.h" -#include "threads.h" #ifdef ALSOFT_EAX #include diff --git a/alc/alc.cpp b/alc/alc.cpp index 128b3d7e..48fa19ec 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -103,7 +103,6 @@ #include "intrusive_ptr.h" #include "opthelpers.h" #include "strutils.h" -#include "threads.h" #include "backends/base.h" #include "backends/null.h" diff --git a/alc/alu.cpp b/alc/alu.cpp index c43da639..0130f280 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -77,7 +77,6 @@ #include "opthelpers.h" #include "ringbuffer.h" #include "strutils.h" -#include "threads.h" #include "vecmat.h" #include "vector.h" diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp index b8325b05..66fc0877 100644 --- a/alc/backends/jack.cpp +++ b/alc/backends/jack.cpp @@ -35,13 +35,13 @@ #include "albit.h" #include "alc/alconfig.h" #include "alnumeric.h" +#include "alsem.h" #include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "dynload.h" #include "ringbuffer.h" -#include "threads.h" #include #include diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp index a3b70791..2a161056 100644 --- a/alc/backends/opensl.cpp +++ b/alc/backends/opensl.cpp @@ -35,13 +35,13 @@ #include "albit.h" #include "alnumeric.h" +#include "alsem.h" #include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "opthelpers.h" #include "ringbuffer.h" -#include "threads.h" #include #include diff --git a/alc/backends/winmm.cpp b/alc/backends/winmm.cpp index fa5bf22a..661585cd 100644 --- a/alc/backends/winmm.cpp +++ b/alc/backends/winmm.cpp @@ -39,13 +39,13 @@ #include #include "alnumeric.h" +#include "alsem.h" #include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "ringbuffer.h" #include "strutils.h" -#include "threads.h" #ifndef WAVE_FORMAT_IEEE_FLOAT #define WAVE_FORMAT_IEEE_FLOAT 0x0003 diff --git a/alc/context.cpp b/alc/context.cpp index bcd72f92..142ad50c 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -33,7 +33,6 @@ #include "core/voice_change.h" #include "device.h" #include "ringbuffer.h" -#include "threads.h" #include "vecmat.h" #ifdef ALSOFT_EAX diff --git a/alc/events.cpp b/alc/events.cpp index b5b65cb1..b14b1a8d 100644 --- a/alc/events.cpp +++ b/alc/events.cpp @@ -6,7 +6,6 @@ #include #include "alspan.h" -#include "common/threads.h" #include "core/logging.h" #include "device.h" diff --git a/common/alsem.cpp b/common/alsem.cpp new file mode 100644 index 00000000..6a92b35c --- /dev/null +++ b/common/alsem.cpp @@ -0,0 +1,126 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 1999-2007 by authors. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include "alsem.h" + +#include + +#include "opthelpers.h" + + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +#include + +namespace al { + +semaphore::semaphore(unsigned int initial) +{ + if(initial > static_cast(std::numeric_limits::max())) + throw std::system_error(std::make_error_code(std::errc::value_too_large)); + mSem = CreateSemaphore(nullptr, initial, std::numeric_limits::max(), nullptr); + if(mSem == nullptr) + throw std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again)); +} + +semaphore::~semaphore() +{ CloseHandle(mSem); } + +void semaphore::post() +{ + if(!ReleaseSemaphore(static_cast(mSem), 1, nullptr)) + throw std::system_error(std::make_error_code(std::errc::value_too_large)); +} + +void semaphore::wait() noexcept +{ WaitForSingleObject(static_cast(mSem), INFINITE); } + +bool semaphore::try_wait() noexcept +{ return WaitForSingleObject(static_cast(mSem), 0) == WAIT_OBJECT_0; } + +} // namespace al + +#else + +/* Do not try using libdispatch on systems where it is absent. */ +#if defined(AL_APPLE_HAVE_DISPATCH) + +namespace al { + +semaphore::semaphore(unsigned int initial) +{ + mSem = dispatch_semaphore_create(initial); + if(!mSem) + throw std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again)); +} + +semaphore::~semaphore() +{ dispatch_release(mSem); } + +void semaphore::post() +{ dispatch_semaphore_signal(mSem); } + +void semaphore::wait() noexcept +{ dispatch_semaphore_wait(mSem, DISPATCH_TIME_FOREVER); } + +bool semaphore::try_wait() noexcept +{ return dispatch_semaphore_wait(mSem, DISPATCH_TIME_NOW) == 0; } + +} // namespace al + +#else /* !__APPLE__ */ + +#include + +namespace al { + +semaphore::semaphore(unsigned int initial) +{ + if(sem_init(&mSem, 0, initial) != 0) + throw std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again)); +} + +semaphore::~semaphore() +{ sem_destroy(&mSem); } + +void semaphore::post() +{ + if(sem_post(&mSem) != 0) + throw std::system_error(std::make_error_code(std::errc::value_too_large)); +} + +void semaphore::wait() noexcept +{ + while(sem_wait(&mSem) == -1 && errno == EINTR) { + } +} + +bool semaphore::try_wait() noexcept +{ return sem_trywait(&mSem) == 0; } + +} // namespace al + +#endif /* __APPLE__ */ + +#endif /* _WIN32 */ diff --git a/common/alsem.h b/common/alsem.h new file mode 100644 index 00000000..9f72d1c6 --- /dev/null +++ b/common/alsem.h @@ -0,0 +1,43 @@ +#ifndef COMMON_ALSEM_H +#define COMMON_ALSEM_H + +#if defined(__APPLE__) +#include +#include +#if (((MAC_OS_X_VERSION_MIN_REQUIRED > 1050) && !defined(__ppc__)) || TARGET_OS_IOS || TARGET_OS_TV) +#include +#define AL_APPLE_HAVE_DISPATCH 1 +#else +#include /* Fallback option for Apple without a working libdispatch */ +#endif +#elif !defined(_WIN32) +#include +#endif + +namespace al { + +class semaphore { +#ifdef _WIN32 + using native_type = void*; +#elif defined(AL_APPLE_HAVE_DISPATCH) + using native_type = dispatch_semaphore_t; +#else + using native_type = sem_t; +#endif + native_type mSem; + +public: + semaphore(unsigned int initial=0); + semaphore(const semaphore&) = delete; + ~semaphore(); + + semaphore& operator=(const semaphore&) = delete; + + void post(); + void wait() noexcept; + bool try_wait() noexcept; +}; + +} // namespace al + +#endif /* COMMON_ALSEM_H */ diff --git a/common/threads.cpp b/common/threads.cpp deleted file mode 100644 index c176f5af..00000000 --- a/common/threads.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include "opthelpers.h" -#include "threads.h" - -#include - - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include - -#include - -namespace al { - -semaphore::semaphore(unsigned int initial) -{ - if(initial > static_cast(std::numeric_limits::max())) - throw std::system_error(std::make_error_code(std::errc::value_too_large)); - mSem = CreateSemaphore(nullptr, initial, std::numeric_limits::max(), nullptr); - if(mSem == nullptr) - throw std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again)); -} - -semaphore::~semaphore() -{ CloseHandle(mSem); } - -void semaphore::post() -{ - if(!ReleaseSemaphore(static_cast(mSem), 1, nullptr)) - throw std::system_error(std::make_error_code(std::errc::value_too_large)); -} - -void semaphore::wait() noexcept -{ WaitForSingleObject(static_cast(mSem), INFINITE); } - -bool semaphore::try_wait() noexcept -{ return WaitForSingleObject(static_cast(mSem), 0) == WAIT_OBJECT_0; } - -} // namespace al - -#else - -/* Do not try using libdispatch on systems where it is absent. */ -#if defined(AL_APPLE_HAVE_DISPATCH) - -namespace al { - -semaphore::semaphore(unsigned int initial) -{ - mSem = dispatch_semaphore_create(initial); - if(!mSem) - throw std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again)); -} - -semaphore::~semaphore() -{ dispatch_release(mSem); } - -void semaphore::post() -{ dispatch_semaphore_signal(mSem); } - -void semaphore::wait() noexcept -{ dispatch_semaphore_wait(mSem, DISPATCH_TIME_FOREVER); } - -bool semaphore::try_wait() noexcept -{ return dispatch_semaphore_wait(mSem, DISPATCH_TIME_NOW) == 0; } - -} // namespace al - -#else /* !__APPLE__ */ - -#include - -namespace al { - -semaphore::semaphore(unsigned int initial) -{ - if(sem_init(&mSem, 0, initial) != 0) - throw std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again)); -} - -semaphore::~semaphore() -{ sem_destroy(&mSem); } - -void semaphore::post() -{ - if(sem_post(&mSem) != 0) - throw std::system_error(std::make_error_code(std::errc::value_too_large)); -} - -void semaphore::wait() noexcept -{ - while(sem_wait(&mSem) == -1 && errno == EINTR) { - } -} - -bool semaphore::try_wait() noexcept -{ return sem_trywait(&mSem) == 0; } - -} // namespace al - -#endif /* __APPLE__ */ - -#endif /* _WIN32 */ diff --git a/common/threads.h b/common/threads.h deleted file mode 100644 index 703d50d4..00000000 --- a/common/threads.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef AL_THREADS_H -#define AL_THREADS_H - -#if defined(__APPLE__) -#include -#include -#if (((MAC_OS_X_VERSION_MIN_REQUIRED > 1050) && !defined(__ppc__)) || TARGET_OS_IOS || TARGET_OS_TV) -#include -#define AL_APPLE_HAVE_DISPATCH 1 -#else -#include /* Fallback option for Apple without a working libdispatch */ -#endif -#elif !defined(_WIN32) -#include -#endif - -namespace al { - -class semaphore { -#ifdef _WIN32 - using native_type = void*; -#elif defined(AL_APPLE_HAVE_DISPATCH) - using native_type = dispatch_semaphore_t; -#else - using native_type = sem_t; -#endif - native_type mSem; - -public: - semaphore(unsigned int initial=0); - semaphore(const semaphore&) = delete; - ~semaphore(); - - semaphore& operator=(const semaphore&) = delete; - - void post(); - void wait() noexcept; - bool try_wait() noexcept; -}; - -} // namespace al - -#endif /* AL_THREADS_H */ diff --git a/core/context.h b/core/context.h index 629e67a5..ccb7dd3b 100644 --- a/core/context.h +++ b/core/context.h @@ -10,11 +10,11 @@ #include #include "almalloc.h" +#include "alsem.h" #include "alspan.h" #include "async_event.h" #include "atomic.h" #include "opthelpers.h" -#include "threads.h" #include "vecmat.h" struct DeviceBase; -- cgit v1.2.3 From 6752d5516c8b30fe7db559c7f3a1423705d2a4fd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 1 Jun 2023 19:05:57 -0700 Subject: Use cinttypes instead of inttypes.h in C++ --- al/source.cpp | 2 +- alc/backends/coreaudio.cpp | 2 +- alc/backends/sndio.cpp | 2 +- utils/uhjencoder.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'alc') diff --git a/al/source.cpp b/al/source.cpp index 8f4d4d48..7e425d43 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -27,11 +27,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index 1e8423b7..c2888e42 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -22,8 +22,8 @@ #include "coreaudio.h" +#include #include -#include #include #include #include diff --git a/alc/backends/sndio.cpp b/alc/backends/sndio.cpp index 84c54c62..89eee941 100644 --- a/alc/backends/sndio.cpp +++ b/alc/backends/sndio.cpp @@ -22,8 +22,8 @@ #include "sndio.h" +#include #include -#include #include #include #include diff --git a/utils/uhjencoder.cpp b/utils/uhjencoder.cpp index c381d1b9..91e4dbd0 100644 --- a/utils/uhjencoder.cpp +++ b/utils/uhjencoder.cpp @@ -25,8 +25,8 @@ #include "config.h" #include +#include #include -#include #include #include #include -- cgit v1.2.3 From 75cbbd0c02be29e2cd6a5b735306158d21765e38 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 1 Jun 2023 22:33:50 -0700 Subject: Remove an unused lambda --- alc/backends/wasapi.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 2b88aa96..a554d1b4 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -237,15 +237,9 @@ public: #if defined(ALSOFT_UWP) mActiveClientEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr); - auto cb = [](alc::DeviceType type, const WCHAR *devid) - { - const std::string msg{"Default device changed: "+wstr_to_utf8(devid)}; - alc::Event(alc::EventType::DefaultDeviceChanged, type, msg); - }; - mRenderDeviceChangedToken = MediaDevice::DefaultAudioRenderDeviceChanged += ref new TypedEventHandler( - [this,cb](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { + [this](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { if(args->Role == AudioDeviceRole::Default) { const std::string msg{"Default playback device changed: "+ @@ -256,7 +250,7 @@ public: }); mCaptureDeviceChangedToken = MediaDevice::DefaultAudioCaptureDeviceChanged += ref new TypedEventHandler( - [this,cb](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { + [this](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { if(args->Role == AudioDeviceRole::Default) { const std::string msg{"Default capture device changed: "+ -- cgit v1.2.3 From e2ce51764e42154c7aa33eb9f53592e85f877255 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 2 Jun 2023 19:10:24 -0700 Subject: Don't initialize in alcGetProcAddress or alcGetEnumValue --- alc/alc.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index 48fa19ec..e6c2f137 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2575,7 +2575,6 @@ ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar return nullptr; } - InitConfig(); #ifdef ALSOFT_EAX if(eax_g_is_enabled) { @@ -2604,7 +2603,6 @@ ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *e return 0; } - InitConfig(); #ifdef ALSOFT_EAX if(eax_g_is_enabled) { -- cgit v1.2.3 From d769041916df4efb48fd212683dc9842decc10f1 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 2 Jun 2023 19:12:48 -0700 Subject: Start the WASAPI COM thread when initializing the backend COM doesn't make this easy. We want to be able to get device change notifications without an open device, but we need an IMMDeviceEnumerator object to register the notification client, which requires COM to be initialized. COM must then stay initialized while we have the IMMDeviceEnumerator object, which we can't assume for the calling thread so it has to be done in the COM thread. Consequently, the COM thread must stay alive and can't quit while the DLL is loaded if we want to get those notifications without an open device, and as there's no reliable way to make the thread quit during DLL unload, the DLL must stay pinned until process exit. --- alc/backends/wasapi.cpp | 163 +++++++++++------------------------------------- 1 file changed, 38 insertions(+), 125 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index a554d1b4..333c0dc7 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -222,7 +222,6 @@ struct DeviceHandle using EventRegistrationToken = Windows::Foundation::EventRegistrationToken; #else using DeviceHandle = ComPtr; -using EventRegistrationToken = void*; #endif #if defined(ALSOFT_UWP) @@ -231,7 +230,6 @@ struct DeviceHelper final : public IActivateAudioInterfaceCompletionHandler struct DeviceHelper final : private IMMNotificationClient #endif { -public: DeviceHelper() { #if defined(ALSOFT_UWP) @@ -259,13 +257,6 @@ public: msg); } }); -#else - HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, al::out_ptr(mEnumerator))}; - if(SUCCEEDED(hr)) - mEnumerator->RegisterEndpointNotificationCallback(this); - else - WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); #endif } ~DeviceHelper() @@ -287,13 +278,7 @@ public: /** -------------------------- IUnkonwn ----------------------------- */ std::atomic mRefCount{1}; STDMETHODIMP_(ULONG) AddRef() noexcept override { return mRefCount.fetch_add(1u) + 1u; } - - STDMETHODIMP_(ULONG) Release() noexcept override - { - auto ret = mRefCount.fetch_sub(1u) - 1u; - if(!ret) delete this; - return ret; - } + STDMETHODIMP_(ULONG) Release() noexcept override { return mRefCount.fetch_sub(1u) - 1u; } STDMETHODIMP QueryInterface(const IID& IId, void **UnknownPtrPtr) noexcept override { @@ -394,7 +379,22 @@ public: #endif /** -------------------------- DeviceHelper ----------------------------- */ - HRESULT OpenDevice(LPCWSTR devid, EDataFlow flow, DeviceHandle& device) + HRESULT init() + { +#if !defined(ALSOFT_UWP) + HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, + IID_IMMDeviceEnumerator, al::out_ptr(mEnumerator))}; + if(SUCCEEDED(hr)) + mEnumerator->RegisterEndpointNotificationCallback(this); + else + WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); + return hr; +#else + return S_OK; +#endif + } + + HRESULT openDevice(LPCWSTR devid, EDataFlow flow, DeviceHandle& device) { #if !defined(ALSOFT_UWP) HRESULT hr{E_POINTER}; @@ -425,7 +425,7 @@ public: #endif } - HRESULT ActivateAudioClient(_In_ DeviceHandle& device, void **ppv) + static HRESULT ActivateAudioClient(_In_ DeviceHandle& device, void **ppv) { #if !defined(ALSOFT_UWP) HRESULT hr{device->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER, nullptr, ppv)}; @@ -570,7 +570,6 @@ public: WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvprop->vt); guid = UnknownGuid; } - #else auto devInfo = device.value; std::string name = wstr_to_utf8(devInfo->Name->Data()); @@ -798,7 +797,7 @@ struct WasapiProxy { virtual HRESULT resetProxy() = 0; virtual HRESULT startProxy() = 0; - virtual void stopProxy() = 0; + virtual void stopProxy() = 0; struct Msg { MsgType mType; @@ -808,14 +807,11 @@ struct WasapiProxy { explicit operator bool() const noexcept { return mType != MsgType::QuitThread; } }; - static std::thread sThread; static std::deque mMsgQueue; static std::mutex mMsgQueueLock; static std::condition_variable mMsgQueueCond; - static std::mutex sThreadLock; - static size_t sInitCount; - static ComPtr sDeviceHelper; + static std::optional sDeviceHelper; std::future pushMessage(MsgType type, const char *param=nullptr) { @@ -851,45 +847,11 @@ struct WasapiProxy { } static int messageHandler(std::promise *promise); - - static HRESULT InitThread() - { - std::lock_guard _{sThreadLock}; - HRESULT res{S_OK}; - if(!sThread.joinable()) - { - std::promise promise; - auto future = promise.get_future(); - - sThread = std::thread{&WasapiProxy::messageHandler, &promise}; - res = future.get(); - if(FAILED(res)) - { - sThread.join(); - return res; - } - } - ++sInitCount; - return res; - } - - static void DeinitThread() - { - std::lock_guard _{sThreadLock}; - if(!--sInitCount && sThread.joinable()) - { - pushMessageStatic(MsgType::QuitThread); - sThread.join(); - } - } }; -std::thread WasapiProxy::sThread; std::deque WasapiProxy::mMsgQueue; std::mutex WasapiProxy::mMsgQueueLock; std::condition_variable WasapiProxy::mMsgQueueCond; -std::mutex WasapiProxy::sThreadLock; -ComPtr WasapiProxy::sDeviceHelper; -size_t WasapiProxy::sInitCount{0}; +std::optional WasapiProxy::sDeviceHelper; int WasapiProxy::messageHandler(std::promise *promise) { @@ -902,8 +864,12 @@ int WasapiProxy::messageHandler(std::promise *promise) promise->set_value(hr); return 0; } - promise->set_value(S_OK); + + hr = sDeviceHelper.emplace().init(); + promise->set_value(hr); promise = nullptr; + if(FAILED(hr)) + goto skip_loop; TRACE("Starting message loop\n"); while(Msg msg{popMessage()}) @@ -956,6 +922,9 @@ int WasapiProxy::messageHandler(std::promise *promise) msg.mPromise.set_value(E_FAIL); } TRACE("Message loop finished\n"); + +skip_loop: + sDeviceHelper.reset(); CoUninitialize(); return 0; @@ -1005,10 +974,7 @@ struct WasapiPlayback final : public BackendBase, WasapiProxy { WasapiPlayback::~WasapiPlayback() { if(SUCCEEDED(mOpenStatus)) - { pushMessage(MsgType::CloseDevice).wait(); - DeinitThread(); - } mOpenStatus = E_FAIL; if(mNotifyEvent != nullptr) @@ -1121,13 +1087,6 @@ void WasapiPlayback::open(const char *name) "Failed to create notify events"}; } - HRESULT hr{InitThread()}; - if(FAILED(hr)) - { - throw al::backend_exception{al::backend_error::DeviceError, - "Failed to init COM thread: 0x%08lx", hr}; - } - if(name) { if(PlaybackDevices.empty()) @@ -1142,11 +1101,8 @@ void WasapiPlayback::open(const char *name) mOpenStatus = pushMessage(MsgType::OpenDevice, name).get(); if(FAILED(mOpenStatus)) - { - DeinitThread(); throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: 0x%08lx", mOpenStatus}; - } } HRESULT WasapiPlayback::openProxy(const char *name) @@ -1173,14 +1129,14 @@ HRESULT WasapiPlayback::openProxy(const char *name) devid = iter->devid.c_str(); } - HRESULT hr{sDeviceHelper->OpenDevice(devid, eRender, mMMDev)}; - if (FAILED(hr)) + HRESULT hr{sDeviceHelper->openDevice(devid, eRender, mMMDev)}; + if(FAILED(hr)) { WARN("Failed to open device \"%s\"\n", name ? name : "(default)"); return hr; } mClient = nullptr; - if (name) + if(name) mDevice->DeviceName = std::string{DevNameHead} + name; else mDevice->DeviceName = DevNameHead + DeviceHelper::get_device_name_and_guid(mMMDev).first; @@ -1657,10 +1613,7 @@ struct WasapiCapture final : public BackendBase, WasapiProxy { WasapiCapture::~WasapiCapture() { if(SUCCEEDED(mOpenStatus)) - { pushMessage(MsgType::CloseDevice).wait(); - DeinitThread(); - } mOpenStatus = E_FAIL; if(mNotifyEvent != nullptr) @@ -1775,13 +1728,6 @@ void WasapiCapture::open(const char *name) "Failed to create notify events"}; } - HRESULT hr{InitThread()}; - if(FAILED(hr)) - { - throw al::backend_exception{al::backend_error::DeviceError, - "Failed to init COM thread: 0x%08lx", hr}; - } - if(name) { if(CaptureDevices.empty()) @@ -1796,13 +1742,10 @@ void WasapiCapture::open(const char *name) mOpenStatus = pushMessage(MsgType::OpenDevice, name).get(); if(FAILED(mOpenStatus)) - { - DeinitThread(); throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: 0x%08lx", mOpenStatus}; - } - hr = pushMessage(MsgType::ResetDevice).get(); + HRESULT hr{pushMessage(MsgType::ResetDevice).get()}; if(FAILED(hr)) { if(hr == E_OUTOFMEMORY) @@ -1835,7 +1778,7 @@ HRESULT WasapiCapture::openProxy(const char *name) devid = iter->devid.c_str(); } - HRESULT hr{sDeviceHelper->OpenDevice(devid, eCapture, mMMDev)}; + HRESULT hr{sDeviceHelper->openDevice(devid, eCapture, mMMDev)}; if (FAILED(hr)) { WARN("Failed to open device \"%s\"\n", name ? name : "(default)"); @@ -2210,34 +2153,13 @@ uint WasapiCapture::availableSamples() bool WasapiBackendFactory::init() { static HRESULT InitResult{E_FAIL}; - if(FAILED(InitResult)) try { - auto res = std::async(std::launch::async, []() -> HRESULT - { - HRESULT hr{CoInitializeEx(nullptr, COINIT_MULTITHREADED)}; - if(FAILED(hr)) - { - WARN("Failed to initialize COM: 0x%08lx\n", hr); - return hr; - } -#if !defined(ALSOFT_UWP) - ComPtr enumerator; - hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, al::out_ptr(enumerator)); - if(FAILED(hr)) - WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); - enumerator = nullptr; -#endif - if(SUCCEEDED(hr)) - WasapiProxy::sDeviceHelper.reset(new DeviceHelper{}); - - CoUninitialize(); - - return hr; - }); + std::promise promise; + auto future = promise.get_future(); - InitResult = res.get(); + std::thread{&WasapiProxy::messageHandler, &promise}.detach(); + InitResult = future.get(); } catch(...) { } @@ -2250,16 +2172,7 @@ bool WasapiBackendFactory::querySupport(BackendType type) std::string WasapiBackendFactory::probe(BackendType type) { - struct ProxyControl { - HRESULT mResult{}; - ProxyControl() { mResult = WasapiProxy::InitThread(); } - ~ProxyControl() { if(SUCCEEDED(mResult)) WasapiProxy::DeinitThread(); } - }; - ProxyControl proxy; - std::string outnames; - if(FAILED(proxy.mResult)) - return outnames; switch(type) { -- cgit v1.2.3 From cb7d5bc6d719c9114982e64c39caf2db7add9c58 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 2 Jun 2023 19:33:21 -0700 Subject: Fix comment typo --- alc/backends/wasapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 333c0dc7..4e67f7dd 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -275,7 +275,7 @@ struct DeviceHelper final : private IMMNotificationClient #endif } - /** -------------------------- IUnkonwn ----------------------------- */ + /** -------------------------- IUnknown ----------------------------- */ std::atomic mRefCount{1}; STDMETHODIMP_(ULONG) AddRef() noexcept override { return mRefCount.fetch_add(1u) + 1u; } STDMETHODIMP_(ULONG) Release() noexcept override { return mRefCount.fetch_sub(1u) - 1u; } -- cgit v1.2.3 From e7dafb65d73d2caf70a45776c5ffde9e38de4701 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 2 Jun 2023 19:50:03 -0700 Subject: Fix UWP builds --- alc/backends/wasapi.cpp | 46 ++++++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 26 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 4e67f7dd..66400681 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -425,16 +425,29 @@ struct DeviceHelper final : private IMMNotificationClient #endif } - static HRESULT ActivateAudioClient(_In_ DeviceHandle& device, void **ppv) - { #if !defined(ALSOFT_UWP) - HRESULT hr{device->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER, nullptr, ppv)}; + static HRESULT ActivateAudioClient(_In_ DeviceHandle& device, void **ppv) + { return device->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER, nullptr, ppv); } #else - HRESULT hr{ActivateAudioInterface(device.value->Id->Data(), __uuidof(IAudioClient3), - nullptr, ppv)}; -#endif - return hr; + HRESULT ActivateAudioClient(_In_ DeviceHandle& device, void **ppv) + { + ComPtr asyncOp; + mPPV = ppv; + HRESULT hr{ActivateAudioInterfaceAsync(deviceInterfacePath, riid, activationParams, this, + al::out_ptr(asyncOp))}; + if(FAILED(hr)) + return hr; + asyncOp = nullptr; + + DWORD res{WaitForSingleObjectEx(mActiveClientEvent, 2000, FALSE)}; + if(res != WAIT_OBJECT_0) + { + ERR("WaitForSingleObjectEx error: 0x%lx\n", res); + return E_FAIL; + } + return S_OK; } +#endif HRESULT probe_devices(EDataFlow flowdir, std::vector& list) { @@ -656,25 +669,6 @@ struct DeviceHelper final : private IMMNotificationClient private: #if defined(ALSOFT_UWP) - HRESULT ActivateAudioInterface(_In_ LPCWSTR deviceInterfacePath, - _In_ REFIID riid, - _In_opt_ PROPVARIANT* activationParams, - void** ppv) - { - IActivateAudioInterfaceAsyncOperation* asyncOp{nullptr}; - mPPV = ppv; - HRESULT hr = ActivateAudioInterfaceAsync(deviceInterfacePath, riid, activationParams, this, &asyncOp); - if(FAILED(hr)) - return hr; - if(asyncOp) - asyncOp->Release(); - - DWORD res{WaitForSingleObjectEx(mActiveClientEvent, 2000, FALSE)}; - if(res != WAIT_OBJECT_0) - ERR("WaitForSingleObjectEx error: 0x%lx\n", res); - return res; - } - HANDLE mActiveClientEvent{nullptr}; void** mPPV{nullptr}; -- cgit v1.2.3 From 4c9906284e2b47f79ebbacb6098ac7f619f2fc0f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 2 Jun 2023 20:23:52 -0700 Subject: Try again to fix UWP builds --- alc/backends/wasapi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 66400681..155f0413 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -433,8 +433,8 @@ struct DeviceHelper final : private IMMNotificationClient { ComPtr asyncOp; mPPV = ppv; - HRESULT hr{ActivateAudioInterfaceAsync(deviceInterfacePath, riid, activationParams, this, - al::out_ptr(asyncOp))}; + HRESULT hr{ActivateAudioInterfaceAsync(device.value->Id->Data(), __uuidof(IAudioClient3), + nullptr, this, al::out_ptr(asyncOp))}; if(FAILED(hr)) return hr; asyncOp = nullptr; -- cgit v1.2.3 From 045a4ff1448d1b8069ccc20d0f38edcbffbb8321 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 3 Jun 2023 21:26:05 -0700 Subject: Use the correct IID for the interface we use --- alc/backends/wasapi.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 155f0413..391976c8 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -426,15 +426,15 @@ struct DeviceHelper final : private IMMNotificationClient } #if !defined(ALSOFT_UWP) - static HRESULT ActivateAudioClient(_In_ DeviceHandle& device, void **ppv) - { return device->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER, nullptr, ppv); } + static HRESULT activateAudioClient(_In_ DeviceHandle& device, REFIID iid, void **ppv) + { return device->Activate(iid, CLSCTX_INPROC_SERVER, nullptr, ppv); } #else - HRESULT ActivateAudioClient(_In_ DeviceHandle& device, void **ppv) + HRESULT activateAudioClient(_In_ DeviceHandle& device, _In_ REFIID iid, void **ppv) { ComPtr asyncOp; mPPV = ppv; - HRESULT hr{ActivateAudioInterfaceAsync(device.value->Id->Data(), __uuidof(IAudioClient3), - nullptr, this, al::out_ptr(asyncOp))}; + HRESULT hr{ActivateAudioInterfaceAsync(device.value->Id->Data(), iid, nullptr, this, + al::out_ptr(asyncOp))}; if(FAILED(hr)) return hr; asyncOp = nullptr; @@ -1156,7 +1156,8 @@ bool WasapiPlayback::reset() HRESULT WasapiPlayback::resetProxy() { mClient = nullptr; - HRESULT hr{sDeviceHelper->ActivateAudioClient(mMMDev, al::out_ptr(mClient))}; + HRESULT hr{sDeviceHelper->activateAudioClient(mMMDev, __uuidof(IAudioClient), + al::out_ptr(mClient))}; if(FAILED(hr)) { ERR("Failed to reactivate audio client: 0x%08lx\n", hr); @@ -1797,7 +1798,8 @@ HRESULT WasapiCapture::resetProxy() { mClient = nullptr; - HRESULT hr{sDeviceHelper->ActivateAudioClient(mMMDev, al::out_ptr(mClient))}; + HRESULT hr{sDeviceHelper->activateAudioClient(mMMDev, __uuidof(IAudioClient), + al::out_ptr(mClient))}; if(FAILED(hr)) { ERR("Failed to reactivate audio client: 0x%08lx\n", hr); -- cgit v1.2.3 From 589602c931790dde97b189c809cb1051f9cc25b8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 4 Jun 2023 02:45:39 -0700 Subject: Better protect the WASAPI device list with a mutex --- alc/backends/wasapi.cpp | 130 ++++++++++++++++++++++++++++++------------------ 1 file changed, 82 insertions(+), 48 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 391976c8..a294105b 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -196,8 +196,27 @@ bool checkName(const al::span list, const std::string &name) return std::find_if(list.cbegin(), list.cend(), match_name) != list.cend(); } -std::vector PlaybackDevices; -std::vector CaptureDevices; + +struct DeviceList { + auto lock() noexcept(noexcept(mMutex.lock())) { return mMutex.lock(); } + auto unlock() noexcept(noexcept(mMutex.unlock())) { return mMutex.unlock(); } + +private: + std::mutex mMutex; + std::vector mPlayback; + std::vector mCapture; + + friend struct DeviceListLock; +}; +struct DeviceListLock : public std::unique_lock { + using std::unique_lock::unique_lock; + + auto& getPlaybackList() noexcept(noexcept(mutex())) { return mutex()->mPlayback; } + auto& getCaptureList() noexcept(noexcept(mutex())) { return mutex()->mCapture; } +}; + +DeviceList gDeviceList; + #if defined(ALSOFT_UWP) enum EDataFlow @@ -394,33 +413,34 @@ struct DeviceHelper final : private IMMNotificationClient #endif } - HRESULT openDevice(LPCWSTR devid, EDataFlow flow, DeviceHandle& device) + HRESULT openDevice(std::wstring_view devid, EDataFlow flow, DeviceHandle& device) { #if !defined(ALSOFT_UWP) HRESULT hr{E_POINTER}; if(mEnumerator) { - if (!devid) + if(devid.empty()) hr = mEnumerator->GetDefaultAudioEndpoint(flow, eMultimedia, al::out_ptr(device)); else - hr = mEnumerator->GetDevice(devid, al::out_ptr(device)); + hr = mEnumerator->GetDevice(devid.data(), al::out_ptr(device)); } return hr; #else const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; - Platform::String^ devIfPath = - !devid ? (flow == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole)) - : ref new Platform::String(devid); + Platform::String^ devIfPath = + devid.empty() ? (flow == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole)) + : ref new Platform::String(devid.data()); - Concurrency::task createDeviceOp( - DeviceInformation::CreateFromIdAsync(devIfPath, nullptr, DeviceInformationKind::DeviceInterface)); - auto status = createDeviceOp.then([&](DeviceInformation^ deviceInfo) { + Concurrency::task createDeviceOp( + DeviceInformation::CreateFromIdAsync(devIfPath, nullptr, DeviceInformationKind::DeviceInterface)); + auto status = createDeviceOp.then([&](DeviceInformation^ deviceInfo) + { device.value = deviceInfo; - }).wait(); - if (status != Concurrency::task_status::completed) - { - return E_NOINTERFACE; - } + }).wait(); + if(status != Concurrency::task_status::completed) + { + return E_NOINTERFACE; + } return S_OK; #endif } @@ -902,9 +922,11 @@ int WasapiProxy::messageHandler(std::promise *promise) case MsgType::EnumeratePlayback: case MsgType::EnumerateCapture: if(msg.mType == MsgType::EnumeratePlayback) - msg.mPromise.set_value(sDeviceHelper->probe_devices(eRender, PlaybackDevices)); + msg.mPromise.set_value(sDeviceHelper->probe_devices(eRender, + DeviceListLock{gDeviceList}.getPlaybackList())); else if(msg.mType == MsgType::EnumerateCapture) - msg.mPromise.set_value(sDeviceHelper->probe_devices(eCapture, CaptureDevices)); + msg.mPromise.set_value(sDeviceHelper->probe_devices(eCapture, + DeviceListLock{gDeviceList}.getCaptureList())); else msg.mPromise.set_value(E_FAIL); continue; @@ -1083,7 +1105,7 @@ void WasapiPlayback::open(const char *name) if(name) { - if(PlaybackDevices.empty()) + if(DeviceListLock{gDeviceList}.getPlaybackList().empty()) pushMessage(MsgType::EnumeratePlayback); if(std::strncmp(name, DevNameHead, DevNameHeadLen) == 0) { @@ -1101,37 +1123,40 @@ void WasapiPlayback::open(const char *name) HRESULT WasapiPlayback::openProxy(const char *name) { - const wchar_t *devid{nullptr}; + std::string devname; + std::wstring devid; if(name) { - auto iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(), + auto devlock = DeviceListLock{gDeviceList}; + auto list = al::span{devlock.getPlaybackList()}; + auto iter = std::find_if(list.cbegin(), list.cend(), [name](const DevMap &entry) -> bool { return entry.name == name || entry.endpoint_guid == name; }); - if(iter == PlaybackDevices.cend()) + if(iter == list.cend()) { const std::wstring wname{utf8_to_wstr(name)}; - iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(), + iter = std::find_if(list.cbegin(), list.cend(), [&wname](const DevMap &entry) -> bool { return entry.devid == wname; }); } - if(iter == PlaybackDevices.cend()) + if(iter == list.cend()) { WARN("Failed to find device name matching \"%s\"\n", name); return E_FAIL; } - name = iter->name.c_str(); - devid = iter->devid.c_str(); + devname = iter->name; + devid = iter->devid; } HRESULT hr{sDeviceHelper->openDevice(devid, eRender, mMMDev)}; if(FAILED(hr)) { - WARN("Failed to open device \"%s\"\n", name ? name : "(default)"); + WARN("Failed to open device \"%s\"\n", devname.empty() ? "(default)" : devname.c_str()); return hr; } mClient = nullptr; - if(name) - mDevice->DeviceName = std::string{DevNameHead} + name; + if(!devname.empty()) + mDevice->DeviceName = DevNameHead + std::move(devname); else mDevice->DeviceName = DevNameHead + DeviceHelper::get_device_name_and_guid(mMMDev).first; @@ -1725,7 +1750,7 @@ void WasapiCapture::open(const char *name) if(name) { - if(CaptureDevices.empty()) + if(DeviceListLock{gDeviceList}.getCaptureList().empty()) pushMessage(MsgType::EnumerateCapture); if(std::strncmp(name, DevNameHead, DevNameHeadLen) == 0) { @@ -1751,37 +1776,40 @@ void WasapiCapture::open(const char *name) HRESULT WasapiCapture::openProxy(const char *name) { - const wchar_t *devid{nullptr}; + std::string devname; + std::wstring devid; if(name) { - auto iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(), + auto devlock = DeviceListLock{gDeviceList}; + auto devlist = al::span{devlock.getCaptureList()}; + auto iter = std::find_if(devlist.cbegin(), devlist.cend(), [name](const DevMap &entry) -> bool { return entry.name == name || entry.endpoint_guid == name; }); - if(iter == CaptureDevices.cend()) + if(iter == devlist.cend()) { const std::wstring wname{utf8_to_wstr(name)}; - iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(), + iter = std::find_if(devlist.cbegin(), devlist.cend(), [&wname](const DevMap &entry) -> bool { return entry.devid == wname; }); } - if(iter == CaptureDevices.cend()) + if(iter == devlist.cend()) { WARN("Failed to find device name matching \"%s\"\n", name); return E_FAIL; } - name = iter->name.c_str(); - devid = iter->devid.c_str(); + devname = iter->name; + devid = iter->devid; } HRESULT hr{sDeviceHelper->openDevice(devid, eCapture, mMMDev)}; - if (FAILED(hr)) + if(FAILED(hr)) { - WARN("Failed to open device \"%s\"\n", name ? name : "(default)"); + WARN("Failed to open device \"%s\"\n", devname.empty() ? "(default)" : devname.c_str()); return hr; } mClient = nullptr; - if (name) - mDevice->DeviceName = std::string{ DevNameHead } + name; + if(!devname.empty()) + mDevice->DeviceName = DevNameHead + std::move(devname); else mDevice->DeviceName = DevNameHead + DeviceHelper::get_device_name_and_guid(mMMDev).first; @@ -2174,19 +2202,25 @@ std::string WasapiBackendFactory::probe(BackendType type) { case BackendType::Playback: WasapiProxy::pushMessageStatic(MsgType::EnumeratePlayback).wait(); - for(const DevMap &entry : PlaybackDevices) { - /* +1 to also append the null char (to ensure a null-separated list - * and double-null terminated list). - */ - outnames.append(DevNameHead).append(entry.name.c_str(), entry.name.length()+1); + auto devlock = DeviceListLock{gDeviceList}; + for(const DevMap &entry : devlock.getPlaybackList()) + { + /* +1 to also append the null char (to ensure a null-separated + * list and double-null terminated list). + */ + outnames.append(DevNameHead).append(entry.name.c_str(), entry.name.length()+1); + } } break; case BackendType::Capture: WasapiProxy::pushMessageStatic(MsgType::EnumerateCapture).wait(); - for(const DevMap &entry : CaptureDevices) - outnames.append(DevNameHead).append(entry.name.c_str(), entry.name.length()+1); + { + auto devlock = DeviceListLock{gDeviceList}; + for(const DevMap &entry : devlock.getCaptureList()) + outnames.append(DevNameHead).append(entry.name.c_str(), entry.name.length()+1); + } break; } -- cgit v1.2.3 From de01990260223aaef5ca9b66051e58d17133e3b1 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 5 Jun 2023 07:43:06 -0700 Subject: Handle device added/removed events with WASAPI Non-UWP only for now. The device list is managed dynamically now so it doesn't need to be probed for each enumeration query. --- alc/backends/wasapi.cpp | 271 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 181 insertions(+), 90 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index a294105b..c0c33ffa 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -188,7 +188,10 @@ struct DevMap { , endpoint_guid{std::forward(guid_)} , devid{std::forward(devid_)} { } + /* To prevent GCC from complaining it doesn't want to inline this. */ + ~DevMap(); }; +DevMap::~DevMap() = default; bool checkName(const al::span list, const std::string &name) { @@ -205,22 +208,28 @@ private: std::mutex mMutex; std::vector mPlayback; std::vector mCapture; + std::wstring mPlaybackDefaultId; + std::wstring mCaptureDefaultId; friend struct DeviceListLock; }; struct DeviceListLock : public std::unique_lock { using std::unique_lock::unique_lock; - auto& getPlaybackList() noexcept(noexcept(mutex())) { return mutex()->mPlayback; } - auto& getCaptureList() noexcept(noexcept(mutex())) { return mutex()->mCapture; } + auto& getPlaybackList() const noexcept { return mutex()->mPlayback; } + auto& getCaptureList() const noexcept { return mutex()->mCapture; } + + void setPlaybackDefaultId(std::wstring_view devid) const { mutex()->mPlaybackDefaultId = devid; } + std::wstring_view getPlaybackDefaultId() const noexcept { return mutex()->mPlaybackDefaultId; } + void setCaptureDefaultId(std::wstring_view devid) const { mutex()->mCaptureDefaultId = devid; } + std::wstring_view getCaptureDefaultId() const noexcept { return mutex()->mCaptureDefaultId; } }; DeviceList gDeviceList; #if defined(ALSOFT_UWP) -enum EDataFlow -{ +enum EDataFlow { eRender = 0, eCapture = (eRender + 1), eAll = (eCapture + 1), @@ -229,8 +238,7 @@ enum EDataFlow #endif #if defined(ALSOFT_UWP) -struct DeviceHandle -{ +struct DeviceHandle { DeviceHandle& operator=(std::nullptr_t) { value = nullptr; @@ -252,6 +260,9 @@ struct DeviceHelper final : private IMMNotificationClient DeviceHelper() { #if defined(ALSOFT_UWP) + /* TODO: UWP also needs to watch for device added/removed events and + * dynamically add/remove devices from the lists. + */ mActiveClientEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr); mRenderDeviceChangedToken = MediaDevice::DefaultAudioRenderDeviceChanged += @@ -373,8 +384,16 @@ struct DeviceHelper final : private IMMNotificationClient #else /** ----------------------- IMMNotificationClient ------------ */ STDMETHODIMP OnDeviceStateChanged(LPCWSTR /*pwstrDeviceId*/, DWORD /*dwNewState*/) noexcept override { return S_OK; } - STDMETHODIMP OnDeviceAdded(LPCWSTR /*pwstrDeviceId*/) noexcept override { return S_OK; } - STDMETHODIMP OnDeviceRemoved(LPCWSTR /*pwstrDeviceId*/) noexcept override { return S_OK; } + STDMETHODIMP OnDeviceAdded(LPCWSTR pwstrDeviceId) noexcept override + { + add_device(pwstrDeviceId); + return S_OK; + } + STDMETHODIMP OnDeviceRemoved(LPCWSTR pwstrDeviceId) noexcept override + { + remove_device(pwstrDeviceId); + return S_OK; + } STDMETHODIMP OnPropertyValueChanged(LPCWSTR /*pwstrDeviceId*/, const PROPERTYKEY /*key*/) noexcept override { return S_OK; } STDMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) noexcept override { @@ -383,12 +402,14 @@ struct DeviceHelper final : private IMMNotificationClient if(flow == eRender) { + DeviceListLock{gDeviceList}.setPlaybackDefaultId(pwstrDefaultDeviceId); const std::string msg{"Default playback device changed: "+ wstr_to_utf8(pwstrDefaultDeviceId)}; alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, msg); } else if(flow == eCapture) { + DeviceListLock{gDeviceList}.setCaptureDefaultId(pwstrDefaultDeviceId); const std::string msg{"Default capture device changed: "+ wstr_to_utf8(pwstrDefaultDeviceId)}; alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, msg); @@ -469,8 +490,9 @@ struct DeviceHelper final : private IMMNotificationClient } #endif - HRESULT probe_devices(EDataFlow flowdir, std::vector& list) + std::wstring probe_devices(EDataFlow flowdir, std::vector& list) { + std::wstring defaultId; std::vector{}.swap(list); #if !defined(ALSOFT_UWP) @@ -480,7 +502,7 @@ struct DeviceHelper final : private IMMNotificationClient if(FAILED(hr)) { ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); - return hr; + return defaultId; } UINT count{0}; @@ -494,7 +516,7 @@ struct DeviceHelper final : private IMMNotificationClient { if(WCHAR *devid{get_device_id(device.get())}) { - add_device(device, devid, list); + defaultId = devid; CoTaskMemFree(devid); } device = nullptr; @@ -514,19 +536,19 @@ struct DeviceHelper final : private IMMNotificationClient device = nullptr; } - return S_OK; + return defaultId; #else const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; auto DefaultAudioId = flowdir == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole); Concurrency::task createDefaultOp(DeviceInformation::CreateFromIdAsync(DefaultAudioId, nullptr, DeviceInformationKind::DeviceInterface)); - auto task_status = createDefaultOp - .then([this, &list](DeviceInformation ^ deviceInfo) { - if (deviceInfo) - add_device(DeviceHandle{deviceInfo}, deviceInfo->Id->Data(), list); + auto task_status = createDefaultOp.then([&defaultId](DeviceInformation ^ deviceInfo) + { + if(deviceInfo) + defaultId = deviceInfo->Id->Data(); }).wait(); - if (task_status != Concurrency::task_group_status::completed) - return E_FAIL; + if(task_status != Concurrency::task_group_status::completed) + return; // Get the string identifier of the audio renderer auto AudioSelector = flowdir == eRender ? MediaDevice::GetAudioRenderSelector() : MediaDevice::GetAudioCaptureSelector(); @@ -534,32 +556,28 @@ struct DeviceHelper final : private IMMNotificationClient // Setup the asynchronous callback Concurrency::task enumOperation( DeviceInformation::FindAllAsync(AudioSelector, /*PropertyList*/nullptr, DeviceInformationKind::DeviceInterface)); - task_status = enumOperation - .then([this, &list](DeviceInformationCollection ^ DeviceInfoCollection) { - if (DeviceInfoCollection) + task_status = enumOperation.then([this,&list](DeviceInformationCollection ^ DeviceInfoCollection) + { + if(DeviceInfoCollection) { - try - { + try { auto deviceCount = DeviceInfoCollection->Size; - for (unsigned int i = 0; i < deviceCount; ++i) + for(unsigned int i{0};i < deviceCount;++i) { DeviceInformation ^ deviceInfo = DeviceInfoCollection->GetAt(i); - if (deviceInfo) + if(deviceInfo) add_device(DeviceHandle{deviceInfo}, deviceInfo->Id->Data(), list); } } - catch (Platform::Exception ^ e) - { + catch (Platform::Exception ^ e) { } } }).wait(); - - return task_status == Concurrency::task_group_status::completed ? S_OK : E_FAIL; #endif } using NameGUIDPair = std::pair; - static NameGUIDPair get_device_name_and_guid(const DeviceHandle& device) + static NameGUIDPair get_device_name_and_guid(const DeviceHandle &device) { #if !defined(ALSOFT_UWP) static constexpr char UnknownName[]{"Unknown Device Name"}; @@ -568,7 +586,7 @@ struct DeviceHelper final : private IMMNotificationClient ComPtr ps; HRESULT hr = device->OpenPropertyStore(STGM_READ, al::out_ptr(ps)); - if (FAILED(hr)) + if(FAILED(hr)) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); return std::make_pair(UnknownName, UnknownGuid); @@ -576,31 +594,31 @@ struct DeviceHelper final : private IMMNotificationClient PropVariant pvprop; hr = ps->GetValue(al::bit_cast(DEVPKEY_Device_FriendlyName), pvprop.get()); - if (FAILED(hr)) + if(FAILED(hr)) { WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); - name += UnknownName; + name = UnknownName; } - else if (pvprop->vt == VT_LPWSTR) - name += wstr_to_utf8(pvprop->pwszVal); + else if(pvprop->vt == VT_LPWSTR) + name = wstr_to_utf8(pvprop->pwszVal); else { - WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvprop->vt); - name += UnknownName; + WARN("Unexpected Device_FriendlyName PROPVARIANT type: 0x%04x\n", pvprop->vt); + name = UnknownName; } pvprop.clear(); hr = ps->GetValue(al::bit_cast(PKEY_AudioEndpoint_GUID), pvprop.get()); - if (FAILED(hr)) + if(FAILED(hr)) { WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); guid = UnknownGuid; } - else if (pvprop->vt == VT_LPWSTR) + else if(pvprop->vt == VT_LPWSTR) guid = wstr_to_utf8(pvprop->pwszVal); else { - WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvprop->vt); + WARN("Unexpected AudioEndpoint_GUID PROPVARIANT type: 0x%04x\n", pvprop->vt); guid = UnknownGuid; } #else @@ -611,11 +629,11 @@ struct DeviceHelper final : private IMMNotificationClient Platform::String ^ devIfPath = devInfo->Id; auto wcsDevIfPath = devIfPath->Data(); auto devIdStart = wcsstr(wcsDevIfPath, L"}."); - if (devIdStart) + if(devIdStart) { devIdStart += 2; // L"}." auto devIdStartEnd = wcschr(devIdStart, L'#'); - if (devIdStartEnd) + if(devIdStartEnd) { std::wstring wDevId{devIdStart, static_cast(devIdStartEnd - devIdStart)}; guid = wstr_to_utf8(wDevId.c_str()); @@ -626,18 +644,18 @@ struct DeviceHelper final : private IMMNotificationClient return std::make_pair(std::move(name), std::move(guid)); } - static void add_device(const DeviceHandle& device, const WCHAR* devid, std::vector& list) + static void add_device(const DeviceHandle &device, const WCHAR *devid, std::vector &list) { - for (auto& entry : list) + for(auto &entry : list) { - if (entry.devid == devid) + if(entry.devid == devid) return; } auto name_guid = get_device_name_and_guid(device); int count{1}; std::string newname{name_guid.first}; - while (checkName(list, newname)) + while(checkName(list, newname)) { newname = name_guid.first; newname += " #"; @@ -651,6 +669,83 @@ struct DeviceHelper final : private IMMNotificationClient } #if !defined(ALSOFT_UWP) + void add_device(std::wstring_view devid) + { + ComPtr device; + HRESULT hr{mEnumerator->GetDevice(devid.data(), al::out_ptr(device))}; + if(FAILED(hr)) + { + ERR("Failed to get device: 0x%08lx\n", hr); + return; + } + + ComPtr endpoint; + hr = device->QueryInterface(__uuidof(IMMEndpoint), al::out_ptr(endpoint)); + if(FAILED(hr)) + { + ERR("Failed to get device endpoint: 0x%08lx\n", hr); + return; + } + + EDataFlow flowdir{}; + hr = endpoint->GetDataFlow(&flowdir); + if(FAILED(hr)) + { + ERR("Failed to get endpoint data flow: 0x%08lx\n", hr); + return; + } + + auto devlock = DeviceListLock{gDeviceList}; + auto &list = (flowdir==eRender) ? devlock.getPlaybackList() : devlock.getCaptureList(); + auto devtype = (flowdir==eRender) ? alc::DeviceType::Playback:alc::DeviceType::Capture; + + /* Ensure the ID doesn't already exist. */ + auto iter = std::find_if(list.begin(), list.end(), + [devid](const DevMap &entry) noexcept { return devid == entry.devid; }); + if(iter != list.end()) return; + + auto name_guid = get_device_name_and_guid(device); + int count{1}; + std::string newname{name_guid.first}; + while(checkName(list, newname)) + { + newname = name_guid.first; + newname += " #"; + newname += std::to_string(++count); + } + list.emplace_back(std::move(newname), std::move(name_guid.second), devid); + const DevMap &newentry = list.back(); + + TRACE("Added device \"%s\", \"%s\", \"%ls\"\n", newentry.name.c_str(), + newentry.endpoint_guid.c_str(), newentry.devid.c_str()); + + std::string msg{"Device added: "+newentry.name}; + alc::Event(alc::EventType::DeviceAdded, devtype, msg); + } + + void remove_device(std::wstring_view devid) + { + auto devlock = DeviceListLock{gDeviceList}; + for(auto flowdir : std::array{eRender, eCapture}) + { + auto &list = (flowdir==eRender) ? devlock.getPlaybackList() : devlock.getCaptureList(); + auto devtype = (flowdir==eRender)?alc::DeviceType::Playback : alc::DeviceType::Capture; + + /* Find the ID in the list to remove. */ + auto iter = std::find_if(list.begin(), list.end(), + [devid](const DevMap &entry) noexcept { return devid == entry.devid; }); + if(iter == list.end()) continue; + + TRACE("Removing device \"%s\", \"%s\", \"%ls\"\n", iter->name.c_str(), + iter->endpoint_guid.c_str(), iter->devid.c_str()); + + std::string msg{"Device removed: "+std::move(iter->name)}; + list.erase(iter); + + alc::Event(alc::EventType::DeviceRemoved, devtype, msg); + } + } + static WCHAR *get_device_id(IMMDevice* device) { WCHAR *devid; @@ -784,21 +879,17 @@ enum class MsgType { StartDevice, StopDevice, CloseDevice, - EnumeratePlayback, - EnumerateCapture, Count, QuitThread = Count }; -constexpr char MessageStr[static_cast(MsgType::Count)][20]{ +constexpr char MessageStr[static_cast(MsgType::Count)][16]{ "Open Device", "Reset Device", "Start Device", "Stop Device", "Close Device", - "Enumerate Playback", - "Enumerate Capture" }; @@ -885,6 +976,14 @@ int WasapiProxy::messageHandler(std::promise *promise) if(FAILED(hr)) goto skip_loop; + { + auto devlock = DeviceListLock{gDeviceList}; + auto defaultId = sDeviceHelper->probe_devices(eRender, devlock.getPlaybackList()); + if(!defaultId.empty()) devlock.setPlaybackDefaultId(defaultId); + defaultId = sDeviceHelper->probe_devices(eCapture, devlock.getCaptureList()); + if(!defaultId.empty()) devlock.setCaptureDefaultId(defaultId); + } + TRACE("Starting message loop\n"); while(Msg msg{popMessage()}) { @@ -919,18 +1018,6 @@ int WasapiProxy::messageHandler(std::promise *promise) msg.mPromise.set_value(S_OK); continue; - case MsgType::EnumeratePlayback: - case MsgType::EnumerateCapture: - if(msg.mType == MsgType::EnumeratePlayback) - msg.mPromise.set_value(sDeviceHelper->probe_devices(eRender, - DeviceListLock{gDeviceList}.getPlaybackList())); - else if(msg.mType == MsgType::EnumerateCapture) - msg.mPromise.set_value(sDeviceHelper->probe_devices(eCapture, - DeviceListLock{gDeviceList}.getCaptureList())); - else - msg.mPromise.set_value(E_FAIL); - continue; - case MsgType::QuitThread: break; } @@ -1103,16 +1190,11 @@ void WasapiPlayback::open(const char *name) "Failed to create notify events"}; } - if(name) + if(name && std::strncmp(name, DevNameHead, DevNameHeadLen) == 0) { - if(DeviceListLock{gDeviceList}.getPlaybackList().empty()) - pushMessage(MsgType::EnumeratePlayback); - if(std::strncmp(name, DevNameHead, DevNameHeadLen) == 0) - { - name += DevNameHeadLen; - if(*name == '\0') - name = nullptr; - } + name += DevNameHeadLen; + if(*name == '\0') + name = nullptr; } mOpenStatus = pushMessage(MsgType::OpenDevice, name).get(); @@ -1748,16 +1830,11 @@ void WasapiCapture::open(const char *name) "Failed to create notify events"}; } - if(name) + if(name && std::strncmp(name, DevNameHead, DevNameHeadLen) == 0) { - if(DeviceListLock{gDeviceList}.getCaptureList().empty()) - pushMessage(MsgType::EnumerateCapture); - if(std::strncmp(name, DevNameHead, DevNameHeadLen) == 0) - { - name += DevNameHeadLen; - if(*name == '\0') - name = nullptr; - } + name += DevNameHeadLen; + if(*name == '\0') + name = nullptr; } mOpenStatus = pushMessage(MsgType::OpenDevice, name).get(); @@ -2198,28 +2275,42 @@ std::string WasapiBackendFactory::probe(BackendType type) { std::string outnames; + auto devlock = DeviceListLock{gDeviceList}; switch(type) { case BackendType::Playback: - WasapiProxy::pushMessageStatic(MsgType::EnumeratePlayback).wait(); { - auto devlock = DeviceListLock{gDeviceList}; + auto defaultId = devlock.getPlaybackDefaultId(); for(const DevMap &entry : devlock.getPlaybackList()) { - /* +1 to also append the null char (to ensure a null-separated - * list and double-null terminated list). - */ - outnames.append(DevNameHead).append(entry.name.c_str(), entry.name.length()+1); + if(entry.devid != defaultId) + { + /* +1 to also append the null char (to ensure a null- + * separated list and double-null terminated list). + */ + outnames.append(DevNameHead).append(entry.name.c_str(), entry.name.length()+1); + continue; + } + /* Default device goes first. */ + std::string name{DevNameHead + entry.name}; + outnames.insert(0, name.c_str(), name.length()+1); } } break; case BackendType::Capture: - WasapiProxy::pushMessageStatic(MsgType::EnumerateCapture).wait(); { - auto devlock = DeviceListLock{gDeviceList}; + auto defaultId = devlock.getCaptureDefaultId(); for(const DevMap &entry : devlock.getCaptureList()) - outnames.append(DevNameHead).append(entry.name.c_str(), entry.name.length()+1); + { + if(entry.devid != defaultId) + { + outnames.append(DevNameHead).append(entry.name.c_str(), entry.name.length()+1); + continue; + } + std::string name{DevNameHead + entry.name}; + outnames.insert(0, name.c_str(), name.length()+1); + } } break; } -- cgit v1.2.3 From 399853fa3456fa1cf21426f0a2f8f39390124c64 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 5 Jun 2023 08:16:48 -0700 Subject: Fix return value for UWP builds --- alc/backends/wasapi.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index c0c33ffa..653c9098 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -535,8 +535,6 @@ struct DeviceHelper final : private IMMNotificationClient } device = nullptr; } - - return defaultId; #else const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; auto DefaultAudioId = flowdir == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) @@ -548,7 +546,7 @@ struct DeviceHelper final : private IMMNotificationClient defaultId = deviceInfo->Id->Data(); }).wait(); if(task_status != Concurrency::task_group_status::completed) - return; + return defaultId; // Get the string identifier of the audio renderer auto AudioSelector = flowdir == eRender ? MediaDevice::GetAudioRenderSelector() : MediaDevice::GetAudioCaptureSelector(); @@ -574,6 +572,8 @@ struct DeviceHelper final : private IMMNotificationClient } }).wait(); #endif + + return defaultId; } using NameGUIDPair = std::pair; -- cgit v1.2.3 From 5c143f8faa791cf563b2e7d11139c0f41bcb6cbc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 5 Jun 2023 19:42:34 -0700 Subject: Avoid explicit definitions of some IIDs --- alc/backends/wasapi.cpp | 6 +++--- core/uiddefs.cpp | 4 ---- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 653c9098..b07cb62a 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -423,7 +423,7 @@ struct DeviceHelper final : private IMMNotificationClient { #if !defined(ALSOFT_UWP) HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, - IID_IMMDeviceEnumerator, al::out_ptr(mEnumerator))}; + __uuidof(IMMDeviceEnumerator), al::out_ptr(mEnumerator))}; if(SUCCEEDED(hr)) mEnumerator->RegisterEndpointNotificationCallback(this); else @@ -1621,7 +1621,7 @@ HRESULT WasapiPlayback::startProxy() return hr; } - hr = mClient->GetService(IID_IAudioRenderClient, al::out_ptr(mRender)); + hr = mClient->GetService(__uuidof(IAudioRenderClient), al::out_ptr(mRender)); if(SUCCEEDED(hr)) { try { @@ -2201,7 +2201,7 @@ HRESULT WasapiCapture::startProxy() return hr; } - hr = mClient->GetService(IID_IAudioCaptureClient, al::out_ptr(mCapture)); + hr = mClient->GetService(__uuidof(IAudioCaptureClient), al::out_ptr(mCapture)); if(SUCCEEDED(hr)) { try { diff --git a/core/uiddefs.cpp b/core/uiddefs.cpp index 833150f5..9471bba5 100644 --- a/core/uiddefs.cpp +++ b/core/uiddefs.cpp @@ -19,10 +19,6 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80,0x DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf,0x08, 0x00,0xa0,0xc9,0x25,0xcd,0x16); DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e); -DEFINE_GUID(IID_IMMDeviceEnumerator, 0xa95664d2, 0x9614, 0x4f35, 0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6); -DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2); -DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2); -DEFINE_GUID(IID_IAudioCaptureClient, 0xc8adbd64, 0xe71e, 0x48a0, 0xa4,0xde, 0x18,0x5c,0x39,0x5c,0xd3,0x17); #if defined(HAVE_WASAPI) && !defined(ALSOFT_UWP) #include -- cgit v1.2.3 From 79bdc1c0a25289c21746283cab56d149b266c7ad Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 6 Jun 2023 02:44:42 -0700 Subject: Directly inline a couple functions --- alc/backends/wasapi.cpp | 363 +++++++++++++++++++++++------------------------- 1 file changed, 174 insertions(+), 189 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index b07cb62a..40255dc9 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -251,6 +251,99 @@ using EventRegistrationToken = Windows::Foundation::EventRegistrationToken; using DeviceHandle = ComPtr; #endif + +using NameGUIDPair = std::pair; +static NameGUIDPair GetDeviceNameAndGuid(const DeviceHandle &device) +{ + static constexpr char UnknownName[]{"Unknown Device Name"}; + static constexpr char UnknownGuid[]{"Unknown Device GUID"}; +#if !defined(ALSOFT_UWP) + std::string name, guid; + + ComPtr ps; + HRESULT hr = device->OpenPropertyStore(STGM_READ, al::out_ptr(ps)); + if(FAILED(hr)) + { + WARN("OpenPropertyStore failed: 0x%08lx\n", hr); + return std::make_pair(UnknownName, UnknownGuid); + } + + PropVariant pvprop; + hr = ps->GetValue(al::bit_cast(DEVPKEY_Device_FriendlyName), pvprop.get()); + if(FAILED(hr)) + { + WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); + name = UnknownName; + } + else if(pvprop->vt == VT_LPWSTR) + name = wstr_to_utf8(pvprop->pwszVal); + else + { + WARN("Unexpected Device_FriendlyName PROPVARIANT type: 0x%04x\n", pvprop->vt); + name = UnknownName; + } + + pvprop.clear(); + hr = ps->GetValue(al::bit_cast(PKEY_AudioEndpoint_GUID), pvprop.get()); + if(FAILED(hr)) + { + WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); + guid = UnknownGuid; + } + else if(pvprop->vt == VT_LPWSTR) + guid = wstr_to_utf8(pvprop->pwszVal); + else + { + WARN("Unexpected AudioEndpoint_GUID PROPVARIANT type: 0x%04x\n", pvprop->vt); + guid = UnknownGuid; + } +#else + auto devInfo = device.value; + std::string name{wstr_to_utf8(devInfo->Name->Data())}; + std::string guid; + // devInfo->Id is DeviceInterfacePath: \\?\SWD#MMDEVAPI#{0.0.0.00000000}.{a21c17a0-fc1d-405e-ab5a-b513422b57d1}#{e6327cad-dcec-4949-ae8a-991e976a79d2} + Platform::String ^ devIfPath = devInfo->Id; + if(auto devIdStart = wcsstr(devIfPath->Data(), L"}.")) + { + devIdStart += 2; // L"}." + if(auto devIdStartEnd = wcschr(devIdStart, L'#')) + { + std::wstring wDevId{devIdStart, static_cast(devIdStartEnd - devIdStart)}; + guid = wstr_to_utf8(wDevId.c_str()); + std::transform(guid.begin(), guid.end(), guid.begin(), + [](char ch) { return static_cast(std::toupper(ch)); }); + } + } + if(name.empty()) name = UnknownName; + if(guid.empty()) guid = UnknownGuid; +#endif + return std::make_pair(std::move(name), std::move(guid)); +} +#if !defined(ALSOFT_UWP) +EndpointFormFactor GetDeviceFormfactor(IMMDevice *device) +{ + ComPtr ps; + HRESULT hr{device->OpenPropertyStore(STGM_READ, al::out_ptr(ps))}; + if(FAILED(hr)) + { + WARN("OpenPropertyStore failed: 0x%08lx\n", hr); + return UnknownFormFactor; + } + + EndpointFormFactor formfactor{UnknownFormFactor}; + PropVariant pvform; + hr = ps->GetValue(PKEY_AudioEndpoint_FormFactor, pvform.get()); + if(FAILED(hr)) + WARN("GetValue AudioEndpoint_FormFactor failed: 0x%08lx\n", hr); + else if(pvform->vt == VT_UI4) + formfactor = static_cast(pvform->ulVal); + else if(pvform->vt != VT_EMPTY) + WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform->vt); + return formfactor; +} +#endif + + #if defined(ALSOFT_UWP) struct DeviceHelper final : public IActivateAudioInterfaceCompletionHandler #else @@ -384,17 +477,74 @@ struct DeviceHelper final : private IMMNotificationClient #else /** ----------------------- IMMNotificationClient ------------ */ STDMETHODIMP OnDeviceStateChanged(LPCWSTR /*pwstrDeviceId*/, DWORD /*dwNewState*/) noexcept override { return S_OK; } + STDMETHODIMP OnDeviceAdded(LPCWSTR pwstrDeviceId) noexcept override { - add_device(pwstrDeviceId); + ComPtr device; + HRESULT hr{mEnumerator->GetDevice(pwstrDeviceId, al::out_ptr(device))}; + if(FAILED(hr)) + { + ERR("Failed to get device: 0x%08lx\n", hr); + return S_OK; + } + + ComPtr endpoint; + hr = device->QueryInterface(__uuidof(IMMEndpoint), al::out_ptr(endpoint)); + if(FAILED(hr)) + { + ERR("Failed to get device endpoint: 0x%08lx\n", hr); + return S_OK; + } + + EDataFlow flowdir{}; + hr = endpoint->GetDataFlow(&flowdir); + if(FAILED(hr)) + { + ERR("Failed to get endpoint data flow: 0x%08lx\n", hr); + return S_OK; + } + + auto devlock = DeviceListLock{gDeviceList}; + auto &list = (flowdir==eRender) ? devlock.getPlaybackList() : devlock.getCaptureList(); + + if(AddDevice(device, pwstrDeviceId, list)) + { + const auto devtype = (flowdir==eRender) ? alc::DeviceType::Playback + : alc::DeviceType::Capture; + const std::string msg{"Device added: "+list.back().name}; + alc::Event(alc::EventType::DeviceAdded, devtype, msg); + } + return S_OK; } + STDMETHODIMP OnDeviceRemoved(LPCWSTR pwstrDeviceId) noexcept override { - remove_device(pwstrDeviceId); + auto devlock = DeviceListLock{gDeviceList}; + for(auto flowdir : std::array{eRender, eCapture}) + { + auto &list = (flowdir==eRender) ? devlock.getPlaybackList() : devlock.getCaptureList(); + auto devtype = (flowdir==eRender)?alc::DeviceType::Playback : alc::DeviceType::Capture; + + /* Find the ID in the list to remove. */ + auto iter = std::find_if(list.begin(), list.end(), + [pwstrDeviceId](const DevMap &entry) noexcept + { return pwstrDeviceId == entry.devid; }); + if(iter == list.end()) continue; + + TRACE("Removing device \"%s\", \"%s\", \"%ls\"\n", iter->name.c_str(), + iter->endpoint_guid.c_str(), iter->devid.c_str()); + + std::string msg{"Device removed: "+std::move(iter->name)}; + list.erase(iter); + + alc::Event(alc::EventType::DeviceRemoved, devtype, msg); + } return S_OK; } + STDMETHODIMP OnPropertyValueChanged(LPCWSTR /*pwstrDeviceId*/, const PROPERTYKEY /*key*/) noexcept override { return S_OK; } + STDMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) noexcept override { if(role != eMultimedia) @@ -437,7 +587,7 @@ struct DeviceHelper final : private IMMNotificationClient HRESULT openDevice(std::wstring_view devid, EDataFlow flow, DeviceHandle& device) { #if !defined(ALSOFT_UWP) - HRESULT hr{E_POINTER}; + HRESULT hr{E_FAIL}; if(mEnumerator) { if(devid.empty()) @@ -490,7 +640,7 @@ struct DeviceHelper final : private IMMNotificationClient } #endif - std::wstring probe_devices(EDataFlow flowdir, std::vector& list) + std::wstring probeDevices(EDataFlow flowdir, std::vector &list) { std::wstring defaultId; std::vector{}.swap(list); @@ -514,7 +664,7 @@ struct DeviceHelper final : private IMMNotificationClient hr = mEnumerator->GetDefaultAudioEndpoint(flowdir, eMultimedia, al::out_ptr(device)); if(SUCCEEDED(hr)) { - if(WCHAR *devid{get_device_id(device.get())}) + if(WCHAR *devid{GetDeviceId(device.get())}) { defaultId = devid; CoTaskMemFree(devid); @@ -528,9 +678,9 @@ struct DeviceHelper final : private IMMNotificationClient if(FAILED(hr)) continue; - if(WCHAR *devid{get_device_id(device.get())}) + if(WCHAR *devid{GetDeviceId(device.get())}) { - add_device(device, devid, list); + std::ignore = AddDevice(device, devid, list); CoTaskMemFree(devid); } device = nullptr; @@ -564,7 +714,8 @@ struct DeviceHelper final : private IMMNotificationClient { DeviceInformation ^ deviceInfo = DeviceInfoCollection->GetAt(i); if(deviceInfo) - add_device(DeviceHandle{deviceInfo}, deviceInfo->Id->Data(), list); + std::ignore = AddDevice(DeviceHandle{deviceInfo}, + deviceInfo->Id->Data(), list); } } catch (Platform::Exception ^ e) { @@ -576,135 +727,16 @@ struct DeviceHelper final : private IMMNotificationClient return defaultId; } - using NameGUIDPair = std::pair; - static NameGUIDPair get_device_name_and_guid(const DeviceHandle &device) - { -#if !defined(ALSOFT_UWP) - static constexpr char UnknownName[]{"Unknown Device Name"}; - static constexpr char UnknownGuid[]{"Unknown Device GUID"}; - std::string name, guid; - - ComPtr ps; - HRESULT hr = device->OpenPropertyStore(STGM_READ, al::out_ptr(ps)); - if(FAILED(hr)) - { - WARN("OpenPropertyStore failed: 0x%08lx\n", hr); - return std::make_pair(UnknownName, UnknownGuid); - } - - PropVariant pvprop; - hr = ps->GetValue(al::bit_cast(DEVPKEY_Device_FriendlyName), pvprop.get()); - if(FAILED(hr)) - { - WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); - name = UnknownName; - } - else if(pvprop->vt == VT_LPWSTR) - name = wstr_to_utf8(pvprop->pwszVal); - else - { - WARN("Unexpected Device_FriendlyName PROPVARIANT type: 0x%04x\n", pvprop->vt); - name = UnknownName; - } - - pvprop.clear(); - hr = ps->GetValue(al::bit_cast(PKEY_AudioEndpoint_GUID), pvprop.get()); - if(FAILED(hr)) - { - WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); - guid = UnknownGuid; - } - else if(pvprop->vt == VT_LPWSTR) - guid = wstr_to_utf8(pvprop->pwszVal); - else - { - WARN("Unexpected AudioEndpoint_GUID PROPVARIANT type: 0x%04x\n", pvprop->vt); - guid = UnknownGuid; - } -#else - auto devInfo = device.value; - std::string name = wstr_to_utf8(devInfo->Name->Data()); - std::string guid; - // devInfo->Id is DeviceInterfacePath: \\?\SWD#MMDEVAPI#{0.0.0.00000000}.{a21c17a0-fc1d-405e-ab5a-b513422b57d1}#{e6327cad-dcec-4949-ae8a-991e976a79d2} - Platform::String ^ devIfPath = devInfo->Id; - auto wcsDevIfPath = devIfPath->Data(); - auto devIdStart = wcsstr(wcsDevIfPath, L"}."); - if(devIdStart) - { - devIdStart += 2; // L"}." - auto devIdStartEnd = wcschr(devIdStart, L'#'); - if(devIdStartEnd) - { - std::wstring wDevId{devIdStart, static_cast(devIdStartEnd - devIdStart)}; - guid = wstr_to_utf8(wDevId.c_str()); - std::transform(guid.begin(), guid.end(), guid.begin(), [](char ch) { return static_cast(std::toupper(ch)); }); - } - } -#endif - return std::make_pair(std::move(name), std::move(guid)); - } - - static void add_device(const DeviceHandle &device, const WCHAR *devid, std::vector &list) +private: + static bool AddDevice(const DeviceHandle &device, const WCHAR *devid, std::vector &list) { for(auto &entry : list) { if(entry.devid == devid) - return; - } - - auto name_guid = get_device_name_and_guid(device); - int count{1}; - std::string newname{name_guid.first}; - while(checkName(list, newname)) - { - newname = name_guid.first; - newname += " #"; - newname += std::to_string(++count); - } - list.emplace_back(std::move(newname), std::move(name_guid.second), devid); - const DevMap& newentry = list.back(); - - TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", newentry.name.c_str(), newentry.endpoint_guid.c_str(), - newentry.devid.c_str()); - } - -#if !defined(ALSOFT_UWP) - void add_device(std::wstring_view devid) - { - ComPtr device; - HRESULT hr{mEnumerator->GetDevice(devid.data(), al::out_ptr(device))}; - if(FAILED(hr)) - { - ERR("Failed to get device: 0x%08lx\n", hr); - return; - } - - ComPtr endpoint; - hr = device->QueryInterface(__uuidof(IMMEndpoint), al::out_ptr(endpoint)); - if(FAILED(hr)) - { - ERR("Failed to get device endpoint: 0x%08lx\n", hr); - return; - } - - EDataFlow flowdir{}; - hr = endpoint->GetDataFlow(&flowdir); - if(FAILED(hr)) - { - ERR("Failed to get endpoint data flow: 0x%08lx\n", hr); - return; + return false; } - auto devlock = DeviceListLock{gDeviceList}; - auto &list = (flowdir==eRender) ? devlock.getPlaybackList() : devlock.getCaptureList(); - auto devtype = (flowdir==eRender) ? alc::DeviceType::Playback:alc::DeviceType::Capture; - - /* Ensure the ID doesn't already exist. */ - auto iter = std::find_if(list.begin(), list.end(), - [devid](const DevMap &entry) noexcept { return devid == entry.devid; }); - if(iter != list.end()) return; - - auto name_guid = get_device_name_and_guid(device); + auto name_guid = GetDeviceNameAndGuid(device); int count{1}; std::string newname{name_guid.first}; while(checkName(list, newname)) @@ -716,37 +748,13 @@ struct DeviceHelper final : private IMMNotificationClient list.emplace_back(std::move(newname), std::move(name_guid.second), devid); const DevMap &newentry = list.back(); - TRACE("Added device \"%s\", \"%s\", \"%ls\"\n", newentry.name.c_str(), + TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", newentry.name.c_str(), newentry.endpoint_guid.c_str(), newentry.devid.c_str()); - - std::string msg{"Device added: "+newentry.name}; - alc::Event(alc::EventType::DeviceAdded, devtype, msg); - } - - void remove_device(std::wstring_view devid) - { - auto devlock = DeviceListLock{gDeviceList}; - for(auto flowdir : std::array{eRender, eCapture}) - { - auto &list = (flowdir==eRender) ? devlock.getPlaybackList() : devlock.getCaptureList(); - auto devtype = (flowdir==eRender)?alc::DeviceType::Playback : alc::DeviceType::Capture; - - /* Find the ID in the list to remove. */ - auto iter = std::find_if(list.begin(), list.end(), - [devid](const DevMap &entry) noexcept { return devid == entry.devid; }); - if(iter == list.end()) continue; - - TRACE("Removing device \"%s\", \"%s\", \"%ls\"\n", iter->name.c_str(), - iter->endpoint_guid.c_str(), iter->devid.c_str()); - - std::string msg{"Device removed: "+std::move(iter->name)}; - list.erase(iter); - - alc::Event(alc::EventType::DeviceRemoved, devtype, msg); - } + return true; } - static WCHAR *get_device_id(IMMDevice* device) +#if !defined(ALSOFT_UWP) + static WCHAR *GetDeviceId(IMMDevice *device) { WCHAR *devid; @@ -759,38 +767,15 @@ struct DeviceHelper final : private IMMNotificationClient return devid; } - static EndpointFormFactor get_device_formfactor(IMMDevice* device) - { - ComPtr ps; - HRESULT hr{device->OpenPropertyStore(STGM_READ, al::out_ptr(ps))}; - if(FAILED(hr)) - { - WARN("OpenPropertyStore failed: 0x%08lx\n", hr); - return UnknownFormFactor; - } + ComPtr mEnumerator{nullptr}; - EndpointFormFactor formfactor{UnknownFormFactor}; - PropVariant pvform; - hr = ps->GetValue(PKEY_AudioEndpoint_FormFactor, pvform.get()); - if(FAILED(hr)) - WARN("GetValue AudioEndpoint_FormFactor failed: 0x%08lx\n", hr); - else if(pvform->vt == VT_UI4) - formfactor = static_cast(pvform->ulVal); - else if(pvform->vt != VT_EMPTY) - WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform->vt); - return formfactor; - } -#endif +#else -private: -#if defined(ALSOFT_UWP) HANDLE mActiveClientEvent{nullptr}; void** mPPV{nullptr}; EventRegistrationToken mRenderDeviceChangedToken; EventRegistrationToken mCaptureDeviceChangedToken; -#else - ComPtr mEnumerator{nullptr}; #endif }; @@ -978,9 +963,9 @@ int WasapiProxy::messageHandler(std::promise *promise) { auto devlock = DeviceListLock{gDeviceList}; - auto defaultId = sDeviceHelper->probe_devices(eRender, devlock.getPlaybackList()); + auto defaultId = sDeviceHelper->probeDevices(eRender, devlock.getPlaybackList()); if(!defaultId.empty()) devlock.setPlaybackDefaultId(defaultId); - defaultId = sDeviceHelper->probe_devices(eCapture, devlock.getCaptureList()); + defaultId = sDeviceHelper->probeDevices(eCapture, devlock.getCaptureList()); if(!defaultId.empty()) devlock.setCaptureDefaultId(defaultId); } @@ -1240,7 +1225,7 @@ HRESULT WasapiPlayback::openProxy(const char *name) if(!devname.empty()) mDevice->DeviceName = DevNameHead + std::move(devname); else - mDevice->DeviceName = DevNameHead + DeviceHelper::get_device_name_and_guid(mMMDev).first; + mDevice->DeviceName = DevNameHead + GetDeviceNameAndGuid(mMMDev).first; return S_OK; } @@ -1536,7 +1521,7 @@ HRESULT WasapiPlayback::resetProxy() mFormat = OutputType; #if !defined(ALSOFT_UWP) - const EndpointFormFactor formfactor{DeviceHelper::get_device_formfactor(mMMDev.get())}; + const EndpointFormFactor formfactor{GetDeviceFormfactor(mMMDev.get())}; mDevice->Flags.set(DirectEar, (formfactor == Headphones || formfactor == Headset)); #else mDevice->Flags.set(DirectEar, false); @@ -1888,7 +1873,7 @@ HRESULT WasapiCapture::openProxy(const char *name) if(!devname.empty()) mDevice->DeviceName = DevNameHead + std::move(devname); else - mDevice->DeviceName = DevNameHead + DeviceHelper::get_device_name_and_guid(mMMDev).first; + mDevice->DeviceName = DevNameHead + GetDeviceNameAndGuid(mMMDev).first; return S_OK; } -- cgit v1.2.3 From 642baebaa2920c92b750246c599f1d381d3f284b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 6 Jun 2023 02:56:06 -0700 Subject: Remove a seemingly unnecessary C++/CLI wrapper --- alc/backends/wasapi.cpp | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 40255dc9..816a2ae1 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -238,17 +238,10 @@ enum EDataFlow { #endif #if defined(ALSOFT_UWP) -struct DeviceHandle { - DeviceHandle& operator=(std::nullptr_t) - { - value = nullptr; - return *this; - } - DeviceInformation^ value{nullptr}; -}; +using DeviceHandle = DeviceInformation^; using EventRegistrationToken = Windows::Foundation::EventRegistrationToken; #else -using DeviceHandle = ComPtr; +using DeviceHandle = ComPtr; #endif @@ -298,11 +291,10 @@ static NameGUIDPair GetDeviceNameAndGuid(const DeviceHandle &device) guid = UnknownGuid; } #else - auto devInfo = device.value; - std::string name{wstr_to_utf8(devInfo->Name->Data())}; + std::string name{wstr_to_utf8(device->Name->Data())}; std::string guid; - // devInfo->Id is DeviceInterfacePath: \\?\SWD#MMDEVAPI#{0.0.0.00000000}.{a21c17a0-fc1d-405e-ab5a-b513422b57d1}#{e6327cad-dcec-4949-ae8a-991e976a79d2} - Platform::String ^ devIfPath = devInfo->Id; + // device->Id is DeviceInterfacePath: \\?\SWD#MMDEVAPI#{0.0.0.00000000}.{a21c17a0-fc1d-405e-ab5a-b513422b57d1}#{e6327cad-dcec-4949-ae8a-991e976a79d2} + Platform::String^ devIfPath = device->Id; if(auto devIdStart = wcsstr(devIfPath->Data(), L"}.")) { devIdStart += 2; // L"}." @@ -606,7 +598,7 @@ struct DeviceHelper final : private IMMNotificationClient DeviceInformation::CreateFromIdAsync(devIfPath, nullptr, DeviceInformationKind::DeviceInterface)); auto status = createDeviceOp.then([&](DeviceInformation^ deviceInfo) { - device.value = deviceInfo; + device = deviceInfo; }).wait(); if(status != Concurrency::task_status::completed) { @@ -624,7 +616,7 @@ struct DeviceHelper final : private IMMNotificationClient { ComPtr asyncOp; mPPV = ppv; - HRESULT hr{ActivateAudioInterfaceAsync(device.value->Id->Data(), iid, nullptr, this, + HRESULT hr{ActivateAudioInterfaceAsync(device->Id->Data(), iid, nullptr, this, al::out_ptr(asyncOp))}; if(FAILED(hr)) return hr; @@ -712,10 +704,9 @@ struct DeviceHelper final : private IMMNotificationClient auto deviceCount = DeviceInfoCollection->Size; for(unsigned int i{0};i < deviceCount;++i) { - DeviceInformation ^ deviceInfo = DeviceInfoCollection->GetAt(i); + DeviceInformation^ deviceInfo = DeviceInfoCollection->GetAt(i); if(deviceInfo) - std::ignore = AddDevice(DeviceHandle{deviceInfo}, - deviceInfo->Id->Data(), list); + std::ignore = AddDevice(deviceInfo, deviceInfo->Id->Data(), list); } } catch (Platform::Exception ^ e) { -- cgit v1.2.3 From 3d9900476ec49b2994b7163a451a69560d498306 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 7 Jun 2023 01:44:02 -0700 Subject: Get the correct audio client interface with UWP --- alc/backends/wasapi.cpp | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 816a2ae1..b68a59e2 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -443,24 +443,8 @@ struct DeviceHelper final : private IMMNotificationClient #if defined(ALSOFT_UWP) /** ----------------------- IActivateAudioInterfaceCompletionHandler ------------ */ - HRESULT ActivateCompleted(IActivateAudioInterfaceAsyncOperation* operation) override + HRESULT ActivateCompleted(IActivateAudioInterfaceAsyncOperation*) override { - HRESULT hrActivateResult = S_OK; - IUnknown* punkAudioInterface = nullptr; - - HRESULT hr = operation->GetActivateResult(&hrActivateResult, &punkAudioInterface); - // Check for a successful activation result - if (SUCCEEDED(hr) && SUCCEEDED(hrActivateResult)) - { - if (mPPV) - { - // Get the pointer for the Audio Client - IAudioClient3* audioClient; - punkAudioInterface->QueryInterface(IID_PPV_ARGS(&audioClient)); - *mPPV = audioClient; - } - } - SetEvent(mActiveClientEvent); // Need to return S_OK @@ -609,26 +593,35 @@ struct DeviceHelper final : private IMMNotificationClient } #if !defined(ALSOFT_UWP) - static HRESULT activateAudioClient(_In_ DeviceHandle& device, REFIID iid, void **ppv) + static HRESULT activateAudioClient(_In_ DeviceHandle &device, REFIID iid, void **ppv) { return device->Activate(iid, CLSCTX_INPROC_SERVER, nullptr, ppv); } #else - HRESULT activateAudioClient(_In_ DeviceHandle& device, _In_ REFIID iid, void **ppv) + HRESULT activateAudioClient(_In_ DeviceHandle &device, _In_ REFIID iid, void **ppv) { ComPtr asyncOp; - mPPV = ppv; HRESULT hr{ActivateAudioInterfaceAsync(device->Id->Data(), iid, nullptr, this, al::out_ptr(asyncOp))}; if(FAILED(hr)) return hr; - asyncOp = nullptr; - DWORD res{WaitForSingleObjectEx(mActiveClientEvent, 2000, FALSE)}; + /* I don't like waiting for INFINITE time, but the activate operation + * can take an indefinite amount of time since it can require user + * input. + */ + DWORD res{WaitForSingleObjectEx(mActiveClientEvent, INFINITE, FALSE)}; if(res != WAIT_OBJECT_0) { ERR("WaitForSingleObjectEx error: 0x%lx\n", res); return E_FAIL; } - return S_OK; + + HRESULT hrActivateRes{E_FAIL}; + ComPtr punkAudioIface; + hr = asyncOp->GetActivateResult(&hrActivateRes, al::out_ptr(punkAudioIface)); + if(SUCCEEDED(hr)) hr = hrActivateRes; + if(FAILED(hr)) return hr; + + return punkAudioIface->QueryInterface(iid, ppv); } #endif @@ -763,7 +756,6 @@ private: #else HANDLE mActiveClientEvent{nullptr}; - void** mPPV{nullptr}; EventRegistrationToken mRenderDeviceChangedToken; EventRegistrationToken mCaptureDeviceChangedToken; -- cgit v1.2.3 From a49b612ef470003ffb16ddc5e19c9a1984a71619 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 12 Jun 2023 09:52:10 -0700 Subject: Fix disabling debug events --- alc/events.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/events.cpp b/alc/events.cpp index b14b1a8d..6c91261c 100644 --- a/alc/events.cpp +++ b/alc/events.cpp @@ -85,7 +85,7 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const AL auto eventlock = std::unique_lock{alc::EventMutex}; if(enable) alc::EventsEnabled |= eventSet; - else alc::EventsEnabled &= eventSet; + else alc::EventsEnabled &= ~eventSet; return ALC_TRUE; } -- cgit v1.2.3 From ec8064d1001daf968a73c8bc4f6088e905488cb7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 12 Jun 2023 13:17:00 -0700 Subject: Trace the surround decoder being used --- alc/panning.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'alc') diff --git a/alc/panning.cpp b/alc/panning.cpp index 6fc955ee..46a840bd 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -979,28 +979,39 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optionalc_str()); + return false; } else if(conf.NumSpeakers > MAX_OUTPUT_CHANNELS) + { ERR("Unsupported decoder speaker count %zu (max %d)\n", conf.NumSpeakers, MAX_OUTPUT_CHANNELS); + return false; + } else if(conf.ChanMask > Ambi3OrderMask) + { ERR("Unsupported decoder channel mask 0x%04x (max 0x%x)\n", conf.ChanMask, Ambi3OrderMask); - else - { - device->mXOverFreq = clampf(conf.XOverFreq, 100.0f, 1000.0f); - - decoder_store = std::make_unique>(); - decoder = MakeDecoderView(device, &conf, *decoder_store); - for(size_t i{0};i < decoder.mChannels.size();++i) - speakerdists[i] = conf.Speakers[i].Distance; + return false; } + + TRACE("Using %s decoder: \"%s\"\n", DevFmtChannelsString(device->FmtChans), + conf.Description.c_str()); + device->mXOverFreq = clampf(conf.XOverFreq, 100.0f, 1000.0f); + + decoder_store = std::make_unique>(); + decoder = MakeDecoderView(device, &conf, *decoder_store); + for(size_t i{0};i < decoder.mChannels.size();++i) + speakerdists[i] = conf.Speakers[i].Distance; + return true; }; + bool usingCustom{false}; if(layout) { if(auto decopt = device->configValue("decoder", layout)) - load_config(decopt->c_str()); + usingCustom = load_config(decopt->c_str()); } + if(!usingCustom && device->FmtChans != DevFmtAmbi3D) + TRACE("Using built-in %s decoder\n", DevFmtChannelsString(device->FmtChans)); /* Enable the stablizer only for formats that have front-left, front- * right, and front-center outputs. -- cgit v1.2.3 From a318126ee33c47b3e017d4970b09eaf581f73004 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 14 Jun 2023 23:33:32 -0700 Subject: Use inline variables instead of functions with static variables --- alc/alu.cpp | 24 ++--- alc/effects/convolution.cpp | 24 ++--- alc/panning.cpp | 44 ++++----- core/ambidefs.h | 221 ++++++++++++++++++-------------------------- core/hrtf.cpp | 2 +- core/voice.cpp | 2 +- 6 files changed, 139 insertions(+), 178 deletions(-) (limited to 'alc') diff --git a/alc/alu.cpp b/alc/alu.cpp index 0130f280..5dfb4fae 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -376,28 +376,28 @@ void UpsampleBFormatTransform( } -inline auto& GetAmbiScales(AmbiScaling scaletype) noexcept +constexpr auto GetAmbiScales(AmbiScaling scaletype) noexcept { switch(scaletype) { - case AmbiScaling::FuMa: return AmbiScale::FromFuMa(); - case AmbiScaling::SN3D: return AmbiScale::FromSN3D(); - case AmbiScaling::UHJ: return AmbiScale::FromUHJ(); + case AmbiScaling::FuMa: return al::span{AmbiScale::FromFuMa}; + case AmbiScaling::SN3D: return al::span{AmbiScale::FromSN3D}; + case AmbiScaling::UHJ: return al::span{AmbiScale::FromUHJ}; case AmbiScaling::N3D: break; } - return AmbiScale::FromN3D(); + return al::span{AmbiScale::FromN3D}; } -inline auto& GetAmbiLayout(AmbiLayout layouttype) noexcept +constexpr auto GetAmbiLayout(AmbiLayout layouttype) noexcept { - if(layouttype == AmbiLayout::FuMa) return AmbiIndex::FromFuMa(); - return AmbiIndex::FromACN(); + if(layouttype == AmbiLayout::FuMa) return al::span{AmbiIndex::FromFuMa}; + return al::span{AmbiIndex::FromACN}; } -inline auto& GetAmbi2DLayout(AmbiLayout layouttype) noexcept +constexpr auto GetAmbi2DLayout(AmbiLayout layouttype) noexcept { - if(layouttype == AmbiLayout::FuMa) return AmbiIndex::FromFuMa2D(); - return AmbiIndex::FromACN2D(); + if(layouttype == AmbiLayout::FuMa) return al::span{AmbiIndex::FromFuMa2D}; + return al::span{AmbiIndex::FromACN2D}; } @@ -859,7 +859,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con */ return CalcAngleCoeffs(ScaleAzimuthFront(az, 1.5f), ev, 0.0f); }; - auto&& scales = GetAmbiScales(voice->mAmbiScaling); + const auto scales = GetAmbiScales(voice->mAmbiScaling); auto coeffs = calc_coeffs(Device->mRenderMode); if(!(coverage > 0.0f)) diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index 04b88f66..bc25963e 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -93,28 +93,28 @@ void LoadSamples(float *RESTRICT dst, const std::byte *src, const size_t srcstep } -inline auto& GetAmbiScales(AmbiScaling scaletype) noexcept +constexpr auto GetAmbiScales(AmbiScaling scaletype) noexcept { switch(scaletype) { - case AmbiScaling::FuMa: return AmbiScale::FromFuMa(); - case AmbiScaling::SN3D: return AmbiScale::FromSN3D(); - case AmbiScaling::UHJ: return AmbiScale::FromUHJ(); + case AmbiScaling::FuMa: return al::span{AmbiScale::FromFuMa}; + case AmbiScaling::SN3D: return al::span{AmbiScale::FromSN3D}; + case AmbiScaling::UHJ: return al::span{AmbiScale::FromUHJ}; case AmbiScaling::N3D: break; } - return AmbiScale::FromN3D(); + return al::span{AmbiScale::FromN3D}; } -inline auto& GetAmbiLayout(AmbiLayout layouttype) noexcept +constexpr auto GetAmbiLayout(AmbiLayout layouttype) noexcept { - if(layouttype == AmbiLayout::FuMa) return AmbiIndex::FromFuMa(); - return AmbiIndex::FromACN(); + if(layouttype == AmbiLayout::FuMa) return al::span{AmbiIndex::FromFuMa}; + return al::span{AmbiIndex::FromACN}; } -inline auto& GetAmbi2DLayout(AmbiLayout layouttype) noexcept +constexpr auto GetAmbi2DLayout(AmbiLayout layouttype) noexcept { - if(layouttype == AmbiLayout::FuMa) return AmbiIndex::FromFuMa2D(); - return AmbiIndex::FromACN2D(); + if(layouttype == AmbiLayout::FuMa) return al::span{AmbiIndex::FromFuMa2D}; + return al::span{AmbiIndex::FromACN2D}; } @@ -453,7 +453,7 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot } mOutTarget = target.Main->Buffer; - auto&& scales = GetAmbiScales(mAmbiScaling); + const auto scales = GetAmbiScales(mAmbiScaling); const uint8_t *index_map{Is2DAmbisonic(mChannels) ? GetAmbi2DLayout(mAmbiLayout).data() : GetAmbiLayout(mAmbiLayout).data()}; diff --git a/alc/panning.cpp b/alc/panning.cpp index 46a840bd..871fef65 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -314,17 +314,17 @@ void InitDistanceComp(ALCdevice *device, const al::span channels, } -inline auto& GetAmbiScales(DevAmbiScaling scaletype) noexcept +constexpr auto GetAmbiScales(DevAmbiScaling scaletype) noexcept { - if(scaletype == DevAmbiScaling::FuMa) return AmbiScale::FromFuMa(); - if(scaletype == DevAmbiScaling::SN3D) return AmbiScale::FromSN3D(); - return AmbiScale::FromN3D(); + if(scaletype == DevAmbiScaling::FuMa) return al::span{AmbiScale::FromFuMa}; + if(scaletype == DevAmbiScaling::SN3D) return al::span{AmbiScale::FromSN3D}; + return al::span{AmbiScale::FromN3D}; } -inline auto& GetAmbiLayout(DevAmbiLayout layouttype) noexcept +constexpr auto GetAmbiLayout(DevAmbiLayout layouttype) noexcept { - if(layouttype == DevAmbiLayout::FuMa) return AmbiIndex::FromFuMa(); - return AmbiIndex::FromACN(); + if(layouttype == DevAmbiLayout::FuMa) return al::span{AmbiIndex::FromFuMa}; + return al::span{AmbiIndex::FromACN}; } @@ -355,8 +355,8 @@ DecoderView MakeDecoderView(ALCdevice *device, const AmbDecConf *conf, const auto num_coeffs = decoder.mIs3D ? AmbiChannelsFromOrder(decoder.mOrder) : Ambi2DChannelsFromOrder(decoder.mOrder); - const auto idx_map = decoder.mIs3D ? AmbiIndex::FromACN().data() - : AmbiIndex::FromACN2D().data(); + const auto idx_map = decoder.mIs3D ? AmbiIndex::FromACN.data() + : AmbiIndex::FromACN2D.data(); const auto hfmatrix = conf->HFMatrix; const auto lfmatrix = conf->LFMatrix; @@ -601,13 +601,13 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= case DevFmtX714: decoder = X714Config; break; case DevFmtX3D71: decoder = X3D71Config; break; case DevFmtAmbi3D: - auto&& acnmap = GetAmbiLayout(device->mAmbiLayout); - auto&& n3dscale = GetAmbiScales(device->mAmbiScale); + const auto acnmap = GetAmbiLayout(device->mAmbiLayout); + const auto n3dscale = GetAmbiScales(device->mAmbiScale); /* For DevFmtAmbi3D, the ambisonic order is already set. */ const size_t count{AmbiChannelsFromOrder(device->mAmbiOrder)}; std::transform(acnmap.begin(), acnmap.begin()+count, std::begin(device->Dry.AmbiMap), - [&n3dscale](const uint8_t &acn) noexcept -> BFChannelConfig + [n3dscale](const uint8_t &acn) noexcept -> BFChannelConfig { return BFChannelConfig{1.0f/n3dscale[acn], acn}; }); AllocChannels(device, count, 0); device->m2DMixing = false; @@ -640,8 +640,8 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= continue; } - auto ordermap = decoder.mIs3D ? AmbiIndex::OrderFromChannel().data() - : AmbiIndex::OrderFrom2DChannel().data(); + auto ordermap = decoder.mIs3D ? AmbiIndex::OrderFromChannel.data() + : AmbiIndex::OrderFrom2DChannel.data(); chancoeffs.resize(maxz(chancoeffs.size(), idx+1u), ChannelDec{}); al::span src{decoder.mCoeffs[i]}; @@ -663,11 +663,11 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= device->mAmbiOrder = decoder.mOrder; device->m2DMixing = !decoder.mIs3D; - const al::span acnmap{decoder.mIs3D ? AmbiIndex::FromACN().data() : - AmbiIndex::FromACN2D().data(), ambicount}; - auto&& coeffscale = GetAmbiScales(decoder.mScaling); + const al::span acnmap{decoder.mIs3D ? AmbiIndex::FromACN.data() : + AmbiIndex::FromACN2D.data(), ambicount}; + const auto coeffscale = GetAmbiScales(decoder.mScaling); std::transform(acnmap.begin(), acnmap.end(), std::begin(device->Dry.AmbiMap), - [&coeffscale](const uint8_t &acn) noexcept + [coeffscale](const uint8_t &acn) noexcept { return BFChannelConfig{1.0f/coeffscale[acn], acn}; }); AllocChannels(device, ambicount, device->channelsFromFmt()); @@ -902,7 +902,7 @@ void InitHrtfPanning(ALCdevice *device) device->m2DMixing = false; const size_t count{AmbiChannelsFromOrder(ambi_order)}; - std::transform(AmbiIndex::FromACN().begin(), AmbiIndex::FromACN().begin()+count, + std::transform(AmbiIndex::FromACN.begin(), AmbiIndex::FromACN.begin()+count, std::begin(device->Dry.AmbiMap), [](const uint8_t &index) noexcept { return BFChannelConfig{1.0f, index}; } ); @@ -925,10 +925,10 @@ void InitUhjPanning(ALCdevice *device) device->mAmbiOrder = 1; device->m2DMixing = true; - auto acnmap_begin = AmbiIndex::FromFuMa2D().begin(); + auto acnmap_begin = AmbiIndex::FromFuMa2D.begin(); std::transform(acnmap_begin, acnmap_begin + count, std::begin(device->Dry.AmbiMap), [](const uint8_t &acn) noexcept -> BFChannelConfig - { return BFChannelConfig{1.0f/AmbiScale::FromUHJ()[acn], acn}; }); + { return BFChannelConfig{1.0f/AmbiScale::FromUHJ[acn], acn}; }); AllocChannels(device, count, device->channelsFromFmt()); } @@ -1155,7 +1155,7 @@ void aluInitEffectPanning(EffectSlot *slot, ALCcontext *context) slot->mWetBuffer.resize(count); - auto acnmap_begin = AmbiIndex::FromACN().begin(); + auto acnmap_begin = AmbiIndex::FromACN.begin(); auto iter = std::transform(acnmap_begin, acnmap_begin + count, slot->Wet.AmbiMap.begin(), [](const uint8_t &acn) noexcept -> BFChannelConfig { return BFChannelConfig{1.0f, acn}; }); diff --git a/core/ambidefs.h b/core/ambidefs.h index 3af26258..bea1a312 100644 --- a/core/ambidefs.h +++ b/core/ambidefs.h @@ -48,70 +48,54 @@ inline constexpr size_t MaxAmbi2DChannels{Ambi2DChannelsFromOrder(MaxAmbiOrder)} * coefficients should be divided by these values to get proper scalings. */ struct AmbiScale { - static auto& FromN3D() noexcept - { - static constexpr const std::array ret{{ - 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f - }}; - return ret; - } - static auto& FromSN3D() noexcept - { - static constexpr const std::array ret{{ - 1.000000000f, /* ACN 0, sqrt(1) */ - 1.732050808f, /* ACN 1, sqrt(3) */ - 1.732050808f, /* ACN 2, sqrt(3) */ - 1.732050808f, /* ACN 3, sqrt(3) */ - 2.236067978f, /* ACN 4, sqrt(5) */ - 2.236067978f, /* ACN 5, sqrt(5) */ - 2.236067978f, /* ACN 6, sqrt(5) */ - 2.236067978f, /* ACN 7, sqrt(5) */ - 2.236067978f, /* ACN 8, sqrt(5) */ - 2.645751311f, /* ACN 9, sqrt(7) */ - 2.645751311f, /* ACN 10, sqrt(7) */ - 2.645751311f, /* ACN 11, sqrt(7) */ - 2.645751311f, /* ACN 12, sqrt(7) */ - 2.645751311f, /* ACN 13, sqrt(7) */ - 2.645751311f, /* ACN 14, sqrt(7) */ - 2.645751311f, /* ACN 15, sqrt(7) */ - }}; - return ret; - } - static auto& FromFuMa() noexcept - { - static constexpr const std::array ret{{ - 1.414213562f, /* ACN 0 (W), sqrt(2) */ - 1.732050808f, /* ACN 1 (Y), sqrt(3) */ - 1.732050808f, /* ACN 2 (Z), sqrt(3) */ - 1.732050808f, /* ACN 3 (X), sqrt(3) */ - 1.936491673f, /* ACN 4 (V), sqrt(15)/2 */ - 1.936491673f, /* ACN 5 (T), sqrt(15)/2 */ - 2.236067978f, /* ACN 6 (R), sqrt(5) */ - 1.936491673f, /* ACN 7 (S), sqrt(15)/2 */ - 1.936491673f, /* ACN 8 (U), sqrt(15)/2 */ - 2.091650066f, /* ACN 9 (Q), sqrt(35/8) */ - 1.972026594f, /* ACN 10 (O), sqrt(35)/3 */ - 2.231093404f, /* ACN 11 (M), sqrt(224/45) */ - 2.645751311f, /* ACN 12 (K), sqrt(7) */ - 2.231093404f, /* ACN 13 (L), sqrt(224/45) */ - 1.972026594f, /* ACN 14 (N), sqrt(35)/3 */ - 2.091650066f, /* ACN 15 (P), sqrt(35/8) */ - }}; - return ret; - } - static auto& FromUHJ() noexcept - { - static constexpr const std::array ret{{ - 1.000000000f, /* ACN 0 (W), sqrt(1) */ - 1.224744871f, /* ACN 1 (Y), sqrt(3/2) */ - 1.224744871f, /* ACN 2 (Z), sqrt(3/2) */ - 1.224744871f, /* ACN 3 (X), sqrt(3/2) */ - /* Higher orders not relevant for UHJ. */ - 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - }}; - return ret; - } + static inline constexpr std::array FromN3D{{ + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f + }}; + static inline constexpr std::array FromSN3D{{ + 1.000000000f, /* ACN 0, sqrt(1) */ + 1.732050808f, /* ACN 1, sqrt(3) */ + 1.732050808f, /* ACN 2, sqrt(3) */ + 1.732050808f, /* ACN 3, sqrt(3) */ + 2.236067978f, /* ACN 4, sqrt(5) */ + 2.236067978f, /* ACN 5, sqrt(5) */ + 2.236067978f, /* ACN 6, sqrt(5) */ + 2.236067978f, /* ACN 7, sqrt(5) */ + 2.236067978f, /* ACN 8, sqrt(5) */ + 2.645751311f, /* ACN 9, sqrt(7) */ + 2.645751311f, /* ACN 10, sqrt(7) */ + 2.645751311f, /* ACN 11, sqrt(7) */ + 2.645751311f, /* ACN 12, sqrt(7) */ + 2.645751311f, /* ACN 13, sqrt(7) */ + 2.645751311f, /* ACN 14, sqrt(7) */ + 2.645751311f, /* ACN 15, sqrt(7) */ + }}; + static inline constexpr std::array FromFuMa{{ + 1.414213562f, /* ACN 0 (W), sqrt(2) */ + 1.732050808f, /* ACN 1 (Y), sqrt(3) */ + 1.732050808f, /* ACN 2 (Z), sqrt(3) */ + 1.732050808f, /* ACN 3 (X), sqrt(3) */ + 1.936491673f, /* ACN 4 (V), sqrt(15)/2 */ + 1.936491673f, /* ACN 5 (T), sqrt(15)/2 */ + 2.236067978f, /* ACN 6 (R), sqrt(5) */ + 1.936491673f, /* ACN 7 (S), sqrt(15)/2 */ + 1.936491673f, /* ACN 8 (U), sqrt(15)/2 */ + 2.091650066f, /* ACN 9 (Q), sqrt(35/8) */ + 1.972026594f, /* ACN 10 (O), sqrt(35)/3 */ + 2.231093404f, /* ACN 11 (M), sqrt(224/45) */ + 2.645751311f, /* ACN 12 (K), sqrt(7) */ + 2.231093404f, /* ACN 13 (L), sqrt(224/45) */ + 1.972026594f, /* ACN 14 (N), sqrt(35)/3 */ + 2.091650066f, /* ACN 15 (P), sqrt(35/8) */ + }}; + static inline constexpr std::array FromUHJ{{ + 1.000000000f, /* ACN 0 (W), sqrt(1) */ + 1.224744871f, /* ACN 1 (Y), sqrt(3/2) */ + 1.224744871f, /* ACN 2 (Z), sqrt(3/2) */ + 1.224744871f, /* ACN 3 (X), sqrt(3/2) */ + /* Higher orders not relevant for UHJ. */ + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + }}; /* Retrieves per-order HF scaling factors for "upsampling" ambisonic data. */ static std::array GetHFOrderScales(const uint src_order, @@ -127,72 +111,49 @@ struct AmbiScale { }; struct AmbiIndex { - static auto& FromFuMa() noexcept - { - static constexpr const std::array ret{{ - 0, /* W */ - 3, /* X */ - 1, /* Y */ - 2, /* Z */ - 6, /* R */ - 7, /* S */ - 5, /* T */ - 8, /* U */ - 4, /* V */ - 12, /* K */ - 13, /* L */ - 11, /* M */ - 14, /* N */ - 10, /* O */ - 15, /* P */ - 9, /* Q */ - }}; - return ret; - } - static auto& FromFuMa2D() noexcept - { - static constexpr const std::array ret{{ - 0, /* W */ - 3, /* X */ - 1, /* Y */ - 8, /* U */ - 4, /* V */ - 15, /* P */ - 9, /* Q */ - }}; - return ret; - } - - static auto& FromACN() noexcept - { - static constexpr const std::array ret{{ - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15 - }}; - return ret; - } - static auto& FromACN2D() noexcept - { - static constexpr const std::array ret{{ - 0, 1,3, 4,8, 9,15 - }}; - return ret; - } - - static auto& OrderFromChannel() noexcept - { - static constexpr const std::array ret{{ - 0, 1,1,1, 2,2,2,2,2, 3,3,3,3,3,3,3, - }}; - return ret; - } - static auto& OrderFrom2DChannel() noexcept - { - static constexpr const std::array ret{{ - 0, 1,1, 2,2, 3,3, - }}; - return ret; - } + static inline constexpr std::array FromFuMa{{ + 0, /* W */ + 3, /* X */ + 1, /* Y */ + 2, /* Z */ + 6, /* R */ + 7, /* S */ + 5, /* T */ + 8, /* U */ + 4, /* V */ + 12, /* K */ + 13, /* L */ + 11, /* M */ + 14, /* N */ + 10, /* O */ + 15, /* P */ + 9, /* Q */ + }}; + static inline constexpr std::array FromFuMa2D{{ + 0, /* W */ + 3, /* X */ + 1, /* Y */ + 8, /* U */ + 4, /* V */ + 15, /* P */ + 9, /* Q */ + }}; + + static inline constexpr std::array FromACN{{ + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15 + }}; + static inline constexpr std::array FromACN2D{{ + 0, 1,3, 4,8, 9,15 + }}; + + + static inline constexpr std::array OrderFromChannel{{ + 0, 1,1,1, 2,2,2,2,2, 3,3,3,3,3,3,3, + }}; + static inline constexpr std::array OrderFrom2DChannel{{ + 0, 1,1, 2,2, 3,3, + }}; }; diff --git a/core/hrtf.cpp b/core/hrtf.cpp index 7d11ee19..f131e72d 100644 --- a/core/hrtf.cpp +++ b/core/hrtf.cpp @@ -289,7 +289,7 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const uint irSize, const bool mChannels[0].mSplitter.init(static_cast(xover_norm)); for(size_t i{0};i < mChannels.size();++i) { - const size_t order{AmbiIndex::OrderFromChannel()[i]}; + const size_t order{AmbiIndex::OrderFromChannel[i]}; mChannels[i].mSplitter = mChannels[0].mSplitter; mChannels[i].mHfScale = AmbiOrderHFGain[order]; } diff --git a/core/voice.cpp b/core/voice.cpp index 65986cd1..92da3e76 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -1273,7 +1273,7 @@ void Voice::prepare(DeviceBase *device) else if(mAmbiOrder && device->mAmbiOrder > mAmbiOrder) { const uint8_t *OrderFromChan{Is2DAmbisonic(mFmtChannels) ? - AmbiIndex::OrderFrom2DChannel().data() : AmbiIndex::OrderFromChannel().data()}; + AmbiIndex::OrderFrom2DChannel.data() : AmbiIndex::OrderFromChannel.data()}; const auto scales = AmbiScale::GetHFOrderScales(mAmbiOrder, device->mAmbiOrder, device->m2DMixing); -- cgit v1.2.3 From 2da9d168b6bee32376889a394e11981a4515d041 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 27 Jun 2023 05:53:35 -0700 Subject: Set the correct dev format when autodetecting 7.1.4 in WASAPI --- alc/backends/wasapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index b68a59e2..c5282fcb 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -1272,7 +1272,7 @@ HRESULT WasapiPlayback::resetProxy() const uint32_t chancount{OutputType.Format.nChannels}; const DWORD chanmask{OutputType.dwChannelMask}; if(chancount >= 12 && (chanmask&X714Mask) == X7DOT1DOT4) - mDevice->FmtChans = DevFmtX71; + mDevice->FmtChans = DevFmtX714; else if(chancount >= 8 && (chanmask&X71Mask) == X7DOT1) mDevice->FmtChans = DevFmtX71; else if(chancount >= 7 && (chanmask&X61Mask) == X6DOT1) -- cgit v1.2.3 From e714c8fbca7bc4a03be308d43d6d6cd5e57914bc Mon Sep 17 00:00:00 2001 From: "Deal(一线灵)" Date: Wed, 28 Jun 2023 16:10:49 +0800 Subject: [UWP] Fix crash when probe capture device fail (#868) * [UWP] Fix crash when probe capture device fail * [UWP] Also check openDevice to avoid crash --- alc/backends/wasapi.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index c5282fcb..dccbeba2 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -577,7 +577,8 @@ struct DeviceHelper final : private IMMNotificationClient Platform::String^ devIfPath = devid.empty() ? (flow == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole)) : ref new Platform::String(devid.data()); - + if (!devIfPath) + return E_POINTER; Concurrency::task createDeviceOp( DeviceInformation::CreateFromIdAsync(devIfPath, nullptr, DeviceInformationKind::DeviceInterface)); auto status = createDeviceOp.then([&](DeviceInformation^ deviceInfo) @@ -674,6 +675,8 @@ struct DeviceHelper final : private IMMNotificationClient const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; auto DefaultAudioId = flowdir == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole); + if (!DefaultAudioId) + return defaultId; Concurrency::task createDefaultOp(DeviceInformation::CreateFromIdAsync(DefaultAudioId, nullptr, DeviceInformationKind::DeviceInterface)); auto task_status = createDefaultOp.then([&defaultId](DeviceInformation ^ deviceInfo) { -- cgit v1.2.3 From 0cad3f7391959d1ad83f948df37db608e3f0e72c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 29 Jun 2023 02:37:08 -0700 Subject: Specify a callback using a lambda --- alc/backends/sdl2.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'alc') diff --git a/alc/backends/sdl2.cpp b/alc/backends/sdl2.cpp index a4a5a9ac..e1e40e27 100644 --- a/alc/backends/sdl2.cpp +++ b/alc/backends/sdl2.cpp @@ -53,8 +53,6 @@ struct Sdl2Backend final : public BackendBase { ~Sdl2Backend() override; void audioCallback(Uint8 *stream, int len) noexcept; - static void audioCallbackC(void *ptr, Uint8 *stream, int len) noexcept - { static_cast(ptr)->audioCallback(stream, len); } void open(const char *name) override; bool reset() override; @@ -103,7 +101,8 @@ void Sdl2Backend::open(const char *name) } want.channels = (mDevice->FmtChans == DevFmtMono) ? 1 : 2; want.samples = static_cast(minu(mDevice->UpdateSize, 8192)); - want.callback = &Sdl2Backend::audioCallbackC; + want.callback = [](void *ptr, Uint8 *stream, int len) noexcept + { return static_cast(ptr)->audioCallback(stream, len); }; want.userdata = this; /* Passing nullptr to SDL_OpenAudioDevice opens a default, which isn't -- cgit v1.2.3 From 548f7ad80abc253a38171b7e4eb1c84a6b179a41 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 1 Jul 2023 06:07:11 -0700 Subject: Don't pass the file handle to al_print --- alc/alc.cpp | 7 ------- core/logging.cpp | 12 +++++++++++- core/logging.h | 18 +++++++++--------- 3 files changed, 20 insertions(+), 17 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index e6c2f137..0e1dc637 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -162,13 +162,6 @@ #endif // ALSOFT_EAX -FILE *gLogFile{stderr}; -#ifdef _DEBUG -LogLevel gLogLevel{LogLevel::Warning}; -#else -LogLevel gLogLevel{LogLevel::Error}; -#endif - /************************************************ * Library initialization ************************************************/ diff --git a/core/logging.cpp b/core/logging.cpp index 34385cf4..b6248514 100644 --- a/core/logging.cpp +++ b/core/logging.cpp @@ -19,7 +19,16 @@ #include #endif -void al_print(LogLevel level, FILE *logfile, const char *fmt, ...) + +FILE *gLogFile{stderr}; +#ifdef _DEBUG +LogLevel gLogLevel{LogLevel::Warning}; +#else +LogLevel gLogLevel{LogLevel::Error}; +#endif + + +void al_print(LogLevel level, const char *fmt, ...) { /* Kind of ugly since string literals are const char arrays with a size * that includes the null terminator, which we want to exclude from the @@ -60,6 +69,7 @@ void al_print(LogLevel level, FILE *logfile, const char *fmt, ...) if(gLogLevel >= level) { + auto logfile = gLogFile; fputs(str, logfile); fflush(logfile); } diff --git a/core/logging.h b/core/logging.h index f4b6ab56..c99c4e45 100644 --- a/core/logging.h +++ b/core/logging.h @@ -17,35 +17,35 @@ extern LogLevel gLogLevel; extern FILE *gLogFile; #ifdef __USE_MINGW_ANSI_STDIO -[[gnu::format(gnu_printf,3,4)]] +[[gnu::format(gnu_printf,2,3)]] #else -[[gnu::format(printf,3,4)]] +[[gnu::format(printf,2,3)]] #endif -void al_print(LogLevel level, FILE *logfile, const char *fmt, ...); +void al_print(LogLevel level, const char *fmt, ...); #if (!defined(_WIN32) || defined(NDEBUG)) && !defined(__ANDROID__) #define TRACE(...) do { \ if(gLogLevel >= LogLevel::Trace) UNLIKELY \ - al_print(LogLevel::Trace, gLogFile, __VA_ARGS__); \ + al_print(LogLevel::Trace, __VA_ARGS__); \ } while(0) #define WARN(...) do { \ if(gLogLevel >= LogLevel::Warning) UNLIKELY \ - al_print(LogLevel::Warning, gLogFile, __VA_ARGS__); \ + al_print(LogLevel::Warning, __VA_ARGS__); \ } while(0) #define ERR(...) do { \ if(gLogLevel >= LogLevel::Error) UNLIKELY \ - al_print(LogLevel::Error, gLogFile, __VA_ARGS__); \ + al_print(LogLevel::Error, __VA_ARGS__); \ } while(0) #else -#define TRACE(...) al_print(LogLevel::Trace, gLogFile, __VA_ARGS__) +#define TRACE(...) al_print(LogLevel::Trace, __VA_ARGS__) -#define WARN(...) al_print(LogLevel::Warning, gLogFile, __VA_ARGS__) +#define WARN(...) al_print(LogLevel::Warning, __VA_ARGS__) -#define ERR(...) al_print(LogLevel::Error, gLogFile, __VA_ARGS__) +#define ERR(...) al_print(LogLevel::Error, __VA_ARGS__) #endif #endif /* CORE_LOGGING_H */ -- cgit v1.2.3 From 65d0196db6f09292c3eb3c106d6ca543ad937e82 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 2 Jul 2023 13:21:48 -0700 Subject: Add a function to set a callback for log messages --- alc/alc.cpp | 5 ++++ alc/export_list.h | 2 ++ alc/inprogext.h | 4 ++- core/logging.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++---- core/logging.h | 25 ++++------------- 5 files changed, 92 insertions(+), 26 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index 0e1dc637..d36f1891 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -1846,6 +1846,11 @@ ContextRef VerifyContext(ALCcontext *context) } // namespace +FORCE_ALIGN void ALC_APIENTRY alsoft_set_log_callback(LPALSOFTLOGCALLBACK callback, void *userptr) noexcept +{ + al_set_log_callback(callback, userptr); +} + /** Returns a new reference to the currently active context for this thread. */ ContextRef GetContextRef(void) { diff --git a/alc/export_list.h b/alc/export_list.h index 7b347e76..8bedd850 100644 --- a/alc/export_list.h +++ b/alc/export_list.h @@ -367,6 +367,8 @@ inline const FuncExport alcFunctions[]{ DECL(alcEventControlSOFT), DECL(alcEventCallbackSOFT), + + DECL(alsoft_set_log_callback), #ifdef ALSOFT_EAX }, eaxFunctions[]{ DECL(EAXGet), diff --git a/alc/inprogext.h b/alc/inprogext.h index 65e34ea4..60c97536 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -460,9 +460,11 @@ void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *user #endif #endif -/* Non-standard export. Not part of any extension. */ +/* Non-standard exports. Not part of any extension. */ AL_API const ALchar* AL_APIENTRY alsoft_get_version(void) noexcept; +typedef void (ALC_APIENTRY*LPALSOFTLOGCALLBACK)(void *userptr, char level, const char *message, int length) noexcept; +void ALC_APIENTRY alsoft_set_log_callback(LPALSOFTLOGCALLBACK callback, void *userptr) noexcept; /* Functions from abandoned extensions. Only here for binary compatibility. */ AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint src, ALsizei nb, diff --git a/core/logging.cpp b/core/logging.cpp index b6248514..56ad0a0d 100644 --- a/core/logging.cpp +++ b/core/logging.cpp @@ -3,8 +3,12 @@ #include "logging.h" +#include #include #include +#include +#include +#include #include #include @@ -28,6 +32,49 @@ LogLevel gLogLevel{LogLevel::Error}; #endif +namespace { + +enum class LogState : uint8_t { + FirstRun, + Ready, + Disable +}; + +std::mutex LogCallbackMutex; +LogState gLogState{LogState::FirstRun}; + +LogCallbackFunc gLogCallback{}; +void *gLogCallbackPtr{}; + +constexpr std::optional GetLevelCode(LogLevel level) +{ + switch(level) + { + case LogLevel::Disable: break; + case LogLevel::Error: return 'E'; + case LogLevel::Warning: return 'W'; + case LogLevel::Trace: return 'I'; + } + return std::nullopt; +} + +} // namespace + +void al_set_log_callback(LogCallbackFunc callback, void *userptr) +{ + auto cblock = std::lock_guard{LogCallbackMutex}; + gLogCallback = callback; + gLogCallbackPtr = callback ? userptr : nullptr; + if(gLogState == LogState::FirstRun) + { + auto extlogopt = al::getenv("ALSOFT_DISABLE_LOG_CALLBACK"); + if(!extlogopt || *extlogopt != "1") + gLogState = LogState::Ready; + else + gLogState = LogState::Disable; + } +} + void al_print(LogLevel level, const char *fmt, ...) { /* Kind of ugly since string literals are const char arrays with a size @@ -54,16 +101,22 @@ void al_print(LogLevel level, const char *fmt, ...) va_start(args, fmt); va_copy(args2, args); const int msglen{std::vsnprintf(msg.data(), msg.size(), fmt, args)}; - if(msglen >= 0 && static_cast(msglen) >= msg.size()) UNLIKELY + if(msglen >= 0) { - dynmsg.resize(static_cast(msglen)+prefix.size() + 1u); + if(static_cast(msglen) >= msg.size()) UNLIKELY + { + dynmsg.resize(static_cast(msglen)+prefix.size() + 1u); - str = dynmsg.data(); - auto prefend2 = std::copy_n(prefix.begin(), prefix.size(), dynmsg.begin()); - msg = {prefend2, dynmsg.end()}; + str = dynmsg.data(); + auto prefend2 = std::copy_n(prefix.begin(), prefix.size(), dynmsg.begin()); + msg = {prefend2, dynmsg.end()}; - std::vsnprintf(msg.data(), msg.size(), fmt, args2); + std::vsnprintf(msg.data(), msg.size(), fmt, args2); + } + msg = msg.first(static_cast(msglen)); } + else + msg = {msg.data(), std::strlen(msg.data())}; va_end(args2); va_end(args); @@ -96,4 +149,21 @@ void al_print(LogLevel level, const char *fmt, ...) }; __android_log_print(android_severity(level), "openal", "%s", str); #endif + + auto cblock = std::lock_guard{LogCallbackMutex}; + if(gLogState != LogState::Disable) + { + while(!msg.empty() && std::isspace(msg.back())) + { + msg.back() = '\0'; + msg = msg.first(msg.size()-1); + } + if(auto logcode = GetLevelCode(level); logcode && !msg.empty()) + { + if(gLogCallback) + gLogCallback(gLogCallbackPtr, *logcode, msg.data(), static_cast(msg.size())); + else if(gLogState == LogState::FirstRun) + gLogState = LogState::Disable; + } + } } diff --git a/core/logging.h b/core/logging.h index c99c4e45..06b7cdde 100644 --- a/core/logging.h +++ b/core/logging.h @@ -16,6 +16,12 @@ extern LogLevel gLogLevel; extern FILE *gLogFile; + +using LogCallbackFunc = void(*)(void *userptr, char level, const char *message, int length) noexcept; + +void al_set_log_callback(LogCallbackFunc callback, void *userptr); + + #ifdef __USE_MINGW_ANSI_STDIO [[gnu::format(gnu_printf,2,3)]] #else @@ -23,29 +29,10 @@ extern FILE *gLogFile; #endif void al_print(LogLevel level, const char *fmt, ...); -#if (!defined(_WIN32) || defined(NDEBUG)) && !defined(__ANDROID__) -#define TRACE(...) do { \ - if(gLogLevel >= LogLevel::Trace) UNLIKELY \ - al_print(LogLevel::Trace, __VA_ARGS__); \ -} while(0) - -#define WARN(...) do { \ - if(gLogLevel >= LogLevel::Warning) UNLIKELY \ - al_print(LogLevel::Warning, __VA_ARGS__); \ -} while(0) - -#define ERR(...) do { \ - if(gLogLevel >= LogLevel::Error) UNLIKELY \ - al_print(LogLevel::Error, __VA_ARGS__); \ -} while(0) - -#else - #define TRACE(...) al_print(LogLevel::Trace, __VA_ARGS__) #define WARN(...) al_print(LogLevel::Warning, __VA_ARGS__) #define ERR(...) al_print(LogLevel::Error, __VA_ARGS__) -#endif #endif /* CORE_LOGGING_H */ -- cgit v1.2.3 From 830a8d7e13be369ecc61d6938da3ee8a47c461a3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 4 Jul 2023 11:31:33 -0700 Subject: Fix a comment typo --- alc/backends/opensl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp index 2a161056..58e78459 100644 --- a/alc/backends/opensl.cpp +++ b/alc/backends/opensl.cpp @@ -934,7 +934,7 @@ void OpenSLCapture::captureSamples(std::byte *buffer, uint samples) return; /* For each buffer chunk that was fully read, queue another writable buffer - * chunk to keep the OpenSL queue full. This is rather convulated, as a + * chunk to keep the OpenSL queue full. This is rather convoluted, as a * result of the ring buffer holding more elements than are writable at a * given time. The end of the write vector increments when the read pointer * advances, which will "expose" a previously unwritable element. So for -- cgit v1.2.3 From e6e6a1c003ec2d80b5b11f8479ad95a4826bff89 Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Wed, 5 Jul 2023 01:48:52 +0200 Subject: Fix some typos (#872) --- CMakeLists.txt | 4 ++-- al/buffer.cpp | 2 +- al/eax/api.h | 2 +- al/source.cpp | 6 +++--- alc/alu.cpp | 2 +- alc/backends/pipewire.cpp | 2 +- alc/backends/sndio.cpp | 2 +- alc/backends/winmm.cpp | 4 ++-- alc/effects/reverb.cpp | 4 ++-- core/filters/nfc.h | 2 +- core/helpers.cpp | 2 +- docs/ambisonics.txt | 4 ++-- examples/alconvolve.c | 4 ++-- examples/alhrtf.c | 2 +- examples/allatency.c | 2 +- examples/alloopback.c | 2 +- examples/almultireverb.c | 6 +++--- examples/alplay.c | 2 +- examples/alreverb.c | 4 ++-- examples/altonegen.c | 2 +- 20 files changed, 30 insertions(+), 30 deletions(-) (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index af25a96c..f458f3e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,7 +171,7 @@ elseif(APPLE) endif() -# QNX's gcc do not uses /usr/include and /usr/lib pathes by default +# QNX's gcc do not uses /usr/include and /usr/lib paths by default if("${CMAKE_C_PLATFORM_ID}" STREQUAL "QNX") set(INC_PATHS ${INC_PATHS} /usr/include) set(LINKER_FLAGS ${LINKER_FLAGS} -L/usr/lib) @@ -539,7 +539,7 @@ if(HAVE_LIBRT) set(RT_LIB rt) endif() -# Check for the dlopen API (for dynamicly loading backend libs) +# Check for the dlopen API (for dynamically loading backend libs) if(ALSOFT_DLOPEN) check_include_file(dlfcn.h HAVE_DLFCN_H) check_library_exists(dl dlopen "" HAVE_LIBDL) diff --git a/al/buffer.cpp b/al/buffer.cpp index edca56ad..01f61793 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -873,7 +873,7 @@ FORCE_ALIGN void AL_APIENTRY alFlushMappedBufferDirectSOFT(ALCcontext *context, else { /* FIXME: Need to use some method of double-buffering for the mixer and - * app to hold separate memory, which can be safely transfered + * app to hold separate memory, which can be safely transferred * asynchronously. Currently we just say the app shouldn't write where * OpenAL's reading, and hope for the best... */ diff --git a/al/eax/api.h b/al/eax/api.h index 8795d833..18d93ef8 100644 --- a/al/eax/api.h +++ b/al/eax/api.h @@ -614,7 +614,7 @@ struct EAX30SOURCEPROPERTIES { float flOcclusionLFRatio; // occlusion low-frequency level re. main control float flOcclusionRoomRatio; // relative occlusion control for room effect float flOcclusionDirectRatio; // relative occlusion control for direct path - long lExclusion; // main exlusion control (attenuation at high frequencies) + long lExclusion; // main exclusion control (attenuation at high frequencies) float flExclusionLFRatio; // exclusion low-frequency level re. main control long lOutsideVolumeHF; // outside sound cone level at high frequencies float flDopplerFactor; // like DS3D flDopplerFactor but per source diff --git a/al/source.cpp b/al/source.cpp index 7e425d43..adea9715 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -434,7 +434,7 @@ struct VoicePos { * GetSampleOffset * * Retrieves the voice position, fixed-point fraction, and bufferlist item - * using the givem offset type and offset. If the offset is out of range, + * using the given offset type and offset. If the offset is out of range, * returns an empty optional. */ std::optional GetSampleOffset(al::deque &BufferList, @@ -3870,7 +3870,7 @@ void ALsource::eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept dst.source.ulFlags = src.dwFlags; dst.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR; - // Set everyting else to defaults. + // Set everything else to defaults. // eax5_set_sends_defaults(dst.sends); eax5_set_active_fx_slots_defaults(dst.active_fx_slots); @@ -3884,7 +3884,7 @@ void ALsource::eax3_translate(const Eax3Props& src, Eax5Props& dst) noexcept static_cast(dst.source) = src; dst.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR; - // Set everyting else to defaults. + // Set everything else to defaults. // eax5_set_sends_defaults(dst.sends); eax5_set_active_fx_slots_defaults(dst.active_fx_slots); diff --git a/alc/alu.cpp b/alc/alu.cpp index 5dfb4fae..8a4df3d4 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -1853,7 +1853,7 @@ void ProcessContexts(DeviceBase *device, const uint SamplesToDo) const EffectSlotArray &auxslots = *ctx->mActiveAuxSlots.load(std::memory_order_acquire); const al::span voices{ctx->getVoicesSpanAcquired()}; - /* Process pending propery updates for objects on the context. */ + /* Process pending property updates for objects on the context. */ ProcessParamUpdates(ctx, auxslots, voices); /* Clear auxiliary effect slot mixing buffers. */ diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 2bee4d7d..aac67ba2 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -1836,7 +1836,7 @@ ClockLatency PipeWirePlayback::getClockLatency() delay -= monoclock - nanoseconds{ptime.now}; /* Return the mixer time and delay. Clamp the delay to no less than 0, - * incase timer drift got that severe. + * in case timer drift got that severe. */ ClockLatency ret{}; ret.ClockTime = mixtime; diff --git a/alc/backends/sndio.cpp b/alc/backends/sndio.cpp index 89eee941..8daa928c 100644 --- a/alc/backends/sndio.cpp +++ b/alc/backends/sndio.cpp @@ -436,7 +436,7 @@ void SndioCapture::open(const char *name) if(!sio_setpar(mSndHandle, &par) || !sio_getpar(mSndHandle, &par)) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to set device praameters"}; + "Failed to set device parameters"}; if(par.bps > 1 && par.le != SIO_LE_NATIVE) throw al::backend_exception{al::backend_error::DeviceError, diff --git a/alc/backends/winmm.cpp b/alc/backends/winmm.cpp index 661585cd..c22f1c4d 100644 --- a/alc/backends/winmm.cpp +++ b/alc/backends/winmm.cpp @@ -167,7 +167,7 @@ WinMMPlayback::~WinMMPlayback() /* WinMMPlayback::waveOutProc * - * Posts a message to 'WinMMPlayback::mixerProc' everytime a WaveOut Buffer is + * Posts a message to 'WinMMPlayback::mixerProc' every time a WaveOut Buffer is * completed and returns to the application (for more data) */ void CALLBACK WinMMPlayback::waveOutProc(HWAVEOUT, UINT msg, DWORD_PTR, DWORD_PTR) noexcept @@ -406,7 +406,7 @@ WinMMCapture::~WinMMCapture() /* WinMMCapture::waveInProc * - * Posts a message to 'WinMMCapture::captureProc' everytime a WaveIn Buffer is + * Posts a message to 'WinMMCapture::captureProc' every time a WaveIn Buffer is * completed and returns to the application (with more data). */ void CALLBACK WinMMCapture::waveInProc(HWAVEIN, UINT msg, DWORD_PTR, DWORD_PTR) noexcept diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index 3875bedb..330c404d 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -643,8 +643,8 @@ inline float CalcDelayLengthMult(float density) */ void ReverbState::allocLines(const float frequency) { - /* All delay line lengths are calculated to accomodate the full range of - * lengths given their respective paramters. + /* All delay line lengths are calculated to accommodate the full range of + * lengths given their respective parameters. */ size_t totalSamples{0u}; diff --git a/core/filters/nfc.h b/core/filters/nfc.h index 33f67a5f..4b8e68b5 100644 --- a/core/filters/nfc.h +++ b/core/filters/nfc.h @@ -39,7 +39,7 @@ public: * w1 = speed_of_sound / (control_distance * sample_rate); * * Generally speaking, the control distance should be approximately the - * average speaker distance, or based on the reference delay if outputing + * average speaker distance, or based on the reference delay if outputting * NFC-HOA. It must not be negative, 0, or infinite. The source distance * should not be too small relative to the control distance. */ diff --git a/core/helpers.cpp b/core/helpers.cpp index 2eccc50f..0d36048c 100644 --- a/core/helpers.cpp +++ b/core/helpers.cpp @@ -23,7 +23,7 @@ #include "strutils.h" -/* Mixing thread piority level */ +/* Mixing thread priority level */ int RTPrioLevel{1}; /* Allow reducing the process's RTTime limit for RTKit. */ diff --git a/docs/ambisonics.txt b/docs/ambisonics.txt index b1b111d6..7798c8f9 100644 --- a/docs/ambisonics.txt +++ b/docs/ambisonics.txt @@ -12,7 +12,7 @@ What Is It? Originally developed in the 1970s by Michael Gerzon and a team others, Ambisonics was created as a means of recording and playing back 3D sound. -Taking advantage of the way sound waves propogate, it is possible to record a +Taking advantage of the way sound waves propagate, it is possible to record a fully 3D soundfield using as few as 4 channels (or even just 3, if you don't mind dropping down to 2 dimensions like many surround sound systems are). This representation is called B-Format. It was designed to handle audio independent @@ -63,7 +63,7 @@ remain correct over a larger area around the center of the speakers. In addition, Ambisonics can encode the near-field effect of sounds, effectively capturing the sound distance. The near-field effect is a subtle low-frequency boost as a result of wave-front curvature, and properly compensating for this -occuring with the output speakers (as well as emulating it with a synthesized +occurring with the output speakers (as well as emulating it with a synthesized soundfield) can create an improved sense of distance for sounds that move near or far. diff --git a/examples/alconvolve.c b/examples/alconvolve.c index 93fd2eb4..94b978b5 100644 --- a/examples/alconvolve.c +++ b/examples/alconvolve.c @@ -292,7 +292,7 @@ static ALuint CreateEffect(void) alGenEffects(1, &effect); alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_CONVOLUTION_REVERB_SOFT); - /* Check if an error occured, and clean up if so. */ + /* Check if an error occurred, and clean up if so. */ err = alGetError(); if(err != AL_NO_ERROR) { @@ -391,7 +391,7 @@ static ALuint LoadSound(const char *filename) free(membuf); sf_close(sndfile); - /* Check if an error occured, and clean up if so. */ + /* Check if an error occurred, and clean up if so. */ err = alGetError(); if(err != AL_NO_ERROR) { diff --git a/examples/alhrtf.c b/examples/alhrtf.c index d878870e..7ea1b99e 100644 --- a/examples/alhrtf.c +++ b/examples/alhrtf.c @@ -121,7 +121,7 @@ static ALuint LoadSound(const char *filename) free(membuf); sf_close(sndfile); - /* Check if an error occured, and clean up if so. */ + /* Check if an error occurred, and clean up if so. */ err = alGetError(); if(err != AL_NO_ERROR) { diff --git a/examples/allatency.c b/examples/allatency.c index ab4a4ebc..01f4eb69 100644 --- a/examples/allatency.c +++ b/examples/allatency.c @@ -124,7 +124,7 @@ static ALuint LoadSound(const char *filename) free(membuf); sf_close(sndfile); - /* Check if an error occured, and clean up if so. */ + /* Check if an error occurred, and clean up if so. */ err = alGetError(); if(err != AL_NO_ERROR) { diff --git a/examples/alloopback.c b/examples/alloopback.c index 56cd420f..964a0cdb 100644 --- a/examples/alloopback.c +++ b/examples/alloopback.c @@ -118,7 +118,7 @@ static ALuint CreateSineWave(void) alGenBuffers(1, &buffer); alBufferData(buffer, AL_FORMAT_MONO16, data, sizeof(data), 44100); - /* Check if an error occured, and clean up if so. */ + /* Check if an error occurred, and clean up if so. */ err = alGetError(); if(err != AL_NO_ERROR) { diff --git a/examples/almultireverb.c b/examples/almultireverb.c index a77cc59e..dcb76c87 100644 --- a/examples/almultireverb.c +++ b/examples/almultireverb.c @@ -137,7 +137,7 @@ static int LoadEffect(ALuint effect, const EFXEAXREVERBPROPERTIES *reverb) alEffectf(effect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, reverb->flRoomRolloffFactor); alEffecti(effect, AL_EAXREVERB_DECAY_HFLIMIT, reverb->iDecayHFLimit); - /* Check if an error occured, and return failure if so. */ + /* Check if an error occurred, and return failure if so. */ if((err=alGetError()) != AL_NO_ERROR) { fprintf(stderr, "Error setting up reverb: %s\n", alGetString(err)); @@ -210,7 +210,7 @@ static ALuint LoadSound(const char *filename) free(membuf); sf_close(sndfile); - /* Check if an error occured, and clean up if so. */ + /* Check if an error occurred, and clean up if so. */ err = alGetError(); if(err != AL_NO_ERROR) { @@ -493,7 +493,7 @@ int main(int argc, char **argv) } if(argc < 1) { - fprintf(stderr, "No filename spacified.\n"); + fprintf(stderr, "No filename specified.\n"); CloseAL(); return 1; } diff --git a/examples/alplay.c b/examples/alplay.c index 4291cb47..1eabcccd 100644 --- a/examples/alplay.c +++ b/examples/alplay.c @@ -266,7 +266,7 @@ static ALuint LoadSound(const char *filename) free(membuf); sf_close(sndfile); - /* Check if an error occured, and clean up if so. */ + /* Check if an error occurred, and clean up if so. */ err = alGetError(); if(err != AL_NO_ERROR) { diff --git a/examples/alreverb.c b/examples/alreverb.c index 11a3ac6b..ff49db25 100644 --- a/examples/alreverb.c +++ b/examples/alreverb.c @@ -132,7 +132,7 @@ static ALuint LoadEffect(const EFXEAXREVERBPROPERTIES *reverb) alEffecti(effect, AL_REVERB_DECAY_HFLIMIT, reverb->iDecayHFLimit); } - /* Check if an error occured, and clean up if so. */ + /* Check if an error occurred, and clean up if so. */ err = alGetError(); if(err != AL_NO_ERROR) { @@ -219,7 +219,7 @@ static ALuint LoadSound(const char *filename) free(membuf); sf_close(sndfile); - /* Check if an error occured, and clean up if so. */ + /* Check if an error occurred, and clean up if so. */ err = alGetError(); if(err != AL_NO_ERROR) { diff --git a/examples/altonegen.c b/examples/altonegen.c index 75db2d6b..a1daa66f 100644 --- a/examples/altonegen.c +++ b/examples/altonegen.c @@ -156,7 +156,7 @@ static ALuint CreateWave(enum WaveType type, ALuint freq, ALuint srate, ALfloat alBufferData(buffer, AL_FORMAT_MONO_FLOAT32, data, (ALsizei)data_size, (ALsizei)srate); free(data); - /* Check if an error occured, and clean up if so. */ + /* Check if an error occurred, and clean up if so. */ err = alGetError(); if(err != AL_NO_ERROR) { -- cgit v1.2.3 From 05f9ce8b978239cebecef1a60f0d451a118fa3df Mon Sep 17 00:00:00 2001 From: captainurist <73941350+captainurist@users.noreply.github.com> Date: Sat, 8 Jul 2023 01:29:45 +0800 Subject: Return noErr from DeviceListenerProc (#875) --- alc/backends/coreaudio.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'alc') diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index c2888e42..12c667ac 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -309,6 +309,7 @@ struct DeviceHelper { break; } } + return noErr; } }; -- cgit v1.2.3 From b48f47bf87b48d5a2e56a6f37abc300336b9da10 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 6 Jul 2023 11:35:27 -0700 Subject: Better order some functions in the export list --- alc/export_list.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'alc') diff --git a/alc/export_list.h b/alc/export_list.h index 8bedd850..ed1165d0 100644 --- a/alc/export_list.h +++ b/alc/export_list.h @@ -56,6 +56,9 @@ inline const FuncExport alcFunctions[]{ DECL(alcReopenDeviceSOFT), + DECL(alcEventControlSOFT), + DECL(alcEventCallbackSOFT), + DECL(alEnable), DECL(alDisable), DECL(alIsEnabled), @@ -365,9 +368,7 @@ inline const FuncExport alcFunctions[]{ DECL(alPopDebugGroupDirectEXT), DECL(alGetDebugMessageLogDirectEXT), - DECL(alcEventControlSOFT), - DECL(alcEventCallbackSOFT), - + /* Extra functions */ DECL(alsoft_set_log_callback), #ifdef ALSOFT_EAX }, eaxFunctions[]{ -- cgit v1.2.3 From ead05bc8de655911327d7356f55dab0f79371cfc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 10 Jul 2023 15:45:04 -0700 Subject: Use a type alias for ALC event bit masks --- alc/events.cpp | 2 +- alc/events.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'alc') diff --git a/alc/events.cpp b/alc/events.cpp index 6c91261c..a80faf8a 100644 --- a/alc/events.cpp +++ b/alc/events.cpp @@ -70,7 +70,7 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const AL return ALC_FALSE; } - std::bitset eventSet{0}; + alc::EventBitSet eventSet{0}; for(ALCenum type : al::span{events, static_cast(count)}) { auto etype = GetEventType(type); diff --git a/alc/events.h b/alc/events.h index ddb3808a..4acc505d 100644 --- a/alc/events.h +++ b/alc/events.h @@ -24,7 +24,8 @@ enum class DeviceType : ALCenum { Capture = ALC_CAPTURE_DEVICE_SOFT, }; -inline std::bitset EventsEnabled{0}; +using EventBitSet = std::bitset; +inline EventBitSet EventsEnabled{0}; inline std::mutex EventMutex; -- cgit v1.2.3 From e90ea548bfcf2fb0eeab484fabfbf508077d1217 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 20 Jul 2023 00:54:48 -0700 Subject: Make C callback functions noexcept --- alc/backends/pipewire.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'alc') diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index aac67ba2..fec2e800 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -1348,9 +1348,9 @@ spa_audio_info_raw make_spa_info(DeviceBase *device, bool is51rear, use_f32p_e u } class PipeWirePlayback final : public BackendBase { - void stateChangedCallback(pw_stream_state old, pw_stream_state state, const char *error); - void ioChangedCallback(uint32_t id, void *area, uint32_t size); - void outputCallback(); + void stateChangedCallback(pw_stream_state old, pw_stream_state state, const char *error) noexcept; + void ioChangedCallback(uint32_t id, void *area, uint32_t size) noexcept; + void outputCallback() noexcept; void open(const char *name) override; bool reset() override; @@ -1373,11 +1373,11 @@ class PipeWirePlayback final : public BackendBase { { pw_stream_events ret{}; ret.version = PW_VERSION_STREAM_EVENTS; - ret.state_changed = [](void *data, pw_stream_state old, pw_stream_state state, const char *error) + ret.state_changed = [](void *data, pw_stream_state old, pw_stream_state state, const char *error) noexcept { static_cast(data)->stateChangedCallback(old, state, error); }; - ret.io_changed = [](void *data, uint32_t id, void *area, uint32_t size) + ret.io_changed = [](void *data, uint32_t id, void *area, uint32_t size) noexcept { static_cast(data)->ioChangedCallback(id, area, size); }; - ret.process = [](void *data) + ret.process = [](void *data) noexcept { static_cast(data)->outputCallback(); }; return ret; } @@ -1394,10 +1394,10 @@ public: }; -void PipeWirePlayback::stateChangedCallback(pw_stream_state, pw_stream_state, const char*) +void PipeWirePlayback::stateChangedCallback(pw_stream_state, pw_stream_state, const char*) noexcept { mLoop.signal(false); } -void PipeWirePlayback::ioChangedCallback(uint32_t id, void *area, uint32_t size) +void PipeWirePlayback::ioChangedCallback(uint32_t id, void *area, uint32_t size) noexcept { switch(id) { @@ -1408,7 +1408,7 @@ void PipeWirePlayback::ioChangedCallback(uint32_t id, void *area, uint32_t size) } } -void PipeWirePlayback::outputCallback() +void PipeWirePlayback::outputCallback() noexcept { pw_buffer *pw_buf{pw_stream_dequeue_buffer(mStream.get())}; if(!pw_buf) UNLIKELY return; @@ -1847,8 +1847,8 @@ ClockLatency PipeWirePlayback::getClockLatency() class PipeWireCapture final : public BackendBase { - void stateChangedCallback(pw_stream_state old, pw_stream_state state, const char *error); - void inputCallback(); + void stateChangedCallback(pw_stream_state old, pw_stream_state state, const char *error) noexcept; + void inputCallback() noexcept; void open(const char *name) override; void start() override; @@ -1869,9 +1869,9 @@ class PipeWireCapture final : public BackendBase { { pw_stream_events ret{}; ret.version = PW_VERSION_STREAM_EVENTS; - ret.state_changed = [](void *data, pw_stream_state old, pw_stream_state state, const char *error) + ret.state_changed = [](void *data, pw_stream_state old, pw_stream_state state, const char *error) noexcept { static_cast(data)->stateChangedCallback(old, state, error); }; - ret.process = [](void *data) + ret.process = [](void *data) noexcept { static_cast(data)->inputCallback(); }; return ret; } @@ -1884,10 +1884,10 @@ public: }; -void PipeWireCapture::stateChangedCallback(pw_stream_state, pw_stream_state, const char*) +void PipeWireCapture::stateChangedCallback(pw_stream_state, pw_stream_state, const char*) noexcept { mLoop.signal(false); } -void PipeWireCapture::inputCallback() +void PipeWireCapture::inputCallback() noexcept { pw_buffer *pw_buf{pw_stream_dequeue_buffer(mStream.get())}; if(!pw_buf) UNLIKELY return; -- cgit v1.2.3 From b9de83c3e191858ac6b572d145bec5f9f2515543 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 20 Jul 2023 02:30:08 -0700 Subject: Use a lambda to forward a C callback --- alc/backends/opensl.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'alc') diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp index 58e78459..35c57d77 100644 --- a/alc/backends/opensl.cpp +++ b/alc/backends/opensl.cpp @@ -161,8 +161,6 @@ struct OpenSLPlayback final : public BackendBase { ~OpenSLPlayback() override; void process(SLAndroidSimpleBufferQueueItf bq) noexcept; - static void processC(SLAndroidSimpleBufferQueueItf bq, void *context) noexcept - { static_cast(context)->process(bq); } int mixerProc(); @@ -566,7 +564,9 @@ void OpenSLPlayback::start() PrintErr(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS == result) { - result = VCALL(bufferQueue,RegisterCallback)(&OpenSLPlayback::processC, this); + result = VCALL(bufferQueue,RegisterCallback)( + [](SLAndroidSimpleBufferQueueItf bq, void *context) noexcept + { static_cast(context)->process(bq); }, this); PrintErr(result, "bufferQueue->RegisterCallback"); } if(SL_RESULT_SUCCESS != result) @@ -644,8 +644,6 @@ struct OpenSLCapture final : public BackendBase { ~OpenSLCapture() override; void process(SLAndroidSimpleBufferQueueItf bq) noexcept; - static void processC(SLAndroidSimpleBufferQueueItf bq, void *context) noexcept - { static_cast(context)->process(bq); } void open(const char *name) override; void start() override; @@ -815,7 +813,9 @@ void OpenSLCapture::open(const char* name) } if(SL_RESULT_SUCCESS == result) { - result = VCALL(bufferQueue,RegisterCallback)(&OpenSLCapture::processC, this); + result = VCALL(bufferQueue,RegisterCallback)( + [](SLAndroidSimpleBufferQueueItf bq, void *context) noexcept + { static_cast(context)->process(bq); }, this); PrintErr(result, "bufferQueue->RegisterCallback"); } if(SL_RESULT_SUCCESS == result) -- cgit v1.2.3 From 8b3a9b527d87009f86ed0b4eb6c33a9e8dfc069b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 24 Jul 2023 12:46:34 -0700 Subject: Catch exceptions from constructing ALCcontexts --- alc/alc.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index d36f1891..82f3ec4b 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2660,7 +2660,21 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin } } - ContextRef context{new ALCcontext{dev, ctxflags}}; + ContextRef context{[](auto&& ...args) -> ContextRef + { + try { + return ContextRef{new ALCcontext{std::forward(args)...}}; + } + catch(std::exception& e) { + ERR("Failed to create ALCcontext: %s\n", e.what()); + return ContextRef{}; + } + }(dev, ctxflags)}; + if(!context) + { + alcSetError(dev.get(), ALC_OUT_OF_MEMORY); + return nullptr; + } context->init(); if(auto volopt = dev->configValue(nullptr, "volume-adjust")) -- cgit v1.2.3 From 34d07fde84ad64342ae6624334957143319615ab Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Wed, 26 Jul 2023 21:57:53 +0200 Subject: disable unavailable functionality on xbox (#887) * disable unavailable functionality on xbox * use not std version of getenv on xbox --- alc/alconfig.cpp | 2 ++ common/strutils.cpp | 4 ++++ core/helpers.cpp | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/alconfig.cpp b/alc/alconfig.cpp index 3c9a9777..03139abe 100644 --- a/alc/alconfig.cpp +++ b/alc/alconfig.cpp @@ -329,6 +329,7 @@ const char *GetConfigValue(const char *devName, const char *blockName, const cha #ifdef _WIN32 void ReadALConfig() { +#if !defined(_GAMING_XBOX) { #if !defined(ALSOFT_UWP) WCHAR buffer[MAX_PATH]; @@ -345,6 +346,7 @@ void ReadALConfig() if(f.is_open()) LoadConfigFromFile(f); } +#endif std::string ppath{GetProcBinary().path}; diff --git a/common/strutils.cpp b/common/strutils.cpp index b221b6ec..355cd030 100644 --- a/common/strutils.cpp +++ b/common/strutils.cpp @@ -45,7 +45,11 @@ namespace al { std::optional getenv(const char *envname) { +#ifdef _GAMING_XBOX + const char *str{::getenv(envname)}; +#else const char *str{std::getenv(envname)}; +#endif if(str && str[0] != '\0') return str; return std::nullopt; diff --git a/core/helpers.cpp b/core/helpers.cpp index 0d36048c..b353da2e 100644 --- a/core/helpers.cpp +++ b/core/helpers.cpp @@ -156,7 +156,7 @@ std::vector SearchDataFiles(const char *ext, const char *subdir) std::replace(path.begin(), path.end(), '/', '\\'); DirectorySearch(path.c_str(), ext, &results); -#if !defined(ALSOFT_UWP) +#if !defined(ALSOFT_UWP) && !defined(_GAMING_XBOX) /* Search the local and global data dirs. */ for(auto id : std::array{CSIDL_APPDATA, CSIDL_COMMON_APPDATA}) { -- cgit v1.2.3 From 7f2caf8609dff8332fefd2a73ac8dc93865198c4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 3 Aug 2023 21:24:09 -0700 Subject: Move some direct context function declarations to the extension --- alc/inprogext.h | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'alc') diff --git a/alc/inprogext.h b/alc/inprogext.h index 60c97536..7f5458e5 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -108,12 +108,6 @@ typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLEXT)(ALenum source, ALenum type typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPEXT)(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void) AL_API_NOEXCEPT17; typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKDIRECTEXT)(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPDIRECTEXT)(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPDIRECTEXT)(ALCcontext *context) AL_API_NOEXCEPT17; -typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGDIRECTEXT)(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; @@ -121,12 +115,6 @@ void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum sev void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; void AL_APIENTRY alPopDebugGroupEXT(void) AL_API_NOEXCEPT; ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; -void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; -void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; -void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; -void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; -void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) AL_API_NOEXCEPT; -ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; #endif #endif @@ -241,11 +229,18 @@ typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *contex typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; /* AL_EXT_BUFFER_DATA_STATIC */ typedef void (AL_APIENTRY *LPALBUFFERDATASTATICDIRECT)(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT17; -/* AL_SOFT_buffer_sub_data */ -typedef void (AL_APIENTRY *LPALBUFFERSUBDATADIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT17; +/* AL_EXT_debug */ +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKDIRECTEXT)(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPDIRECTEXT)(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPDIRECTEXT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGDIRECTEXT)(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; /* AL_EXT_FOLDBACK */ typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTARTDIRECT)(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTOPDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; +/* AL_SOFT_buffer_sub_data */ +typedef void (AL_APIENTRY *LPALBUFFERSUBDATADIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT17; /* AL_SOFT_source_latency */ typedef void (AL_APIENTRY *LPALSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY *LPALSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble,ALdouble,ALdouble) AL_API_NOEXCEPT17; @@ -400,11 +395,18 @@ void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint ef void AL_APIENTRY alBufferDataStaticDirect(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT; -void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) AL_API_NOEXCEPT; +ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; void AL_APIENTRY alRequestFoldbackStartDirect(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT; void AL_APIENTRY alRequestFoldbackStopDirect(ALCcontext *context) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT; + void AL_APIENTRY alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value) AL_API_NOEXCEPT; void AL_APIENTRY alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) AL_API_NOEXCEPT; void AL_APIENTRY alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALdouble *values) AL_API_NOEXCEPT; -- cgit v1.2.3 From 199a75f17ac564983a4bc8fb70715107b1f99126 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 4 Aug 2023 04:59:42 -0700 Subject: Don't use pipewire user data storage for native proxy objects --- alc/backends/pipewire.cpp | 193 ++++++++++++++++++++-------------------------- 1 file changed, 83 insertions(+), 110 deletions(-) (limited to 'alc') diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index fec2e800..902d6374 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -435,8 +435,75 @@ using MainloopLockGuard = std::lock_guard; * devices provided by the server. */ -struct NodeProxy; -struct MetadataProxy; +/* A generic PipeWire node proxy object used to track changes to sink and + * source nodes. + */ +struct NodeProxy { + static constexpr pw_node_events CreateNodeEvents() + { + pw_node_events ret{}; + ret.version = PW_VERSION_NODE_EVENTS; + ret.info = [](void *object, const pw_node_info *info) noexcept + { static_cast(object)->infoCallback(info); }; + ret.param = [](void *object, int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) noexcept + { static_cast(object)->paramCallback(seq, id, index, next, param); }; + return ret; + } + + uint32_t mId{}; + + PwNodePtr mNode{}; + spa_hook mListener{}; + + NodeProxy(uint32_t id, PwNodePtr node) + : mId{id}, mNode{std::move(node)} + { + static constexpr pw_node_events nodeEvents{CreateNodeEvents()}; + ppw_node_add_listener(mNode.get(), &mListener, &nodeEvents, this); + + /* Track changes to the enumerable formats (indicates the default + * format, which is what we're interested in). + */ + uint32_t fmtids[]{SPA_PARAM_EnumFormat}; + ppw_node_subscribe_params(mNode.get(), std::data(fmtids), std::size(fmtids)); + } + ~NodeProxy() + { spa_hook_remove(&mListener); } + + + void infoCallback(const pw_node_info *info) noexcept; + + void paramCallback(int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) noexcept; +}; + +/* A metadata proxy object used to query the default sink and source. */ +struct MetadataProxy { + static constexpr pw_metadata_events CreateMetadataEvents() + { + pw_metadata_events ret{}; + ret.version = PW_VERSION_METADATA_EVENTS; + ret.property = [](void *object, uint32_t id, const char *key, const char *type, const char *value) noexcept + { return static_cast(object)->propertyCallback(id, key, type, value); }; + return ret; + } + + uint32_t mId{}; + + PwMetadataPtr mMetadata{}; + spa_hook mListener{}; + + MetadataProxy(uint32_t id, PwMetadataPtr mdata) + : mId{id}, mMetadata{std::move(mdata)} + { + static constexpr pw_metadata_events metadataEvents{CreateMetadataEvents()}; + ppw_metadata_add_listener(mMetadata.get(), &mListener, &metadataEvents, this); + } + ~MetadataProxy() + { spa_hook_remove(&mListener); } + + int propertyCallback(uint32_t id, const char *key, const char *type, const char *value) noexcept; +}; + /* The global thread watching for global events. This particular class responds * to objects being added to or removed from the registry. @@ -452,8 +519,8 @@ struct EventManager { /* A list of proxy objects watching for events about changes to objects in * the registry. */ - std::vector mNodeList; - MetadataProxy *mDefaultMetadata{nullptr}; + std::vector> mNodeList; + std::optional mDefaultMetadata; /* Initialization handling. When init() is called, mInitSeq is set to a * SequenceID that marks the end of populating the registry. As objects of @@ -465,8 +532,9 @@ struct EventManager { std::atomic mHasAudio{false}; int mInitSeq{}; + ~EventManager() { if(mLoop) mLoop.stop(); } + bool init(); - ~EventManager(); void kill(); @@ -573,7 +641,7 @@ struct DeviceNode { static DeviceNode *Find(uint32_t id); static DeviceNode *FindByDevName(std::string_view devname); static void Remove(uint32_t id); - static std::vector &GetList() noexcept { return sList; } + static auto GetList() noexcept { return al::span{sList}; } void parseSampleRate(const spa_pod *value) noexcept; void parsePositions(const spa_pod *value) noexcept; @@ -613,8 +681,7 @@ DeviceNode &DeviceNode::Add(uint32_t id) auto match = std::find_if(sList.begin(), sList.end(), match_id); if(match != sList.end()) return *match; - sList.emplace_back(); - auto &n = sList.back(); + auto &n = sList.emplace_back(); n.mId = id; return n; } @@ -834,47 +901,6 @@ constexpr char AudioSourceVirtualClass[]{"Audio/Source/Virtual"}; constexpr char AudioDuplexClass[]{"Audio/Duplex"}; constexpr char StreamClass[]{"Stream/"}; -/* A generic PipeWire node proxy object used to track changes to sink and - * source nodes. - */ -struct NodeProxy { - static constexpr pw_node_events CreateNodeEvents() - { - pw_node_events ret{}; - ret.version = PW_VERSION_NODE_EVENTS; - ret.info = [](void *object, const pw_node_info *info) noexcept - { static_cast(object)->infoCallback(info); }; - ret.param = [](void *object, int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) noexcept - { static_cast(object)->paramCallback(seq, id, index, next, param); }; - return ret; - } - - uint32_t mId{}; - - PwNodePtr mNode{}; - spa_hook mListener{}; - - NodeProxy(uint32_t id, PwNodePtr node) - : mId{id}, mNode{std::move(node)} - { - static constexpr pw_node_events nodeEvents{CreateNodeEvents()}; - ppw_node_add_listener(mNode.get(), &mListener, &nodeEvents, this); - - /* Track changes to the enumerable formats (indicates the default - * format, which is what we're interested in). - */ - uint32_t fmtids[]{SPA_PARAM_EnumFormat}; - ppw_node_subscribe_params(mNode.get(), std::data(fmtids), std::size(fmtids)); - } - ~NodeProxy() - { spa_hook_remove(&mListener); } - - - void infoCallback(const pw_node_info *info) noexcept; - - void paramCallback(int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) noexcept; -}; - void NodeProxy::infoCallback(const pw_node_info *info) noexcept { /* We only care about property changes here (media class, name/desc). @@ -982,34 +1008,6 @@ void NodeProxy::paramCallback(int, uint32_t id, uint32_t, uint32_t, const spa_po } -/* A metadata proxy object used to query the default sink and source. */ -struct MetadataProxy { - static constexpr pw_metadata_events CreateMetadataEvents() - { - pw_metadata_events ret{}; - ret.version = PW_VERSION_METADATA_EVENTS; - ret.property = [](void *object, uint32_t id, const char *key, const char *type, const char *value) noexcept - { return static_cast(object)->propertyCallback(id, key, type, value); }; - return ret; - } - - uint32_t mId{}; - - PwMetadataPtr mMetadata{}; - spa_hook mListener{}; - - MetadataProxy(uint32_t id, PwMetadataPtr mdata) - : mId{id}, mMetadata{std::move(mdata)} - { - static constexpr pw_metadata_events metadataEvents{CreateMetadataEvents()}; - ppw_metadata_add_listener(mMetadata.get(), &mListener, &metadataEvents, this); - } - ~MetadataProxy() - { spa_hook_remove(&mListener); } - - int propertyCallback(uint32_t id, const char *key, const char *type, const char *value) noexcept; -}; - int MetadataProxy::propertyCallback(uint32_t id, const char *key, const char *type, const char *value) noexcept { @@ -1158,26 +1156,12 @@ bool EventManager::init() return true; } -EventManager::~EventManager() -{ - if(mLoop) mLoop.stop(); - - for(NodeProxy *node : mNodeList) - std::destroy_at(node); - if(mDefaultMetadata) - std::destroy_at(mDefaultMetadata); -} - void EventManager::kill() { if(mLoop) mLoop.stop(); - for(NodeProxy *node : mNodeList) - std::destroy_at(node); + mDefaultMetadata.reset(); mNodeList.clear(); - if(mDefaultMetadata) - std::destroy_at(mDefaultMetadata); - mDefaultMetadata = nullptr; mRegistry = nullptr; mCore = nullptr; @@ -1209,7 +1193,7 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t /* Create the proxy object. */ auto node = PwNodePtr{static_cast(pw_registry_bind(mRegistry.get(), id, type, - version, sizeof(NodeProxy)))}; + version, 0))}; if(!node) { ERR("Failed to create node proxy object (errno: %d)\n", errno); @@ -1219,8 +1203,7 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t /* Initialize the NodeProxy to hold the node object, add it to the * active node list, and update the sync point. */ - auto *proxy = static_cast(pw_proxy_get_user_data(as(node.get()))); - mNodeList.emplace_back(al::construct_at(proxy, id, std::move(node))); + mNodeList.emplace_back(std::make_unique(id, std::move(node))); syncInit(); /* Signal any waiters that we have found a source or sink for audio @@ -1247,16 +1230,14 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t } auto mdata = PwMetadataPtr{static_cast(pw_registry_bind(mRegistry.get(), id, - type, version, sizeof(MetadataProxy)))}; + type, version, 0))}; if(!mdata) { ERR("Failed to create metadata proxy object (errno: %d)\n", errno); return; } - auto *proxy = static_cast( - pw_proxy_get_user_data(as(mdata.get()))); - mDefaultMetadata = al::construct_at(proxy, id, std::move(mdata)); + mDefaultMetadata.emplace(id, std::move(mdata)); syncInit(); } } @@ -1265,21 +1246,13 @@ void EventManager::removeCallback(uint32_t id) noexcept { DeviceNode::Remove(id); - auto clear_node = [id](NodeProxy *node) noexcept - { - if(node->mId != id) - return false; - std::destroy_at(node); - return true; - }; + auto clear_node = [id](std::unique_ptr &node) noexcept + { return node->mId == id; }; auto node_end = std::remove_if(mNodeList.begin(), mNodeList.end(), clear_node); mNodeList.erase(node_end, mNodeList.end()); if(mDefaultMetadata && mDefaultMetadata->mId == id) - { - std::destroy_at(mDefaultMetadata); - mDefaultMetadata = nullptr; - } + mDefaultMetadata.reset(); } void EventManager::coreCallback(uint32_t id, int seq) noexcept -- cgit v1.2.3 From 9296af5566afea4ba4cb78b374ef3ee0bf9bc04b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 6 Aug 2023 18:49:42 -0700 Subject: Use a string_view for the backend open method --- alc/alc.cpp | 41 ++++++++++++++++++++++++++++++----- alc/backends/alsa.cpp | 16 +++++++------- alc/backends/base.h | 3 ++- alc/backends/coreaudio.cpp | 36 +++++++++++++++--------------- alc/backends/dsound.cpp | 22 ++++++++++--------- alc/backends/jack.cpp | 18 +++++++-------- alc/backends/loopback.cpp | 4 ++-- alc/backends/null.cpp | 12 +++++----- alc/backends/oboe.cpp | 24 ++++++++++---------- alc/backends/opensl.cpp | 24 ++++++++++---------- alc/backends/oss.cpp | 16 +++++++------- alc/backends/pipewire.cpp | 21 +++++++++--------- alc/backends/portaudio.cpp | 24 ++++++++++---------- alc/backends/pulseaudio.cpp | 16 +++++++------- alc/backends/sdl2.cpp | 27 +++++++++++++++++------ alc/backends/sndio.cpp | 24 ++++++++++---------- alc/backends/solaris.cpp | 12 +++++----- alc/backends/wasapi.cpp | 53 +++++++++++++++++++++++---------------------- alc/backends/wave.cpp | 14 ++++++------ alc/backends/winmm.cpp | 20 ++++++++--------- common/strutils.cpp | 17 ++++++++------- common/strutils.h | 5 +++-- 22 files changed, 249 insertions(+), 200 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index 82f3ec4b..45a55793 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2905,9 +2905,26 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) noexcep device->NumAuxSends = DefaultSends; try { + /* We need to ensure the device name isn't too long. The string_view is + * printed using the "%.*s" formatter, which uses an int for the + * precision/length. It wouldn't be a significant problem if larger + * values simply printed fewer characters due to truncation, but + * negative values are ignored, treating it like a normal null- + * terminated string, and string_views don't need to be null- + * terminated. + * + * Other than the annoyance of checking, this shouldn't be a problem. + * Two billion bytes is enough for a device name. + */ + const std::string_view devname{deviceName ? deviceName : ""}; + if(devname.length() >= std::numeric_limits::max()) + throw al::backend_exception{al::backend_error::NoDevice, + "Device name too long (%zu >= %d)", devname.length(), + std::numeric_limits::max()}; + auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback); std::lock_guard _{ListLock}; - backend->open(deviceName); + backend->open(devname); device->Backend = std::move(backend); } catch(al::backend_exception &e) { @@ -3024,14 +3041,20 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, device->UpdateSize = static_cast(samples); device->BufferSize = static_cast(samples); + TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n", DevFmtChannelsString(device->FmtChans), + DevFmtTypeString(device->FmtType), device->Frequency, device->UpdateSize, + device->BufferSize); + try { - TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n", - DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), - device->Frequency, device->UpdateSize, device->BufferSize); + const std::string_view devname{deviceName ? deviceName : ""}; + if(devname.length() >= std::numeric_limits::max()) + throw al::backend_exception{al::backend_error::NoDevice, + "Device name too long (%zu >= %d)", devname.length(), + std::numeric_limits::max()}; auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture); std::lock_guard _{ListLock}; - backend->open(deviceName); + backend->open(devname); device->Backend = std::move(backend); } catch(al::backend_exception &e) { @@ -3393,8 +3416,14 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, BackendPtr newbackend; try { + const std::string_view devname{deviceName ? deviceName : ""}; + if(devname.length() >= std::numeric_limits::max()) + throw al::backend_exception{al::backend_error::NoDevice, + "Device name too long (%zu >= %d)", devname.length(), + std::numeric_limits::max()}; + newbackend = PlaybackFactory->createBackend(dev.get(), BackendType::Playback); - newbackend->open(deviceName); + newbackend->open(devname); } catch(al::backend_exception &e) { listlock.unlock(); diff --git a/alc/backends/alsa.cpp b/alc/backends/alsa.cpp index 83eef183..0d9ff30d 100644 --- a/alc/backends/alsa.cpp +++ b/alc/backends/alsa.cpp @@ -427,7 +427,7 @@ struct AlsaPlayback final : public BackendBase { int mixerProc(); int mixerNoMMapProc(); - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -626,10 +626,10 @@ int AlsaPlayback::mixerNoMMapProc() } -void AlsaPlayback::open(const char *name) +void AlsaPlayback::open(std::string_view name) { std::string driver{"default"}; - if(name) + if(!name.empty()) { if(PlaybackDevices.empty()) PlaybackDevices = probe_devices(SND_PCM_STREAM_PLAYBACK); @@ -638,7 +638,7 @@ void AlsaPlayback::open(const char *name) [name](const DevMap &entry) -> bool { return entry.name == name; }); if(iter == PlaybackDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; driver = iter->device_name; } else @@ -871,7 +871,7 @@ struct AlsaCapture final : public BackendBase { AlsaCapture(DeviceBase *device) noexcept : BackendBase{device} { } ~AlsaCapture() override; - void open(const char *name) override; + void open(std::string_view name) override; void start() override; void stop() override; void captureSamples(std::byte *buffer, uint samples) override; @@ -898,10 +898,10 @@ AlsaCapture::~AlsaCapture() } -void AlsaCapture::open(const char *name) +void AlsaCapture::open(std::string_view name) { std::string driver{"default"}; - if(name) + if(!name.empty()) { if(CaptureDevices.empty()) CaptureDevices = probe_devices(SND_PCM_STREAM_CAPTURE); @@ -910,7 +910,7 @@ void AlsaCapture::open(const char *name) [name](const DevMap &entry) -> bool { return entry.name == name; }); if(iter == CaptureDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; driver = iter->device_name; } else diff --git a/alc/backends/base.h b/alc/backends/base.h index 07b430e0..a4079fe4 100644 --- a/alc/backends/base.h +++ b/alc/backends/base.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "core/device.h" #include "core/except.h" @@ -20,7 +21,7 @@ struct ClockLatency { }; struct BackendBase { - virtual void open(const char *name) = 0; + virtual void open(std::string_view name) = 0; virtual bool reset(); virtual void start() = 0; diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index 12c667ac..1684545b 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -329,7 +329,7 @@ struct CoreAudioPlayback final : public BackendBase { const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) noexcept; - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -362,11 +362,11 @@ OSStatus CoreAudioPlayback::MixerProc(AudioUnitRenderActionFlags*, const AudioTi } -void CoreAudioPlayback::open(const char *name) +void CoreAudioPlayback::open(std::string_view name) { #if CAN_ENUMERATE AudioDeviceID audioDevice{kAudioDeviceUnknown}; - if(!name) + if(name.empty()) GetHwProperty(kAudioHardwarePropertyDefaultOutputDevice, sizeof(audioDevice), &audioDevice); else @@ -379,16 +379,16 @@ void CoreAudioPlayback::open(const char *name) auto devmatch = std::find_if(PlaybackList.cbegin(), PlaybackList.cend(), find_name); if(devmatch == PlaybackList.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; audioDevice = devmatch->mId; } #else - if(!name) + if(name.empty()) name = ca_device; - else if(strcmp(name, ca_device) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != ca_device) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; #endif /* open the default output unit */ @@ -436,7 +436,7 @@ void CoreAudioPlayback::open(const char *name) mAudioUnit = audioUnit; #if CAN_ENUMERATE - if(name) + if(!name.empty()) mDevice->DeviceName = name; else { @@ -608,7 +608,7 @@ struct CoreAudioCapture final : public BackendBase { const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) noexcept; - void open(const char *name) override; + void open(std::string_view name) override; void start() override; void stop() override; void captureSamples(std::byte *buffer, uint samples) override; @@ -663,11 +663,11 @@ OSStatus CoreAudioCapture::RecordProc(AudioUnitRenderActionFlags *ioActionFlags, } -void CoreAudioCapture::open(const char *name) +void CoreAudioCapture::open(std::string_view name) { #if CAN_ENUMERATE AudioDeviceID audioDevice{kAudioDeviceUnknown}; - if(!name) + if(name.empty()) GetHwProperty(kAudioHardwarePropertyDefaultInputDevice, sizeof(audioDevice), &audioDevice); else @@ -680,16 +680,16 @@ void CoreAudioCapture::open(const char *name) auto devmatch = std::find_if(CaptureList.cbegin(), CaptureList.cend(), find_name); if(devmatch == CaptureList.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; audioDevice = devmatch->mId; } #else - if(!name) + if(name.empty()) name = ca_device; - else if(strcmp(name, ca_device) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != ca_device) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; #endif AudioComponentDescription desc{}; @@ -887,7 +887,7 @@ void CoreAudioCapture::open(const char *name) mDevice->Frequency, Resampler::FastBSinc24); #if CAN_ENUMERATE - if(name) + if(!name.empty()) mDevice->DeviceName = name; else { diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index 54fac898..b5596f1c 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -178,7 +178,7 @@ struct DSoundPlayback final : public BackendBase { int mixerProc(); - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -301,7 +301,7 @@ FORCE_ALIGN int DSoundPlayback::mixerProc() return 0; } -void DSoundPlayback::open(const char *name) +void DSoundPlayback::open(std::string_view name) { HRESULT hr; if(PlaybackDevices.empty()) @@ -316,9 +316,9 @@ void DSoundPlayback::open(const char *name) } const GUID *guid{nullptr}; - if(!name && !PlaybackDevices.empty()) + if(name.empty() && !PlaybackDevices.empty()) { - name = PlaybackDevices[0].name.c_str(); + name = PlaybackDevices[0].name; guid = &PlaybackDevices[0].guid; } else @@ -334,7 +334,8 @@ void DSoundPlayback::open(const char *name) [&id](const DevMap &entry) -> bool { return entry.guid == id; }); if(iter == PlaybackDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), + name.data()}; } guid = &iter->guid; } @@ -549,7 +550,7 @@ struct DSoundCapture final : public BackendBase { DSoundCapture(DeviceBase *device) noexcept : BackendBase{device} { } ~DSoundCapture() override; - void open(const char *name) override; + void open(std::string_view name) override; void start() override; void stop() override; void captureSamples(std::byte *buffer, uint samples) override; @@ -576,7 +577,7 @@ DSoundCapture::~DSoundCapture() } -void DSoundCapture::open(const char *name) +void DSoundCapture::open(std::string_view name) { HRESULT hr; if(CaptureDevices.empty()) @@ -591,9 +592,9 @@ void DSoundCapture::open(const char *name) } const GUID *guid{nullptr}; - if(!name && !CaptureDevices.empty()) + if(name.empty() && !CaptureDevices.empty()) { - name = CaptureDevices[0].name.c_str(); + name = CaptureDevices[0].name; guid = &CaptureDevices[0].guid; } else @@ -609,7 +610,8 @@ void DSoundCapture::open(const char *name) [&id](const DevMap &entry) -> bool { return entry.guid == id; }); if(iter == CaptureDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), + name.data()}; } guid = &iter->guid; } diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp index 66fc0877..a0a5c440 100644 --- a/alc/backends/jack.cpp +++ b/alc/backends/jack.cpp @@ -298,7 +298,7 @@ struct JackPlayback final : public BackendBase { int mixerProc(); - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -460,7 +460,7 @@ int JackPlayback::mixerProc() } -void JackPlayback::open(const char *name) +void JackPlayback::open(std::string_view name) { if(!mClient) { @@ -484,9 +484,9 @@ void JackPlayback::open(const char *name) if(PlaybackList.empty()) EnumerateDevices(mClient, PlaybackList); - if(!name && !PlaybackList.empty()) + if(name.empty() && !PlaybackList.empty()) { - name = PlaybackList[0].mName.c_str(); + name = PlaybackList[0].mName; mPortPattern = PlaybackList[0].mPattern; } else @@ -496,14 +496,10 @@ void JackPlayback::open(const char *name) auto iter = std::find_if(PlaybackList.cbegin(), PlaybackList.cend(), check_name); if(iter == PlaybackList.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name?name:""}; + "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; mPortPattern = iter->mPattern; } - mRTMixing = GetConfigValueBool(name, "jack", "rt-mix", true); - jack_set_process_callback(mClient, - mRTMixing ? &JackPlayback::processRtC : &JackPlayback::processC, this); - mDevice->DeviceName = name; } @@ -514,6 +510,10 @@ bool JackPlayback::reset() std::for_each(mPort.begin(), mPort.end(), unregister_port); mPort.fill(nullptr); + mRTMixing = GetConfigValueBool(mDevice->DeviceName.c_str(), "jack", "rt-mix", true); + jack_set_process_callback(mClient, + mRTMixing ? &JackPlayback::processRtC : &JackPlayback::processC, this); + /* Ignore the requested buffer metrics and just keep one JACK-sized buffer * ready for when requested. */ diff --git a/alc/backends/loopback.cpp b/alc/backends/loopback.cpp index bf4ab246..2972fc01 100644 --- a/alc/backends/loopback.cpp +++ b/alc/backends/loopback.cpp @@ -30,7 +30,7 @@ namespace { struct LoopbackBackend final : public BackendBase { LoopbackBackend(DeviceBase *device) noexcept : BackendBase{device} { } - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -39,7 +39,7 @@ struct LoopbackBackend final : public BackendBase { }; -void LoopbackBackend::open(const char *name) +void LoopbackBackend::open(std::string_view name) { mDevice->DeviceName = name; } diff --git a/alc/backends/null.cpp b/alc/backends/null.cpp index 73420ad3..3c68e4ce 100644 --- a/alc/backends/null.cpp +++ b/alc/backends/null.cpp @@ -50,7 +50,7 @@ struct NullBackend final : public BackendBase { int mixerProc(); - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -105,13 +105,13 @@ int NullBackend::mixerProc() } -void NullBackend::open(const char *name) +void NullBackend::open(std::string_view name) { - if(!name) + if(name.empty()) name = nullDevice; - else if(strcmp(name, nullDevice) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != nullDevice) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; mDevice->DeviceName = name; } diff --git a/alc/backends/oboe.cpp b/alc/backends/oboe.cpp index cc44b867..b7bab19a 100644 --- a/alc/backends/oboe.cpp +++ b/alc/backends/oboe.cpp @@ -30,7 +30,7 @@ struct OboePlayback final : public BackendBase, public oboe::AudioStreamCallback void onErrorAfterClose(oboe::AudioStream* /* audioStream */, oboe::Result /* error */) override; - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -56,13 +56,13 @@ void OboePlayback::onErrorAfterClose(oboe::AudioStream* audioStream, oboe::Resul TRACE("Error was %s", oboe::convertToText(error)); } -void OboePlayback::open(const char *name) +void OboePlayback::open(std::string_view name) { - if(!name) + if(name.empty()) name = device_name; - else if(std::strcmp(name, device_name) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != device_name) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; /* Open a basic output stream, just to ensure it can work. */ oboe::ManagedStream stream; @@ -220,7 +220,7 @@ struct OboeCapture final : public BackendBase, public oboe::AudioStreamCallback oboe::DataCallbackResult onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) override; - void open(const char *name) override; + void open(std::string_view name) override; void start() override; void stop() override; void captureSamples(std::byte *buffer, uint samples) override; @@ -235,13 +235,13 @@ oboe::DataCallbackResult OboeCapture::onAudioReady(oboe::AudioStream*, void *aud } -void OboeCapture::open(const char *name) +void OboeCapture::open(std::string_view name) { - if(!name) + if(name.empty()) name = device_name; - else if(std::strcmp(name, device_name) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != device_name) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; oboe::AudioStreamBuilder builder; builder.setDirection(oboe::Direction::Input) diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp index 35c57d77..61e3c9a7 100644 --- a/alc/backends/opensl.cpp +++ b/alc/backends/opensl.cpp @@ -164,7 +164,7 @@ struct OpenSLPlayback final : public BackendBase { int mixerProc(); - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -312,13 +312,13 @@ int OpenSLPlayback::mixerProc() } -void OpenSLPlayback::open(const char *name) +void OpenSLPlayback::open(std::string_view name) { - if(!name) + if(name.empty()) name = opensl_device; - else if(strcmp(name, opensl_device) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != opensl_device) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; /* There's only one device, so if it's already open, there's nothing to do. */ if(mEngineObj) return; @@ -645,7 +645,7 @@ struct OpenSLCapture final : public BackendBase { void process(SLAndroidSimpleBufferQueueItf bq) noexcept; - void open(const char *name) override; + void open(std::string_view name) override; void start() override; void stop() override; void captureSamples(std::byte *buffer, uint samples) override; @@ -686,13 +686,13 @@ void OpenSLCapture::process(SLAndroidSimpleBufferQueueItf) noexcept } -void OpenSLCapture::open(const char* name) +void OpenSLCapture::open(std::string_view name) { - if(!name) + if(name.empty()) name = opensl_device; - else if(strcmp(name, opensl_device) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != opensl_device) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)}; PrintErr(result, "slCreateEngine"); diff --git a/alc/backends/oss.cpp b/alc/backends/oss.cpp index 554ccc24..87d3ba35 100644 --- a/alc/backends/oss.cpp +++ b/alc/backends/oss.cpp @@ -227,7 +227,7 @@ struct OSSPlayback final : public BackendBase { int mixerProc(); - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -304,10 +304,10 @@ int OSSPlayback::mixerProc() } -void OSSPlayback::open(const char *name) +void OSSPlayback::open(std::string_view name) { const char *devname{DefaultPlayback.c_str()}; - if(!name) + if(name.empty()) name = DefaultName; else { @@ -320,7 +320,7 @@ void OSSPlayback::open(const char *name) ); if(iter == PlaybackDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; devname = iter->device_name.c_str(); } @@ -443,7 +443,7 @@ struct OSScapture final : public BackendBase { int recordProc(); - void open(const char *name) override; + void open(std::string_view name) override; void start() override; void stop() override; void captureSamples(std::byte *buffer, uint samples) override; @@ -512,10 +512,10 @@ int OSScapture::recordProc() } -void OSScapture::open(const char *name) +void OSScapture::open(std::string_view name) { const char *devname{DefaultCapture.c_str()}; - if(!name) + if(name.empty()) name = DefaultName; else { @@ -528,7 +528,7 @@ void OSScapture::open(const char *name) ); if(iter == CaptureDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; devname = iter->device_name.c_str(); } diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 902d6374..9a63d2f4 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -1325,7 +1325,7 @@ class PipeWirePlayback final : public BackendBase { void ioChangedCallback(uint32_t id, void *area, uint32_t size) noexcept; void outputCallback() noexcept; - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -1428,14 +1428,14 @@ void PipeWirePlayback::outputCallback() noexcept } -void PipeWirePlayback::open(const char *name) +void PipeWirePlayback::open(std::string_view name) { static std::atomic OpenCount{0}; uint64_t targetid{PwIdAny}; std::string devname{}; gEventHandler.waitForInit(); - if(!name) + if(name.empty()) { EventWatcherLockGuard _{gEventHandler}; auto&& devlist = DeviceNode::GetList(); @@ -1470,7 +1470,7 @@ void PipeWirePlayback::open(const char *name) auto match = std::find_if(devlist.cbegin(), devlist.cend(), match_name); if(match == devlist.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; targetid = match->mSerial; devname = match->mName; @@ -1823,7 +1823,7 @@ class PipeWireCapture final : public BackendBase { void stateChangedCallback(pw_stream_state old, pw_stream_state state, const char *error) noexcept; void inputCallback() noexcept; - void open(const char *name) override; + void open(std::string_view name) override; void start() override; void stop() override; void captureSamples(std::byte *buffer, uint samples) override; @@ -1875,14 +1875,14 @@ void PipeWireCapture::inputCallback() noexcept } -void PipeWireCapture::open(const char *name) +void PipeWireCapture::open(std::string_view name) { static std::atomic OpenCount{0}; uint64_t targetid{PwIdAny}; std::string devname{}; gEventHandler.waitForInit(); - if(!name) + if(name.empty()) { EventWatcherLockGuard _{gEventHandler}; auto&& devlist = DeviceNode::GetList(); @@ -1920,16 +1920,17 @@ void PipeWireCapture::open(const char *name) auto match_name = [name](const DeviceNode &n) -> bool { return n.mType != NodeType::Sink && n.mName == name; }; auto match = std::find_if(devlist.cbegin(), devlist.cend(), match_name); - if(match == devlist.cend() && std::strncmp(name, MonitorPrefix, MonitorPrefixLen) == 0) + if(match == devlist.cend() && name.length() >= MonitorPrefixLen + && std::strncmp(name.data(), MonitorPrefix, MonitorPrefixLen) == 0) { - const char *sinkname{name + MonitorPrefixLen}; + const std::string_view sinkname{name.substr(MonitorPrefixLen)}; auto match_sinkname = [sinkname](const DeviceNode &n) -> bool { return n.mType == NodeType::Sink && n.mName == sinkname; }; match = std::find_if(devlist.cbegin(), devlist.cend(), match_sinkname); } if(match == devlist.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; targetid = match->mSerial; devname = name; diff --git a/alc/backends/portaudio.cpp b/alc/backends/portaudio.cpp index 2551f448..979a54d6 100644 --- a/alc/backends/portaudio.cpp +++ b/alc/backends/portaudio.cpp @@ -86,7 +86,7 @@ struct PortPlayback final : public BackendBase { framesPerBuffer, timeInfo, statusFlags); } - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -116,13 +116,13 @@ int PortPlayback::writeCallback(const void*, void *outputBuffer, unsigned long f } -void PortPlayback::open(const char *name) +void PortPlayback::open(std::string_view name) { - if(!name) + if(name.empty()) name = pa_device; - else if(strcmp(name, pa_device) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != pa_device) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; PaStreamParameters params{}; auto devidopt = ConfigValueInt(nullptr, "port", "device"); @@ -245,7 +245,7 @@ struct PortCapture final : public BackendBase { framesPerBuffer, timeInfo, statusFlags); } - void open(const char *name) override; + void open(std::string_view name) override; void start() override; void stop() override; void captureSamples(std::byte *buffer, uint samples) override; @@ -276,13 +276,13 @@ int PortCapture::readCallback(const void *inputBuffer, void*, unsigned long fram } -void PortCapture::open(const char *name) +void PortCapture::open(std::string_view name) { - if(!name) + if(name.empty()) name = pa_device; - else if(strcmp(name, pa_device) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != pa_device) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; uint samples{mDevice->BufferSize}; samples = maxu(samples, 100 * mDevice->Frequency / 1000); diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index 8c6cc4d3..e2cea8a8 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -647,7 +647,7 @@ struct PulsePlayback final : public BackendBase { void sinkNameCallback(pa_context *context, const pa_sink_info *info, int eol) noexcept; void streamMovedCallback(pa_stream *stream) noexcept; - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -782,14 +782,14 @@ void PulsePlayback::streamMovedCallback(pa_stream *stream) noexcept } -void PulsePlayback::open(const char *name) +void PulsePlayback::open(std::string_view name) { mMainloop = PulseMainloop::Create(); mMainloop.start(); const char *pulse_name{nullptr}; const char *dev_name{nullptr}; - if(name) + if(!name.empty()) { if(PlaybackDevices.empty()) mMainloop.probePlaybackDevices(); @@ -798,7 +798,7 @@ void PulsePlayback::open(const char *name) [name](const DevMap &entry) -> bool { return entry.name == name; }); if(iter == PlaybackDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; pulse_name = iter->device_name.c_str(); dev_name = iter->name.c_str(); } @@ -1066,7 +1066,7 @@ struct PulseCapture final : public BackendBase { void sourceNameCallback(pa_context *context, const pa_source_info *info, int eol) noexcept; void streamMovedCallback(pa_stream *stream) noexcept; - void open(const char *name) override; + void open(std::string_view name) override; void start() override; void stop() override; void captureSamples(std::byte *buffer, uint samples) override; @@ -1123,7 +1123,7 @@ void PulseCapture::streamMovedCallback(pa_stream *stream) noexcept } -void PulseCapture::open(const char *name) +void PulseCapture::open(std::string_view name) { if(!mMainloop) { @@ -1132,7 +1132,7 @@ void PulseCapture::open(const char *name) } const char *pulse_name{nullptr}; - if(name) + if(!name.empty()) { if(CaptureDevices.empty()) mMainloop.probeCaptureDevices(); @@ -1141,7 +1141,7 @@ void PulseCapture::open(const char *name) [name](const DevMap &entry) -> bool { return entry.name == name; }); if(iter == CaptureDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%s\" not found", name}; + "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; pulse_name = iter->device_name.c_str(); mDevice->DeviceName = iter->name; } diff --git a/alc/backends/sdl2.cpp b/alc/backends/sdl2.cpp index e1e40e27..f5ed4316 100644 --- a/alc/backends/sdl2.cpp +++ b/alc/backends/sdl2.cpp @@ -54,7 +54,7 @@ struct Sdl2Backend final : public BackendBase { void audioCallback(Uint8 *stream, int len) noexcept; - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -84,7 +84,7 @@ void Sdl2Backend::audioCallback(Uint8 *stream, int len) noexcept mDevice->renderSamples(stream, ulen / mFrameSize, mDevice->channelsFromFmt()); } -void Sdl2Backend::open(const char *name) +void Sdl2Backend::open(std::string_view name) { SDL_AudioSpec want{}, have{}; @@ -109,16 +109,29 @@ void Sdl2Backend::open(const char *name) * necessarily the first in the list. */ SDL_AudioDeviceID devid; - if(!name || strcmp(name, defaultDeviceName) == 0) + if(name.empty() || name == defaultDeviceName) + { + name = defaultDeviceName; devid = SDL_OpenAudioDevice(nullptr, SDL_FALSE, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); + } else { const size_t prefix_len = strlen(DEVNAME_PREFIX); - if(strncmp(name, DEVNAME_PREFIX, prefix_len) == 0) - devid = SDL_OpenAudioDevice(name+prefix_len, SDL_FALSE, &want, &have, + if(name.length() >= prefix_len && strncmp(name.data(), DEVNAME_PREFIX, prefix_len) == 0) + { + /* Copy the string_view to a string to ensure it's null terminated + * for this call. + */ + const std::string devname{name.substr(prefix_len)}; + devid = SDL_OpenAudioDevice(devname.c_str(), SDL_FALSE, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); + } else - devid = SDL_OpenAudioDevice(name, SDL_FALSE, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); + { + const std::string devname{name}; + devid = SDL_OpenAudioDevice(devname.c_str(), SDL_FALSE, &want, &have, + SDL_AUDIO_ALLOW_ANY_CHANGE); + } } if(!devid) throw al::backend_exception{al::backend_error::NoDevice, "%s", SDL_GetError()}; @@ -160,7 +173,7 @@ void Sdl2Backend::open(const char *name) mFmtType = devtype; mUpdateSize = have.samples; - mDevice->DeviceName = name ? name : defaultDeviceName; + mDevice->DeviceName = name; } bool Sdl2Backend::reset() diff --git a/alc/backends/sndio.cpp b/alc/backends/sndio.cpp index 8daa928c..d54c337b 100644 --- a/alc/backends/sndio.cpp +++ b/alc/backends/sndio.cpp @@ -57,7 +57,7 @@ struct SndioPlayback final : public BackendBase { int mixerProc(); - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -112,13 +112,13 @@ int SndioPlayback::mixerProc() } -void SndioPlayback::open(const char *name) +void SndioPlayback::open(std::string_view name) { - if(!name) + if(name.empty()) name = sndio_device; - else if(strcmp(name, sndio_device) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != sndio_device) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; sio_hdl *sndHandle{sio_open(nullptr, SIO_PLAY, 0)}; if(!sndHandle) @@ -280,7 +280,7 @@ struct SndioCapture final : public BackendBase { int recordProc(); - void open(const char *name) override; + void open(std::string_view name) override; void start() override; void stop() override; void captureSamples(std::byte *buffer, uint samples) override; @@ -382,13 +382,13 @@ int SndioCapture::recordProc() } -void SndioCapture::open(const char *name) +void SndioCapture::open(std::string_view name) { - if(!name) + if(name.empty()) name = sndio_device; - else if(strcmp(name, sndio_device) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != sndio_device) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; mSndHandle = sio_open(nullptr, SIO_REC, true); if(mSndHandle == nullptr) diff --git a/alc/backends/solaris.cpp b/alc/backends/solaris.cpp index 15dcc98f..38f9db19 100644 --- a/alc/backends/solaris.cpp +++ b/alc/backends/solaris.cpp @@ -62,7 +62,7 @@ struct SolarisBackend final : public BackendBase { int mixerProc(); - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -139,13 +139,13 @@ int SolarisBackend::mixerProc() } -void SolarisBackend::open(const char *name) +void SolarisBackend::open(std::string_view name) { - if(!name) + if(name.empty()) name = solaris_device; - else if(strcmp(name, solaris_device) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != solaris_device) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; int fd{::open(solaris_driver.c_str(), O_WRONLY)}; if(fd == -1) diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index dccbeba2..96c56fa8 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -868,7 +868,7 @@ constexpr char MessageStr[static_cast(MsgType::Count)][16]{ struct WasapiProxy { virtual ~WasapiProxy() = default; - virtual HRESULT openProxy(const char *name) = 0; + virtual HRESULT openProxy(std::string_view name) = 0; virtual void closeProxy() = 0; virtual HRESULT resetProxy() = 0; @@ -878,7 +878,7 @@ struct WasapiProxy { struct Msg { MsgType mType; WasapiProxy *mProxy; - const char *mParam; + std::string_view mParam; std::promise mPromise; explicit operator bool() const noexcept { return mType != MsgType::QuitThread; } @@ -889,7 +889,7 @@ struct WasapiProxy { static std::optional sDeviceHelper; - std::future pushMessage(MsgType type, const char *param=nullptr) + std::future pushMessage(MsgType type, std::string_view param={}) { std::promise promise; std::future future{promise.get_future()}; @@ -907,7 +907,7 @@ struct WasapiProxy { std::future future{promise.get_future()}; { std::lock_guard _{mMsgQueueLock}; - mMsgQueue.emplace_back(Msg{type, nullptr, nullptr, std::move(promise)}); + mMsgQueue.emplace_back(Msg{type, nullptr, {}, std::move(promise)}); } mMsgQueueCond.notify_one(); return future; @@ -958,9 +958,10 @@ int WasapiProxy::messageHandler(std::promise *promise) TRACE("Starting message loop\n"); while(Msg msg{popMessage()}) { - TRACE("Got message \"%s\" (0x%04x, this=%p, param=%p)\n", + TRACE("Got message \"%s\" (0x%04x, this=%p, param={%p,%zu})\n", MessageStr[static_cast(msg.mType)], static_cast(msg.mType), - static_cast(msg.mProxy), static_cast(msg.mParam)); + static_cast(msg.mProxy), static_cast(msg.mParam.data()), + msg.mParam.length()); switch(msg.mType) { @@ -1010,8 +1011,8 @@ struct WasapiPlayback final : public BackendBase, WasapiProxy { int mixerProc(); - void open(const char *name) override; - HRESULT openProxy(const char *name) override; + void open(std::string_view name) override; + HRESULT openProxy(std::string_view name) override; void closeProxy() override; bool reset() override; @@ -1147,7 +1148,7 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() } -void WasapiPlayback::open(const char *name) +void WasapiPlayback::open(std::string_view name) { if(SUCCEEDED(mOpenStatus)) throw al::backend_exception{al::backend_error::DeviceError, @@ -1161,11 +1162,10 @@ void WasapiPlayback::open(const char *name) "Failed to create notify events"}; } - if(name && std::strncmp(name, DevNameHead, DevNameHeadLen) == 0) + if(name.length() >= DevNameHeadLen + && std::strncmp(name.data(), DevNameHead, DevNameHeadLen) == 0) { - name += DevNameHeadLen; - if(*name == '\0') - name = nullptr; + name = name.substr(DevNameHeadLen); } mOpenStatus = pushMessage(MsgType::OpenDevice, name).get(); @@ -1174,11 +1174,11 @@ void WasapiPlayback::open(const char *name) mOpenStatus}; } -HRESULT WasapiPlayback::openProxy(const char *name) +HRESULT WasapiPlayback::openProxy(std::string_view name) { std::string devname; std::wstring devid; - if(name) + if(!name.empty()) { auto devlock = DeviceListLock{gDeviceList}; auto list = al::span{devlock.getPlaybackList()}; @@ -1194,7 +1194,8 @@ HRESULT WasapiPlayback::openProxy(const char *name) } if(iter == list.cend()) { - WARN("Failed to find device name matching \"%s\"\n", name); + WARN("Failed to find device name matching \"%.*s\"\n", static_cast(name.length()), + name.data()); return E_FAIL; } devname = iter->name; @@ -1654,8 +1655,8 @@ struct WasapiCapture final : public BackendBase, WasapiProxy { int recordProc(); - void open(const char *name) override; - HRESULT openProxy(const char *name) override; + void open(std::string_view name) override; + HRESULT openProxy(std::string_view name) override; void closeProxy() override; HRESULT resetProxy() override; @@ -1787,7 +1788,7 @@ FORCE_ALIGN int WasapiCapture::recordProc() } -void WasapiCapture::open(const char *name) +void WasapiCapture::open(std::string_view name) { if(SUCCEEDED(mOpenStatus)) throw al::backend_exception{al::backend_error::DeviceError, @@ -1801,11 +1802,10 @@ void WasapiCapture::open(const char *name) "Failed to create notify events"}; } - if(name && std::strncmp(name, DevNameHead, DevNameHeadLen) == 0) + if(name.length() >= DevNameHeadLen + && std::strncmp(name.data(), DevNameHead, DevNameHeadLen) == 0) { - name += DevNameHeadLen; - if(*name == '\0') - name = nullptr; + name = name.substr(DevNameHeadLen); } mOpenStatus = pushMessage(MsgType::OpenDevice, name).get(); @@ -1822,11 +1822,11 @@ void WasapiCapture::open(const char *name) } } -HRESULT WasapiCapture::openProxy(const char *name) +HRESULT WasapiCapture::openProxy(std::string_view name) { std::string devname; std::wstring devid; - if(name) + if(!name.empty()) { auto devlock = DeviceListLock{gDeviceList}; auto devlist = al::span{devlock.getCaptureList()}; @@ -1842,7 +1842,8 @@ HRESULT WasapiCapture::openProxy(const char *name) } if(iter == devlist.cend()) { - WARN("Failed to find device name matching \"%s\"\n", name); + WARN("Failed to find device name matching \"%.*s\"\n", static_cast(name.length()), + name.data()); return E_FAIL; } devname = iter->name; diff --git a/alc/backends/wave.cpp b/alc/backends/wave.cpp index 40592ee7..1078c654 100644 --- a/alc/backends/wave.cpp +++ b/alc/backends/wave.cpp @@ -96,7 +96,7 @@ struct WaveBackend final : public BackendBase { int mixerProc(); - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -194,24 +194,24 @@ int WaveBackend::mixerProc() return 0; } -void WaveBackend::open(const char *name) +void WaveBackend::open(std::string_view name) { auto fname = ConfigValueStr(nullptr, "wave", "file"); if(!fname) throw al::backend_exception{al::backend_error::NoDevice, "No wave output filename"}; - if(!name) + if(name.empty()) name = waveDevice; - else if(strcmp(name, waveDevice) != 0) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + else if(name != waveDevice) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; /* There's only one "device", so if it's already open, we're done. */ if(mFile) return; #ifdef _WIN32 { - std::wstring wname{utf8_to_wstr(fname->c_str())}; + std::wstring wname{utf8_to_wstr(fname.value())}; mFile = _wfopen(wname.c_str(), L"wb"); } #else diff --git a/alc/backends/winmm.cpp b/alc/backends/winmm.cpp index c22f1c4d..f0fb0a1c 100644 --- a/alc/backends/winmm.cpp +++ b/alc/backends/winmm.cpp @@ -135,7 +135,7 @@ struct WinMMPlayback final : public BackendBase { int mixerProc(); - void open(const char *name) override; + void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; @@ -208,18 +208,18 @@ FORCE_ALIGN int WinMMPlayback::mixerProc() } -void WinMMPlayback::open(const char *name) +void WinMMPlayback::open(std::string_view name) { if(PlaybackDevices.empty()) ProbePlaybackDevices(); // Find the Device ID matching the deviceName if valid - auto iter = name ? + auto iter = !name.empty() ? std::find(PlaybackDevices.cbegin(), PlaybackDevices.cend(), name) : PlaybackDevices.cbegin(); if(iter == PlaybackDevices.cend()) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; auto DeviceID = static_cast(std::distance(PlaybackDevices.cbegin(), iter)); DevFmtType fmttype{mDevice->FmtType}; @@ -370,7 +370,7 @@ struct WinMMCapture final : public BackendBase { int captureProc(); - void open(const char *name) override; + void open(std::string_view name) override; void start() override; void stop() override; void captureSamples(std::byte *buffer, uint samples) override; @@ -446,18 +446,18 @@ int WinMMCapture::captureProc() } -void WinMMCapture::open(const char *name) +void WinMMCapture::open(std::string_view name) { if(CaptureDevices.empty()) ProbeCaptureDevices(); // Find the Device ID matching the deviceName if valid - auto iter = name ? + auto iter = !name.empty() ? std::find(CaptureDevices.cbegin(), CaptureDevices.cend(), name) : CaptureDevices.cbegin(); if(iter == CaptureDevices.cend()) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%s\" not found", - name}; + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", + static_cast(name.length()), name.data()}; auto DeviceID = static_cast(std::distance(CaptureDevices.cbegin(), iter)); switch(mDevice->FmtChans) diff --git a/common/strutils.cpp b/common/strutils.cpp index 355cd030..f7868e2e 100644 --- a/common/strutils.cpp +++ b/common/strutils.cpp @@ -10,31 +10,32 @@ #define WIN32_LEAN_AND_MEAN #include -std::string wstr_to_utf8(const WCHAR *wstr) +std::string wstr_to_utf8(std::wstring_view wstr) { std::string ret; - int len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr); + int len{WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast(wstr.length()), nullptr, + 0, nullptr, nullptr)}; if(len > 0) { ret.resize(len); - WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &ret[0], len, nullptr, nullptr); - ret.pop_back(); + WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast(wstr.length()), &ret[0], len, + nullptr, nullptr); } return ret; } -std::wstring utf8_to_wstr(const char *str) +std::wstring utf8_to_wstr(std::string_view str) { std::wstring ret; - int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, nullptr, 0); + int len{MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.length()), nullptr, + 0)}; if(len > 0) { ret.resize(len); - MultiByteToWideChar(CP_UTF8, 0, str, -1, &ret[0], len); - ret.pop_back(); + MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.length()), &ret[0], len); } return ret; diff --git a/common/strutils.h b/common/strutils.h index 67f057a7..7eee0c1d 100644 --- a/common/strutils.h +++ b/common/strutils.h @@ -5,10 +5,11 @@ #include #ifdef _WIN32 +#include #include -std::string wstr_to_utf8(const wchar_t *wstr); -std::wstring utf8_to_wstr(const char *str); +std::string wstr_to_utf8(std::wstring_view wstr); +std::wstring utf8_to_wstr(std::string_view str); #endif namespace al { -- cgit v1.2.3 From 09eff761b8c8a2da79b0083c86a304eb3643b396 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 11 Aug 2023 02:10:26 -0700 Subject: Add AL_EXT_debug functions to set/get object names --- al/auxeffectslot.cpp | 13 +++++++ al/auxeffectslot.h | 3 ++ al/buffer.cpp | 15 ++++++++ al/buffer.h | 3 ++ al/debug.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++++++++--- al/debug.h | 1 + al/effect.cpp | 15 ++++++++ al/effect.h | 2 + al/filter.cpp | 15 ++++++++ al/filter.h | 2 + al/source.cpp | 14 +++++++ al/source.h | 5 ++- al/state.cpp | 5 +++ alc/context.h | 3 ++ alc/device.h | 5 +++ alc/export_list.h | 10 +++++ alc/inprogext.h | 30 +++++++++++---- 17 files changed, 228 insertions(+), 14 deletions(-) (limited to 'alc') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 6f82db71..09db0736 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -286,6 +286,8 @@ ALeffectslot *AllocEffectSlot(ALCcontext *context) void FreeEffectSlot(ALCcontext *context, ALeffectslot *slot) { + context->mEffectSlotNames.erase(slot->id); + const ALuint id{slot->id - 1}; const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; @@ -962,6 +964,17 @@ void ALeffectslot::updateProps(ALCcontext *context) } } +void ALeffectslot::SetName(ALCcontext* context, ALuint id, std::string_view name) +{ + std::lock_guard _{context->mEffectSlotLock}; + + auto slot = LookupEffectSlot(context, id); + if(!slot) UNLIKELY + return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", id); + + context->mEffectSlotNames.insert_or_assign(id, name); +} + void UpdateAllEffectSlotProps(ALCcontext *context) { std::lock_guard _{context->mEffectSlotLock}; diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 3e9a2a4e..9038647c 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -3,6 +3,7 @@ #include #include +#include #include "AL/al.h" #include "AL/alc.h" @@ -76,6 +77,8 @@ struct ALeffectslot { ALenum initEffect(ALenum effectType, const EffectProps &effectProps, ALCcontext *context); void updateProps(ALCcontext *context); + static void SetName(ALCcontext *context, ALuint id, std::string_view name); + /* This can be new'd for the context's default effect slot. */ DEF_NEWDEL(ALeffectslot) diff --git a/al/buffer.cpp b/al/buffer.cpp index 58e8f375..e56aa13e 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -222,6 +222,8 @@ void FreeBuffer(ALCdevice *device, ALbuffer *buffer) eax_x_ram_clear(*device, *buffer); #endif // ALSOFT_EAX + device->mBufferNames.erase(buffer->id); + const ALuint id{buffer->id - 1}; const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; @@ -1440,6 +1442,19 @@ AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum /*format*/) no } +void ALbuffer::SetName(ALCcontext *context, ALuint id, std::string_view name) +{ + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->BufferLock}; + + auto buffer = LookupBuffer(device, id); + if(!buffer) UNLIKELY + return context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", id); + + device->mBufferNames.insert_or_assign(id, name); +} + + BufferSubList::~BufferSubList() { if(!Buffers) diff --git a/al/buffer.h b/al/buffer.h index 3df1fa4c..f936cf98 100644 --- a/al/buffer.h +++ b/al/buffer.h @@ -3,6 +3,7 @@ #include #include +#include #include "AL/al.h" @@ -47,6 +48,8 @@ struct ALbuffer : public BufferStorage { /* Self ID */ ALuint id{0}; + static void SetName(ALCcontext *context, ALuint id, std::string_view name); + DISABLE_ALLOC() #ifdef ALSOFT_EAX diff --git a/al/debug.cpp b/al/debug.cpp index 2d8819f3..62e88914 100644 --- a/al/debug.cpp +++ b/al/debug.cpp @@ -17,9 +17,14 @@ #include "alc/context.h" #include "alc/inprogext.h" #include "alspan.h" +#include "auxeffectslot.h" +#include "buffer.h" #include "core/logging.h" #include "direct_defs.h" +#include "effect.h" +#include "filter.h" #include "opthelpers.h" +#include "source.h" namespace { @@ -242,13 +247,8 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, if(!message) UNLIKELY return context->setError(AL_INVALID_VALUE, "Null message pointer"); - if(length >= MaxDebugMessageLength) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Debug message too long (%d >= %d)", length, - MaxDebugMessageLength); - auto msgview = (length < 0) ? std::string_view{message} : std::string_view{message, static_cast(length)}; - if(msgview.length() >= MaxDebugMessageLength) UNLIKELY return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu >= %d)", msgview.length(), MaxDebugMessageLength); @@ -472,3 +472,94 @@ FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context return count; } + +FORCE_ALIGN DECL_FUNCEXT4(void, alObjectLabel,EXT, ALenum, ALuint, ALsizei, const ALchar*) +FORCE_ALIGN void AL_APIENTRY alObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, + ALuint name, ALsizei length, const ALchar *label) noexcept +{ + if(!label && length != 0) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Null label pointer"); + + auto objname = (length < 0) ? std::string_view{label} + : std::string_view{label, static_cast(length)}; + if(objname.length() >= MaxObjectLabelLength) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Object label length too long (%zu >= %d)", + objname.length(), MaxObjectLabelLength); + + if(identifier == AL_SOURCE_EXT) + return ALsource::SetName(context, name, objname); + if(identifier == AL_BUFFER) + return ALbuffer::SetName(context, name, objname); + if(identifier == AL_FILTER_EXT) + return ALfilter::SetName(context, name, objname); + if(identifier == AL_EFFECT_EXT) + return ALeffect::SetName(context, name, objname); + if(identifier == AL_AUXILIARY_EFFECT_SLOT_EXT) + return ALeffectslot::SetName(context, name, objname); + + return context->setError(AL_INVALID_ENUM, "Invalid name identifier 0x%04x", identifier); +} + +FORCE_ALIGN DECL_FUNCEXT5(void, alGetObjectLabel,EXT, ALenum, ALuint, ALsizei, ALsizei*, ALchar*) +FORCE_ALIGN void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, + ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) noexcept +{ + if(bufSize < 0) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Negative label bufSize"); + + if(!label && !length) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Null length and label"); + if(label && bufSize == 0) UNLIKELY + return context->setError(AL_INVALID_VALUE, "Zero label bufSize"); + + auto copy_name = [name,bufSize,length,label](std::unordered_map &names) + { + std::string_view objname; + + auto iter = names.find(name); + if(iter != names.end()) + objname = iter->second; + + if(!label) + *length = static_cast(objname.length()); + else + { + const size_t tocopy{minz(objname.length(), static_cast(bufSize)-1)}; + std::memcpy(label, objname.data(), tocopy); + label[tocopy] = '\0'; + if(length) + *length = static_cast(tocopy); + } + }; + + if(identifier == AL_SOURCE_EXT) + { + std::lock_guard _{context->mSourceLock}; + copy_name(context->mSourceNames); + } + else if(identifier == AL_BUFFER) + { + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->BufferLock}; + copy_name(device->mBufferNames); + } + else if(identifier == AL_FILTER_EXT) + { + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->FilterLock}; + copy_name(device->mFilterNames); + } + else if(identifier == AL_EFFECT_EXT) + { + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->EffectLock}; + copy_name(device->mEffectNames); + } + else if(identifier == AL_AUXILIARY_EFFECT_SLOT_EXT) + { + std::lock_guard _{context->mEffectSlotLock}; + copy_name(context->mEffectSlotNames); + } + else + context->setError(AL_INVALID_ENUM, "Invalid name identifier 0x%04x", identifier); +} diff --git a/al/debug.h b/al/debug.h index 0c53f0ae..2764bb7f 100644 --- a/al/debug.h +++ b/al/debug.h @@ -14,6 +14,7 @@ using uint = unsigned int; inline constexpr uint8_t MaxDebugLoggedMessages{64}; inline constexpr uint16_t MaxDebugMessageLength{1024}; inline constexpr uint8_t MaxDebugGroupDepth{64}; +inline constexpr uint16_t MaxObjectLabelLength{1024}; inline constexpr uint DebugSourceBase{0}; diff --git a/al/effect.cpp b/al/effect.cpp index 81cbb4c6..5c7f9627 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -207,6 +207,8 @@ ALeffect *AllocEffect(ALCdevice *device) void FreeEffect(ALCdevice *device, ALeffect *effect) { + device->mEffectNames.erase(effect->id); + const ALuint id{effect->id - 1}; const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; @@ -511,6 +513,19 @@ void InitEffect(ALeffect *effect) InitEffectParams(effect, AL_EFFECT_NULL); } +void ALeffect::SetName(ALCcontext* context, ALuint id, std::string_view name) +{ + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->EffectLock}; + + auto effect = LookupEffect(device, id); + if(!effect) UNLIKELY + return context->setError(AL_INVALID_NAME, "Invalid effect ID %u", id); + + device->mEffectNames.insert_or_assign(id, name); +} + + EffectSubList::~EffectSubList() { if(!Effects) diff --git a/al/effect.h b/al/effect.h index a1d43313..3d05e692 100644 --- a/al/effect.h +++ b/al/effect.h @@ -50,6 +50,8 @@ struct ALeffect { /* Self ID */ ALuint id{0u}; + static void SetName(ALCcontext *context, ALuint id, std::string_view name); + DISABLE_ALLOC() }; diff --git a/al/filter.cpp b/al/filter.cpp index 9ad57b54..e6520e6a 100644 --- a/al/filter.cpp +++ b/al/filter.cpp @@ -163,6 +163,8 @@ ALfilter *AllocFilter(ALCdevice *device) void FreeFilter(ALCdevice *device, ALfilter *filter) { + device->mFilterNames.erase(filter->id); + const ALuint id{filter->id - 1}; const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; @@ -671,6 +673,19 @@ FORCE_ALIGN void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint fil } +void ALfilter::SetName(ALCcontext *context, ALuint id, std::string_view name) +{ + ALCdevice *device{context->mALDevice.get()}; + std::lock_guard _{device->FilterLock}; + + auto filter = LookupFilter(device, id); + if(!filter) UNLIKELY + return context->setError(AL_INVALID_NAME, "Invalid filter ID %u", id); + + device->mFilterNames.insert_or_assign(id, name); +} + + FilterSubList::~FilterSubList() { if(!Filters) diff --git a/al/filter.h b/al/filter.h index 2ed483cc..24ebc203 100644 --- a/al/filter.h +++ b/al/filter.h @@ -48,6 +48,8 @@ struct ALfilter { /* Self ID */ ALuint id{0}; + static void SetName(ALCcontext *context, ALuint id, std::string_view name); + DISABLE_ALLOC() }; diff --git a/al/source.cpp b/al/source.cpp index 70182ec8..6bcb7318 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -764,6 +764,8 @@ ALsource *AllocSource(ALCcontext *context) void FreeSource(ALCcontext *context, ALsource *source) { + context->mSourceNames.erase(source->id); + const ALuint id{source->id - 1}; const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; @@ -3614,6 +3616,18 @@ void UpdateAllSourceProps(ALCcontext *context) } } +void ALsource::SetName(ALCcontext *context, ALuint id, std::string_view name) +{ + std::lock_guard _{context->mSourceLock}; + + auto source = LookupSource(context, id); + if(!source) UNLIKELY + return context->setError(AL_INVALID_NAME, "Invalid source ID %u", id); + + context->mSourceNames.insert_or_assign(id, name); +} + + SourceSubList::~SourceSubList() { if(!Sources) diff --git a/al/source.h b/al/source.h index ac97c8a7..2bdeb2a3 100644 --- a/al/source.h +++ b/al/source.h @@ -4,9 +4,10 @@ #include #include #include +#include #include #include -#include +#include #include "AL/al.h" #include "AL/alc.h" @@ -157,6 +158,8 @@ struct ALsource { ALsource(const ALsource&) = delete; ALsource& operator=(const ALsource&) = delete; + static void SetName(ALCcontext *context, ALuint id, std::string_view name); + DISABLE_ALLOC() #ifdef ALSOFT_EAX diff --git a/al/state.cpp b/al/state.cpp index 5b0772c7..1c41d63c 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -152,6 +152,7 @@ enum PropertyValue : ALenum { MaxDebugMessageLength = AL_MAX_DEBUG_MESSAGE_LENGTH_EXT, MaxDebugLoggedMessages = AL_MAX_DEBUG_LOGGED_MESSAGES_EXT, MaxDebugGroupDepth = AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT, + MaxLabelLength = AL_MAX_LABEL_LENGTH_EXT, ContextFlags = AL_CONTEXT_FLAGS_EXT, #ifdef ALSOFT_EAX EaxRamSize = AL_EAX_RAM_SIZE, @@ -245,6 +246,10 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) *values = cast_value(MaxDebugGroupDepth); return; + case AL_MAX_LABEL_LENGTH_EXT: + *values = cast_value(MaxObjectLabelLength); + return; + case AL_CONTEXT_FLAGS_EXT: *values = cast_value(context->mContextFlags.to_ulong()); return; diff --git a/alc/context.h b/alc/context.h index 0611775a..f936bbe8 100644 --- a/alc/context.h +++ b/alc/context.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -146,6 +147,8 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { std::vector mExtensions; std::string mExtensionsString{}; + std::unordered_map mSourceNames; + std::unordered_map mEffectSlotNames; ALCcontext(al::intrusive_ptr device, ContextFlagBitset flags); ALCcontext(const ALCcontext&) = delete; diff --git a/alc/device.h b/alc/device.h index c346dc9e..66f37a7e 100644 --- a/alc/device.h +++ b/alc/device.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -133,6 +134,10 @@ struct ALCdevice : public al::intrusive_ref, DeviceBase { #endif // ALSOFT_EAX + std::unordered_map mBufferNames; + std::unordered_map mEffectNames; + std::unordered_map mFilterNames; + ALCdevice(DeviceType type); ~ALCdevice(); diff --git a/alc/export_list.h b/alc/export_list.h index ed1165d0..89d394a8 100644 --- a/alc/export_list.h +++ b/alc/export_list.h @@ -367,6 +367,10 @@ inline const FuncExport alcFunctions[]{ DECL(alPushDebugGroupDirectEXT), DECL(alPopDebugGroupDirectEXT), DECL(alGetDebugMessageLogDirectEXT), + DECL(alObjectLabelEXT), + DECL(alObjectLabelDirectEXT), + DECL(alGetObjectLabelEXT), + DECL(alGetObjectLabelDirectEXT), /* Extra functions */ DECL(alsoft_set_log_callback), @@ -862,8 +866,14 @@ inline const EnumExport alcEnumerations[]{ DECL(AL_MAX_DEBUG_MESSAGE_LENGTH_EXT), DECL(AL_MAX_DEBUG_LOGGED_MESSAGES_EXT), DECL(AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT), + DECL(AL_MAX_LABEL_LENGTH_EXT), DECL(AL_STACK_OVERFLOW_EXT), DECL(AL_STACK_UNDERFLOW_EXT), + DECL(AL_BUFFER_EXT), + DECL(AL_SOURCE_EXT), + DECL(AL_FILTER_EXT), + DECL(AL_EFFECT_EXT), + DECL(AL_AUXILIARY_EFFECT_SLOT_EXT), DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), #ifdef ALSOFT_EAX diff --git a/alc/inprogext.h b/alc/inprogext.h index 7f5458e5..dc1744ee 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -97,9 +97,15 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_MAX_DEBUG_MESSAGE_LENGTH_EXT 0x19C9 #define AL_MAX_DEBUG_LOGGED_MESSAGES_EXT 0x19CA #define AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT 0x19CB -#define AL_STACK_OVERFLOW_EXT 0x19CC -#define AL_STACK_UNDERFLOW_EXT 0x19CD -#define AL_CONTEXT_FLAGS_EXT 0x19CE +#define AL_MAX_LABEL_LENGTH_EXT 0x19CC +#define AL_STACK_OVERFLOW_EXT 0x19CD +#define AL_STACK_UNDERFLOW_EXT 0x19CE +#define AL_CONTEXT_FLAGS_EXT 0x19CF +#define AL_BUFFER_EXT 0x1009 /* Same as AL_BUFFER */ +#define AL_SOURCE_EXT 0x19D0 +#define AL_FILTER_EXT 0x19D1 +#define AL_EFFECT_EXT 0x19D2 +#define AL_AUXILIARY_EFFECT_SLOT_EXT 0x19D3 typedef void (AL_APIENTRY*ALDEBUGPROCEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKEXT)(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; @@ -108,6 +114,8 @@ typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLEXT)(ALenum source, ALenum type typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPEXT)(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void) AL_API_NOEXCEPT17; typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; @@ -115,6 +123,8 @@ void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum sev void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; void AL_APIENTRY alPopDebugGroupEXT(void) AL_API_NOEXCEPT; ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alObjectLabelEXT(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; +void AL_APIENTRY alGetObjectLabelEXT(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; #endif #endif @@ -236,6 +246,8 @@ typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLDIRECTEXT)(ALCcontext *context, typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPDIRECTEXT)(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPDIRECTEXT)(ALCcontext *context) AL_API_NOEXCEPT17; typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGDIRECTEXT)(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; /* AL_EXT_FOLDBACK */ typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTARTDIRECT)(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTOPDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; @@ -401,6 +413,8 @@ void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum sour void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) AL_API_NOEXCEPT; ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; +void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; void AL_APIENTRY alRequestFoldbackStartDirect(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT; void AL_APIENTRY alRequestFoldbackStopDirect(ALCcontext *context) AL_API_NOEXCEPT; @@ -447,11 +461,11 @@ ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, AL #ifndef ALC_SOFT_system_events #define ALC_SOFT_system_events -#define ALC_PLAYBACK_DEVICE_SOFT 0x19CF -#define ALC_CAPTURE_DEVICE_SOFT 0x19D0 -#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D1 -#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D2 -#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D3 +#define ALC_PLAYBACK_DEVICE_SOFT 0x19D4 +#define ALC_CAPTURE_DEVICE_SOFT 0x19D5 +#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D6 +#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D7 +#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D8 typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCenum deviceType, ALCdevice *device, ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17; typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT17; -- cgit v1.2.3 From 5ae60a58ead6b9eda23cbaf953dec90292031aa7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 11 Aug 2023 08:08:44 -0700 Subject: Track the current/active format for pipewire nodes --- alc/backends/pipewire.cpp | 140 ++++++++++++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 55 deletions(-) (limited to 'alc') diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 9a63d2f4..dbca20d9 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -461,10 +461,10 @@ struct NodeProxy { static constexpr pw_node_events nodeEvents{CreateNodeEvents()}; ppw_node_add_listener(mNode.get(), &mListener, &nodeEvents, this); - /* Track changes to the enumerable formats (indicates the default - * format, which is what we're interested in). + /* Track changes to the enumerable and current formats (indicates the + * default and active format, which is what we're interested in). */ - uint32_t fmtids[]{SPA_PARAM_EnumFormat}; + uint32_t fmtids[]{SPA_PARAM_EnumFormat, SPA_PARAM_Format}; ppw_node_subscribe_params(mNode.get(), std::data(fmtids), std::size(fmtids)); } ~NodeProxy() @@ -643,9 +643,9 @@ struct DeviceNode { static void Remove(uint32_t id); static auto GetList() noexcept { return al::span{sList}; } - void parseSampleRate(const spa_pod *value) noexcept; - void parsePositions(const spa_pod *value) noexcept; - void parseChannelCount(const spa_pod *value) noexcept; + void parseSampleRate(const spa_pod *value, bool force_update) noexcept; + void parsePositions(const spa_pod *value, bool force_update) noexcept; + void parseChannelCount(const spa_pod *value, bool force_update) noexcept; void callEvent(alc::EventType type, std::string_view message) { @@ -769,7 +769,7 @@ bool MatchChannelMap(const al::span map0, const spa_audio_channe return true; } -void DeviceNode::parseSampleRate(const spa_pod *value) noexcept +void DeviceNode::parseSampleRate(const spa_pod *value, bool force_update) noexcept { /* TODO: Can this be anything else? Long, Float, Double? */ uint32_t nvals{}, choiceType{}; @@ -778,7 +778,7 @@ void DeviceNode::parseSampleRate(const spa_pod *value) noexcept const uint podType{get_pod_type(value)}; if(podType != SPA_TYPE_Int) { - WARN("Unhandled sample rate POD type: %u\n", podType); + WARN(" Unhandled sample rate POD type: %u\n", podType); return; } @@ -786,15 +786,15 @@ void DeviceNode::parseSampleRate(const spa_pod *value) noexcept { if(nvals != 3) { - WARN("Unexpected SPA_CHOICE_Range count: %u\n", nvals); + WARN(" Unexpected SPA_CHOICE_Range count: %u\n", nvals); return; } auto srates = get_pod_body(value); /* [0] is the default, [1] is the min, and [2] is the max. */ - TRACE("Device ID %" PRIu64 " sample rate: %d (range: %d -> %d)\n", mSerial, srates[0], - srates[1], srates[2]); - mSampleRate = static_cast(clampi(srates[0], MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)); + TRACE(" sample rate: %d (range: %d -> %d)\n", srates[0], srates[1], srates[2]); + if(!mSampleRate || force_update) + mSampleRate = static_cast(clampi(srates[0], MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)); return; } @@ -802,7 +802,7 @@ void DeviceNode::parseSampleRate(const spa_pod *value) noexcept { if(nvals == 0) { - WARN("Unexpected SPA_CHOICE_Enum count: %u\n", nvals); + WARN(" Unexpected SPA_CHOICE_Enum count: %u\n", nvals); return; } auto srates = get_pod_body(value, nvals); @@ -814,7 +814,7 @@ void DeviceNode::parseSampleRate(const spa_pod *value) noexcept others += ", "; others += std::to_string(srates[i]); } - TRACE("Device ID %" PRIu64 " sample rate: %d (%s)\n", mSerial, srates[0], others.c_str()); + TRACE(" sample rate: %d (%s)\n", srates[0], others.c_str()); /* Pick the first rate listed that's within the allowed range (default * rate if possible). */ @@ -822,7 +822,8 @@ void DeviceNode::parseSampleRate(const spa_pod *value) noexcept { if(rate >= MIN_OUTPUT_RATE && rate <= MAX_OUTPUT_RATE) { - mSampleRate = static_cast(rate); + if(!mSampleRate || force_update) + mSampleRate = static_cast(rate); break; } } @@ -833,63 +834,88 @@ void DeviceNode::parseSampleRate(const spa_pod *value) noexcept { if(nvals != 1) { - WARN("Unexpected SPA_CHOICE_None count: %u\n", nvals); + WARN(" Unexpected SPA_CHOICE_None count: %u\n", nvals); return; } auto srates = get_pod_body(value); - TRACE("Device ID %" PRIu64 " sample rate: %d\n", mSerial, srates[0]); - mSampleRate = static_cast(clampi(srates[0], MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)); + TRACE(" sample rate: %d\n", srates[0]); + if(!mSampleRate || force_update) + mSampleRate = static_cast(clampi(srates[0], MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)); return; } - WARN("Unhandled sample rate choice type: %u\n", choiceType); + WARN(" Unhandled sample rate choice type: %u\n", choiceType); } -void DeviceNode::parsePositions(const spa_pod *value) noexcept +void DeviceNode::parsePositions(const spa_pod *value, bool force_update) noexcept { + uint32_t choiceCount{}, choiceType{}; + value = spa_pod_get_values(value, &choiceCount, &choiceType); + + if(choiceType != SPA_CHOICE_None || choiceCount != 1) + { + ERR(" Unexpected positions choice: type=%u, count=%u\n", choiceType, choiceCount); + return; + } + const auto chanmap = get_array_span(value); if(chanmap.empty()) return; - mIs51Rear = false; - - if(MatchChannelMap(chanmap, X714Map)) - mChannels = DevFmtX714; - else if(MatchChannelMap(chanmap, X71Map)) - mChannels = DevFmtX71; - else if(MatchChannelMap(chanmap, X61Map)) - mChannels = DevFmtX61; - else if(MatchChannelMap(chanmap, X51Map)) - mChannels = DevFmtX51; - else if(MatchChannelMap(chanmap, X51RearMap)) - { - mChannels = DevFmtX51; - mIs51Rear = true; - } - else if(MatchChannelMap(chanmap, QuadMap)) - mChannels = DevFmtQuad; - else if(MatchChannelMap(chanmap, StereoMap)) - mChannels = DevFmtStereo; - else - mChannels = DevFmtMono; - TRACE("Device ID %" PRIu64 " got %zu position%s for %s%s\n", mSerial, chanmap.size(), - (chanmap.size()==1)?"":"s", DevFmtChannelsString(mChannels), mIs51Rear?"(rear)":""); + if(mChannels == InvalidChannelConfig || force_update) + { + mIs51Rear = false; + + if(MatchChannelMap(chanmap, X714Map)) + mChannels = DevFmtX714; + else if(MatchChannelMap(chanmap, X71Map)) + mChannels = DevFmtX71; + else if(MatchChannelMap(chanmap, X61Map)) + mChannels = DevFmtX61; + else if(MatchChannelMap(chanmap, X51Map)) + mChannels = DevFmtX51; + else if(MatchChannelMap(chanmap, X51RearMap)) + { + mChannels = DevFmtX51; + mIs51Rear = true; + } + else if(MatchChannelMap(chanmap, QuadMap)) + mChannels = DevFmtQuad; + else if(MatchChannelMap(chanmap, StereoMap)) + mChannels = DevFmtStereo; + else + mChannels = DevFmtMono; + } + TRACE(" %zu position%s for %s%s\n", chanmap.size(), (chanmap.size()==1)?"":"s", + DevFmtChannelsString(mChannels), mIs51Rear?"(rear)":""); } -void DeviceNode::parseChannelCount(const spa_pod *value) noexcept +void DeviceNode::parseChannelCount(const spa_pod *value, bool force_update) noexcept { /* As a fallback with just a channel count, just assume mono or stereo. */ + uint32_t choiceCount{}, choiceType{}; + value = spa_pod_get_values(value, &choiceCount, &choiceType); + + if(choiceType != SPA_CHOICE_None || choiceCount != 1) + { + ERR(" Unexpected positions choice: type=%u, count=%u\n", choiceType, choiceCount); + return; + } + const auto chancount = get_value(value); if(!chancount) return; - mIs51Rear = false; + if(mChannels == InvalidChannelConfig || force_update) + { + mIs51Rear = false; - if(*chancount >= 2) - mChannels = DevFmtStereo; - else if(*chancount >= 1) - mChannels = DevFmtMono; - TRACE("Device ID %" PRIu64 " got %d channel%s for %s\n", mSerial, *chancount, - (*chancount==1)?"":"s", DevFmtChannelsString(mChannels)); + if(*chancount >= 2) + mChannels = DevFmtStereo; + else if(*chancount >= 1) + mChannels = DevFmtMono; + } + TRACE(" %d channel%s for %s\n", *chancount, (*chancount==1)?"":"s", + DevFmtChannelsString(mChannels)); } @@ -992,18 +1018,22 @@ void NodeProxy::infoCallback(const pw_node_info *info) noexcept void NodeProxy::paramCallback(int, uint32_t id, uint32_t, uint32_t, const spa_pod *param) noexcept { - if(id == SPA_PARAM_EnumFormat) + if(id == SPA_PARAM_EnumFormat || id == SPA_PARAM_Format) { DeviceNode *node{DeviceNode::Find(mId)}; if(!node) UNLIKELY return; + TRACE("Device ID %" PRIu64 " %s format:\n", node->mSerial, + (id == SPA_PARAM_EnumFormat) ? "enumerable" : "current"); + + const bool force_update{id == SPA_PARAM_Format}; if(const spa_pod_prop *prop{spa_pod_find_prop(param, nullptr, SPA_FORMAT_AUDIO_rate)}) - node->parseSampleRate(&prop->value); + node->parseSampleRate(&prop->value, force_update); if(const spa_pod_prop *prop{spa_pod_find_prop(param, nullptr, SPA_FORMAT_AUDIO_position)}) - node->parsePositions(&prop->value); + node->parsePositions(&prop->value, force_update); else if((prop=spa_pod_find_prop(param, nullptr, SPA_FORMAT_AUDIO_channels)) != nullptr) - node->parseChannelCount(&prop->value); + node->parseChannelCount(&prop->value, force_update); } } -- cgit v1.2.3 From 3b7e3a164fa0ea734308f1db69c8537ac4bab4d2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 11 Aug 2023 13:11:42 -0700 Subject: Make AL(C)_EXT_debug public --- alc/alc.cpp | 2 +- alc/context.cpp | 2 +- alc/inprogext.h | 66 ------------------------------------------------------ include/AL/alext.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 68 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index 45a55793..b2a5355a 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -312,7 +312,7 @@ constexpr ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT " "ALC_ENUMERATION_EXT " "ALC_EXT_CAPTURE " - "ALC_EXTX_debug " + "ALC_EXT_debug " "ALC_EXT_DEDICATED " "ALC_EXTX_direct_context " "ALC_EXT_disconnect " diff --git a/alc/context.cpp b/alc/context.cpp index 142ad50c..9c5a62c4 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -53,7 +53,7 @@ std::vector getContextExtensions() noexcept return std::vector{ "AL_EXT_ALAW", "AL_EXT_BFORMAT", - "AL_EXTX_debug", + "AL_EXT_debug", "AL_EXTX_direct_context", "AL_EXT_DOUBLE", "AL_EXT_EXPONENT_DISTANCE", diff --git a/alc/inprogext.h b/alc/inprogext.h index dc1744ee..739af517 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -62,72 +62,6 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #define AL_STOP_SOURCES_ON_DISCONNECT_SOFT 0x19AB #endif -#ifndef ALC_EXT_debug -#define ALC_EXT_debug -#define ALC_CONTEXT_FLAGS_EXT 0x19CE -#define ALC_CONTEXT_DEBUG_BIT_EXT 0x0001 -#endif - -#ifndef AL_EXT_debug -#define AL_EXT_debug -#define AL_DONT_CARE_EXT 0x0002 -#define AL_DEBUG_OUTPUT_EXT 0x19B2 -#define AL_DEBUG_CALLBACK_FUNCTION_EXT 0x19B3 -#define AL_DEBUG_CALLBACK_USER_PARAM_EXT 0x19B4 -#define AL_DEBUG_SOURCE_API_EXT 0x19B5 -#define AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT 0x19B6 -#define AL_DEBUG_SOURCE_THIRD_PARTY_EXT 0x19B7 -#define AL_DEBUG_SOURCE_APPLICATION_EXT 0x19B8 -#define AL_DEBUG_SOURCE_OTHER_EXT 0x19B9 -#define AL_DEBUG_TYPE_ERROR_EXT 0x19BA -#define AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT 0x19BB -#define AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT 0x19BC -#define AL_DEBUG_TYPE_PORTABILITY_EXT 0x19BD -#define AL_DEBUG_TYPE_PERFORMANCE_EXT 0x19BE -#define AL_DEBUG_TYPE_MARKER_EXT 0x19BF -#define AL_DEBUG_TYPE_PUSH_GROUP_EXT 0x19C0 -#define AL_DEBUG_TYPE_POP_GROUP_EXT 0x19C1 -#define AL_DEBUG_TYPE_OTHER_EXT 0x19C2 -#define AL_DEBUG_SEVERITY_HIGH_EXT 0x19C3 -#define AL_DEBUG_SEVERITY_MEDIUM_EXT 0x19C4 -#define AL_DEBUG_SEVERITY_LOW_EXT 0x19C5 -#define AL_DEBUG_SEVERITY_NOTIFICATION_EXT 0x19C6 -#define AL_DEBUG_LOGGED_MESSAGES_EXT 0x19C7 -#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT 0x19C8 -#define AL_MAX_DEBUG_MESSAGE_LENGTH_EXT 0x19C9 -#define AL_MAX_DEBUG_LOGGED_MESSAGES_EXT 0x19CA -#define AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT 0x19CB -#define AL_MAX_LABEL_LENGTH_EXT 0x19CC -#define AL_STACK_OVERFLOW_EXT 0x19CD -#define AL_STACK_UNDERFLOW_EXT 0x19CE -#define AL_CONTEXT_FLAGS_EXT 0x19CF -#define AL_BUFFER_EXT 0x1009 /* Same as AL_BUFFER */ -#define AL_SOURCE_EXT 0x19D0 -#define AL_FILTER_EXT 0x19D1 -#define AL_EFFECT_EXT 0x19D2 -#define AL_AUXILIARY_EFFECT_SLOT_EXT 0x19D3 - -typedef void (AL_APIENTRY*ALDEBUGPROCEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKEXT)(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLEXT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPEXT)(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void) AL_API_NOEXCEPT17; -typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALGETOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; -#ifdef AL_ALEXT_PROTOTYPES -void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; -void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; -void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; -void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; -void AL_APIENTRY alPopDebugGroupEXT(void) AL_API_NOEXCEPT; -ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; -void AL_APIENTRY alObjectLabelEXT(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; -void AL_APIENTRY alGetObjectLabelEXT(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; -#endif -#endif - #ifndef AL_EXT_direct_context #define AL_EXT_direct_context diff --git a/include/AL/alext.h b/include/AL/alext.h index c4f4d4b2..7ac09010 100644 --- a/include/AL/alext.h +++ b/include/AL/alext.h @@ -647,6 +647,72 @@ void AL_APIENTRY alSourcePlayAtTimevSOFT(ALsizei n, const ALuint *sources, ALint #endif #endif +#ifndef ALC_EXT_debug +#define ALC_EXT_debug +#define ALC_CONTEXT_FLAGS_EXT 0x19CE +#define ALC_CONTEXT_DEBUG_BIT_EXT 0x0001 +#endif + +#ifndef AL_EXT_debug +#define AL_EXT_debug +#define AL_DONT_CARE_EXT 0x0002 +#define AL_DEBUG_OUTPUT_EXT 0x19B2 +#define AL_DEBUG_CALLBACK_FUNCTION_EXT 0x19B3 +#define AL_DEBUG_CALLBACK_USER_PARAM_EXT 0x19B4 +#define AL_DEBUG_SOURCE_API_EXT 0x19B5 +#define AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT 0x19B6 +#define AL_DEBUG_SOURCE_THIRD_PARTY_EXT 0x19B7 +#define AL_DEBUG_SOURCE_APPLICATION_EXT 0x19B8 +#define AL_DEBUG_SOURCE_OTHER_EXT 0x19B9 +#define AL_DEBUG_TYPE_ERROR_EXT 0x19BA +#define AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT 0x19BB +#define AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT 0x19BC +#define AL_DEBUG_TYPE_PORTABILITY_EXT 0x19BD +#define AL_DEBUG_TYPE_PERFORMANCE_EXT 0x19BE +#define AL_DEBUG_TYPE_MARKER_EXT 0x19BF +#define AL_DEBUG_TYPE_PUSH_GROUP_EXT 0x19C0 +#define AL_DEBUG_TYPE_POP_GROUP_EXT 0x19C1 +#define AL_DEBUG_TYPE_OTHER_EXT 0x19C2 +#define AL_DEBUG_SEVERITY_HIGH_EXT 0x19C3 +#define AL_DEBUG_SEVERITY_MEDIUM_EXT 0x19C4 +#define AL_DEBUG_SEVERITY_LOW_EXT 0x19C5 +#define AL_DEBUG_SEVERITY_NOTIFICATION_EXT 0x19C6 +#define AL_DEBUG_LOGGED_MESSAGES_EXT 0x19C7 +#define AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT 0x19C8 +#define AL_MAX_DEBUG_MESSAGE_LENGTH_EXT 0x19C9 +#define AL_MAX_DEBUG_LOGGED_MESSAGES_EXT 0x19CA +#define AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT 0x19CB +#define AL_MAX_LABEL_LENGTH_EXT 0x19CC +#define AL_STACK_OVERFLOW_EXT 0x19CD +#define AL_STACK_UNDERFLOW_EXT 0x19CE +#define AL_CONTEXT_FLAGS_EXT 0x19CF +#define AL_BUFFER_EXT 0x1009 /* Same as AL_BUFFER */ +#define AL_SOURCE_EXT 0x19D0 +#define AL_FILTER_EXT 0x19D1 +#define AL_EFFECT_EXT 0x19D2 +#define AL_AUXILIARY_EFFECT_SLOT_EXT 0x19D3 + +typedef void (AL_APIENTRY*ALDEBUGPROCEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKEXT)(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTEXT)(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLEXT)(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPEXT)(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void) AL_API_NOEXCEPT17; +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alPopDebugGroupEXT(void) AL_API_NOEXCEPT; +ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alObjectLabelEXT(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; +void AL_APIENTRY alGetObjectLabelEXT(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; +#endif +#endif + #ifdef __cplusplus } #endif -- cgit v1.2.3 From 2b05b61a4a941280391e7b97e1b6b423e4dae6e2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 13 Aug 2023 09:23:55 -0700 Subject: Don't null check the context in the direct EAX functions --- al/buffer.cpp | 18 ++---------------- alc/context.cpp | 54 +++++++++++++----------------------------------------- 2 files changed, 15 insertions(+), 57 deletions(-) (limited to 'alc') diff --git a/al/buffer.cpp b/al/buffer.cpp index e56aa13e..28afc7c0 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -1474,19 +1474,12 @@ BufferSubList::~BufferSubList() #ifdef ALSOFT_EAX -FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint *buffers, ALint value) noexcept -{ return EAXSetBufferModeDirect(GetContextRef().get(), n, buffers, value); } +FORCE_ALIGN DECL_FUNC3(ALboolean, EAXSetBufferMode, ALsizei, const ALuint*, ALint) FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) noexcept { #define EAX_PREFIX "[EAXSetBufferMode] " - if(!context) - { - ERR(EAX_PREFIX "%s\n", "No current context."); - return AL_FALSE; - } - if(!eax_g_is_enabled) { context->setError(AL_INVALID_OPERATION, EAX_PREFIX "%s", "EAX not enabled."); @@ -1617,19 +1610,12 @@ FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, AL #undef EAX_PREFIX } -FORCE_ALIGN ALenum AL_APIENTRY EAXGetBufferMode(ALuint buffer, ALint *pReserved) noexcept -{ return EAXGetBufferModeDirect(GetContextRef().get(), buffer, pReserved); } +FORCE_ALIGN DECL_FUNC2(ALenum, EAXGetBufferMode, ALuint, ALint*) FORCE_ALIGN ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, ALint *pReserved) noexcept { #define EAX_PREFIX "[EAXGetBufferMode] " - if(!context) - { - ERR(EAX_PREFIX "%s\n", "No current context."); - return AL_NONE; - } - if(!eax_g_is_enabled) { context->setError(AL_INVALID_OPERATION, EAX_PREFIX "%s", "EAX not enabled."); diff --git a/alc/context.cpp b/alc/context.cpp index 9c5a62c4..bba74a59 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -1020,48 +1020,20 @@ void ALCcontext::eaxCommit() eax_update_sources(); } -namespace { - -class EaxSetException : public EaxException { -public: - explicit EaxSetException(const char* message) - : EaxException{"EAX_SET", message} - {} -}; - -[[noreturn]] void eax_fail_set(const char* message) -{ - throw EaxSetException{message}; -} - -class EaxGetException : public EaxException { -public: - explicit EaxGetException(const char* message) - : EaxException{"EAX_GET", message} - {} -}; -[[noreturn]] void eax_fail_get(const char* message) +FORCE_ALIGN ALenum AL_APIENTRY EAXSet(const GUID *a, ALuint b, ALuint c, ALvoid *d, ALuint e) noexcept { - throw EaxGetException{message}; + auto context = GetContextRef(); + if(!context) UNLIKELY return AL_INVALID_OPERATION; + return EAXSetDirect(context.get(), a, b, c, d, e); } -} // namespace - - -FORCE_ALIGN ALenum AL_APIENTRY EAXSet(const GUID *property_set_id, ALuint property_id, - ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept -{ return EAXSetDirect(GetContextRef().get(), property_set_id, property_id, property_source_id, property_value, property_value_size); } FORCE_ALIGN ALenum AL_APIENTRY EAXSetDirect(ALCcontext *context, const GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept try { - if(!context) - eax_fail_set("No current context."); - std::lock_guard prop_lock{context->mPropLock}; - return context->eax_eax_set( property_set_id, property_id, @@ -1069,26 +1041,26 @@ try property_value, property_value_size); } -catch (...) +catch(...) { eax_log_exception(__func__); return AL_INVALID_OPERATION; } -FORCE_ALIGN ALenum AL_APIENTRY EAXGet(const GUID *property_set_id, ALuint property_id, - ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept -{ return EAXGetDirect(GetContextRef().get(), property_set_id, property_id, property_source_id, property_value, property_value_size); } +FORCE_ALIGN ALenum AL_APIENTRY EAXGet(const GUID *a, ALuint b, ALuint c, ALvoid *d, ALuint e) noexcept +{ + auto context = GetContextRef(); + if(!context) UNLIKELY return AL_INVALID_OPERATION; + return EAXGetDirect(context.get(), a, b, c, d, e); +} + FORCE_ALIGN ALenum AL_APIENTRY EAXGetDirect(ALCcontext *context, const GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) noexcept try { - if(!context) - eax_fail_get("No current context."); - std::lock_guard prop_lock{context->mPropLock}; - return context->eax_eax_get( property_set_id, property_id, @@ -1096,7 +1068,7 @@ try property_value, property_value_size); } -catch (...) +catch(...) { eax_log_exception(__func__); return AL_INVALID_OPERATION; -- cgit v1.2.3 From bfb79945d0ed7450ad3e93941f6576ce1cc4058b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 18 Aug 2023 15:59:04 -0700 Subject: Make ALC_SOFT_system_events public --- alc/alc.cpp | 4 ++-- alc/export_list.h | 6 ++++++ alc/inprogext.h | 17 ----------------- include/AL/alext.h | 17 +++++++++++++++++ 4 files changed, 25 insertions(+), 19 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index b2a5355a..6163e004 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -307,7 +307,7 @@ constexpr ALCchar alcNoDeviceExtList[] = "ALC_SOFT_loopback " "ALC_SOFT_loopback_bformat " "ALC_SOFT_reopen_device " - "ALC_SOFTX_system_events"; + "ALC_SOFT_system_events"; constexpr ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT " "ALC_ENUMERATION_EXT " @@ -326,7 +326,7 @@ constexpr ALCchar alcExtensionList[] = "ALC_SOFT_output_mode " "ALC_SOFT_pause_device " "ALC_SOFT_reopen_device " - "ALC_SOFTX_system_events"; + "ALC_SOFT_system_events"; constexpr int alcMajorVersion{1}; constexpr int alcMinorVersion{1}; diff --git a/alc/export_list.h b/alc/export_list.h index 89d394a8..9e92570e 100644 --- a/alc/export_list.h +++ b/alc/export_list.h @@ -489,6 +489,12 @@ inline const EnumExport alcEnumerations[]{ DECL(ALC_CONTEXT_FLAGS_EXT), DECL(ALC_CONTEXT_DEBUG_BIT_EXT), + DECL(ALC_PLAYBACK_DEVICE_SOFT), + DECL(ALC_CAPTURE_DEVICE_SOFT), + DECL(ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT), + DECL(ALC_EVENT_TYPE_DEVICE_ADDED_SOFT), + DECL(ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT), + DECL(AL_INVALID), DECL(AL_NONE), diff --git a/alc/inprogext.h b/alc/inprogext.h index 739af517..fe2a1437 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -393,23 +393,6 @@ ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, AL #endif #endif -#ifndef ALC_SOFT_system_events -#define ALC_SOFT_system_events -#define ALC_PLAYBACK_DEVICE_SOFT 0x19D4 -#define ALC_CAPTURE_DEVICE_SOFT 0x19D5 -#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D6 -#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D7 -#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D8 -typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCenum deviceType, - ALCdevice *device, ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17; -typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT17; -typedef void (ALC_APIENTRY*LPALCEVENTCALLBACKSOFT)(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT17; -#ifdef AL_ALEXT_PROTOTYPES -ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT; -void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT; -#endif -#endif - /* Non-standard exports. Not part of any extension. */ AL_API const ALchar* AL_APIENTRY alsoft_get_version(void) noexcept; diff --git a/include/AL/alext.h b/include/AL/alext.h index 7ac09010..0e8a2d2f 100644 --- a/include/AL/alext.h +++ b/include/AL/alext.h @@ -713,6 +713,23 @@ void AL_APIENTRY alGetObjectLabelEXT(ALenum identifier, ALuint name, ALsizei buf #endif #endif +#ifndef ALC_SOFT_system_events +#define ALC_SOFT_system_events +#define ALC_PLAYBACK_DEVICE_SOFT 0x19D4 +#define ALC_CAPTURE_DEVICE_SOFT 0x19D5 +#define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D6 +#define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D7 +#define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D8 +typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCenum deviceType, + ALCdevice *device, ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17; +typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT17; +typedef void (ALC_APIENTRY*LPALCEVENTCALLBACKSOFT)(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT; +void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT; +#endif +#endif + #ifdef __cplusplus } #endif -- cgit v1.2.3 From bb841f02fb06148bba422e92a9b1a6b46ab3bde3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 18 Aug 2023 18:40:08 -0700 Subject: Use a string instead of a c_str for a string_view --- alc/alc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index 6163e004..9dc99a5d 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -366,7 +366,7 @@ void alc_initconfig(void) if(logf) gLogFile = logf; else { - auto u8name = wstr_to_utf8(logfile->c_str()); + auto u8name = wstr_to_utf8(*logfile); ERR("Failed to open log file '%s'\n", u8name.c_str()); } } -- cgit v1.2.3 From eaad1b353611d589653f3b7ea2d671f3a59a42b0 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 21 Aug 2023 02:43:34 -0700 Subject: Clear errno prior to the call that may set it --- alc/backends/pipewire.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'alc') diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index dbca20d9..ede4399b 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -965,6 +965,7 @@ void NodeProxy::infoCallback(const pw_node_info *info) noexcept #ifdef PW_KEY_OBJECT_SERIAL if(const char *serial_str{spa_dict_lookup(info->props, PW_KEY_OBJECT_SERIAL)}) { + errno = 0; char *serial_end{}; serial_id = std::strtoull(serial_str, &serial_end, 0); if(*serial_end != '\0' || errno == ERANGE) -- cgit v1.2.3 From 4b924e636b6e0651304b289a667d358d336d6d03 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 25 Aug 2023 02:10:18 -0700 Subject: Allow querying AL_EFFECTSLOT_EFFECT This doesn't make much sense since the effect associated with the ID may be modified and not represent the effect being played, or was even deleted and isn't a valid effect ID, but Generic Software allows querying it so it should be queryable for compatibility if nothing else. --- al/auxeffectslot.cpp | 14 ++++++++++---- al/auxeffectslot.h | 4 +++- alc/alc.cpp | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) (limited to 'alc') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 09db0736..66a65b5c 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -548,12 +548,12 @@ FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, A std::lock_guard ___{device->EffectLock}; ALeffect *effect{value ? LookupEffect(device, static_cast(value)) : nullptr}; if(effect) - err = slot->initEffect(effect->type, effect->Props, context); + err = slot->initEffect(effect->id, effect->type, effect->Props, context); else { if(value != 0) return context->setError(AL_INVALID_VALUE, "Invalid effect ID %u", value); - err = slot->initEffect(AL_EFFECT_NULL, EffectProps{}, context); + err = slot->initEffect(0, AL_EFFECT_NULL, EffectProps{}, context); } } if(err != AL_NO_ERROR) UNLIKELY @@ -754,6 +754,10 @@ FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotiDirect(ALCcontext *context switch(param) { + case AL_EFFECTSLOT_EFFECT: + *value = static_cast(slot->EffectId); + break; + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: *value = slot->AuxSendAuto ? AL_TRUE : AL_FALSE; break; @@ -887,7 +891,7 @@ ALeffectslot::~ALeffectslot() mSlot->InUse = false; } -ALenum ALeffectslot::initEffect(ALenum effectType, const EffectProps &effectProps, +ALenum ALeffectslot::initEffect(ALuint effectId, ALenum effectType, const EffectProps &effectProps, ALCcontext *context) { EffectSlotType newtype{EffectSlotTypeFromEnum(effectType)}; @@ -916,6 +920,7 @@ ALenum ALeffectslot::initEffect(ALenum effectType, const EffectProps &effectProp } else if(newtype != EffectSlotType::None) Effect.Props = effectProps; + EffectId = effectId; /* Remove state references from old effect slot property updates. */ EffectSlotProps *props{context->mFreeEffectslotProps.load()}; @@ -1445,7 +1450,8 @@ void ALeffectslot::eax_set_efx_slot_effect(EaxEffect &effect) { #define EAX_PREFIX "[EAX_SET_EFFECT_SLOT_EFFECT] " - const auto error = initEffect(effect.al_effect_type_, effect.al_effect_props_, eax_al_context_); + const auto error = initEffect(0, effect.al_effect_type_, effect.al_effect_props_, + eax_al_context_); if(error != AL_NO_ERROR) { ERR(EAX_PREFIX "%s\n", "Failed to initialize an effect."); diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 9038647c..1ad0ffc4 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -46,6 +46,7 @@ enum class SlotState : ALenum { }; struct ALeffectslot { + ALuint EffectId{}; float Gain{1.0f}; bool AuxSendAuto{true}; ALeffectslot *Target{nullptr}; @@ -74,7 +75,8 @@ struct ALeffectslot { ALeffectslot& operator=(const ALeffectslot&) = delete; ~ALeffectslot(); - ALenum initEffect(ALenum effectType, const EffectProps &effectProps, ALCcontext *context); + ALenum initEffect(ALuint effectId, ALenum effectType, const EffectProps &effectProps, + ALCcontext *context); void updateProps(ALCcontext *context); static void SetName(ALCcontext *context, ALuint id, std::string_view name); diff --git a/alc/alc.cpp b/alc/alc.cpp index 9dc99a5d..0c42edbc 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2728,7 +2728,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin if(ALeffectslot *slot{context->mDefaultSlot.get()}) { - ALenum sloterr{slot->initEffect(ALCcontext::sDefaultEffect.type, + ALenum sloterr{slot->initEffect(0, ALCcontext::sDefaultEffect.type, ALCcontext::sDefaultEffect.Props, context.get())}; if(sloterr == AL_NO_ERROR) slot->updateProps(context.get()); -- cgit v1.2.3 From 098acdef7b3089801fa1a37411b512227e4fe335 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 28 Aug 2023 22:18:36 -0700 Subject: Avoid some large stack buffers --- alc/effects/modulator.cpp | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'alc') diff --git a/alc/effects/modulator.cpp b/alc/effects/modulator.cpp index 14ee5004..cf0e16a6 100644 --- a/alc/effects/modulator.cpp +++ b/alc/effects/modulator.cpp @@ -45,8 +45,6 @@ namespace { using uint = unsigned int; -#define MAX_UPDATE_SAMPLES 128 - #define WAVEFORM_FRACBITS 24 #define WAVEFORM_FRACONE (1< samplesIn, const al::span samplesOut) { - for(size_t base{0u};base < samplesToDo;) - { - alignas(16) float modsamples[MAX_UPDATE_SAMPLES]; - const size_t td{minz(MAX_UPDATE_SAMPLES, samplesToDo-base)}; - - mGetSamples(modsamples, mIndex, mStep, td); - mIndex += static_cast(mStep * td); - mIndex &= WAVEFORM_FRACMASK; + mGetSamples(mModSamples.data(), mIndex, mStep, samplesToDo); + mIndex += static_cast(mStep * samplesToDo); + mIndex &= WAVEFORM_FRACMASK; - auto chandata = std::begin(mChans); - for(const auto &input : samplesIn) + auto chandata = std::begin(mChans); + for(const auto &input : samplesIn) + { + const size_t outidx{chandata->mTargetChannel}; + if(outidx != InvalidChannelIndex) { - const size_t outidx{chandata->mTargetChannel}; - if(outidx != InvalidChannelIndex) - { - alignas(16) float temps[MAX_UPDATE_SAMPLES]; - - chandata->mFilter.process({&input[base], td}, temps); - for(size_t i{0u};i < td;i++) - temps[i] *= modsamples[i]; - - MixSamples({temps, td}, samplesOut[outidx].data()+base, chandata->mCurrentGain, - chandata->mTargetGain, samplesToDo-base); - } - ++chandata; - } + chandata->mFilter.process({input.data(), samplesToDo}, mBuffer.data()); + for(size_t i{0u};i < samplesToDo;++i) + mBuffer[i] *= mModSamples[i]; - base += td; + MixSamples({mBuffer.data(), samplesToDo}, samplesOut[outidx].data(), + chandata->mCurrentGain, chandata->mTargetGain, minz(samplesToDo, 64)); + } + ++chandata; } } -- cgit v1.2.3 From e987e511a962772c96a2122265874c00cca2a54f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 29 Aug 2023 02:47:56 -0700 Subject: Use a more accurate ring modulator waveform generator This restricts available frequencies to fit an integer number of samples per cycle, but ensures no unintended harmonics from misaligned samples w.r.t. sawtooth and square waveforms. --- alc/effects/modulator.cpp | 113 +++++++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 37 deletions(-) (limited to 'alc') diff --git a/alc/effects/modulator.cpp b/alc/effects/modulator.cpp index cf0e16a6..f99ba19c 100644 --- a/alc/effects/modulator.cpp +++ b/alc/effects/modulator.cpp @@ -45,41 +45,46 @@ namespace { using uint = unsigned int; -#define WAVEFORM_FRACBITS 24 -#define WAVEFORM_FRACONE (1<(index) * scale); } -inline float Sin(uint index) -{ - constexpr float scale{al::numbers::pi_v*2.0f / WAVEFORM_FRACONE}; - return std::sin(static_cast(index) * scale); -} - -inline float Saw(uint index) -{ return static_cast(index)*(2.0f/WAVEFORM_FRACONE) - 1.0f; } +inline float Saw(uint index, float scale) +{ return static_cast(index)*scale - 1.0f; } -inline float Square(uint index) -{ return static_cast(static_cast((index>>(WAVEFORM_FRACBITS-2))&2) - 1); } +inline float Square(uint index, float scale) +{ return (static_cast(index)*scale < 0.5f)*2.0f - 1.0f; } -inline float One(uint) { return 1.0f; } +inline float One(uint, float) +{ return 1.0f; } -template -void Modulate(float *RESTRICT dst, uint index, const uint step, size_t todo) -{ - for(size_t i{0u};i < todo;i++) +struct ModulatorState final : public EffectState { + template + void Modulate(size_t todo) { - index += step; - index &= WAVEFORM_FRACMASK; - dst[i] = func(index); - } -} + const uint range{mRange}; + const float scale{mIndexScale}; + uint index{mIndex}; + ASSUME(range > 1); + ASSUME(todo > 0); -struct ModulatorState final : public EffectState { - void (*mGetSamples)(float*RESTRICT, uint, const uint, size_t){}; + for(size_t i{0};i < todo;) + { + size_t rem{minz(todo-i, range-index)}; + do { + mModSamples[i++] = func(index++, scale); + } while(--rem); + if(index == range) + index = 0; + } + mIndex = index; + } + + void (ModulatorState::*mGenModSamples)(size_t){}; uint mIndex{0}; - uint mStep{1}; + uint mRange{1}; + float mIndexScale{0.0f}; alignas(16) FloatBufferLine mModSamples{}; alignas(16) FloatBufferLine mBuffer{}; @@ -103,6 +108,13 @@ struct ModulatorState final : public EffectState { DEF_NEWDEL(ModulatorState) }; +template<> +void ModulatorState::Modulate(size_t todo) +{ + std::fill_n(mModSamples.begin(), todo, 1.0f); + mIndex = 0; +} + void ModulatorState::deviceUpdate(const DeviceBase*, const BufferStorage*) { for(auto &e : mChans) @@ -118,17 +130,46 @@ void ModulatorState::update(const ContextBase *context, const EffectSlot *slot, { const DeviceBase *device{context->mDevice}; - const float step{props->Modulator.Frequency / static_cast(device->Frequency)}; - mStep = fastf2u(clampf(step*WAVEFORM_FRACONE, 0.0f, float{WAVEFORM_FRACONE-1})); - - if(mStep == 0) - mGetSamples = Modulate; + /* The effective frequency will be adjusted to have a whole number of + * samples per cycle (at 48khz, that allows 8000, 6857.14, 6000, 5333.33, + * 4800, etc). We could do better by using fixed-point stepping over a sin + * function, with additive synthesis for the square and sawtooth waveforms, + * but that may need a more efficient sin function since it needs to do + * many iterations per sample. + */ + const float samplesPerCycle{props->Modulator.Frequency > 0.0f + ? static_cast(device->Frequency)/props->Modulator.Frequency + 0.5f + : 1.0f}; + const uint range{static_cast(clampf(samplesPerCycle, 1.0f, + static_cast(device->Frequency)))}; + mIndex = static_cast(uint64_t{mIndex} * range / mRange); + mRange = range; + + if(mRange == 1) + { + mIndexScale = 0.0f; + mGenModSamples = &ModulatorState::Modulate; + } else if(props->Modulator.Waveform == ModulatorWaveform::Sinusoid) - mGetSamples = Modulate; + { + mIndexScale = al::numbers::pi_v*2.0f / static_cast(mRange); + mGenModSamples = &ModulatorState::Modulate; + } else if(props->Modulator.Waveform == ModulatorWaveform::Sawtooth) - mGetSamples = Modulate; + { + mIndexScale = 2.0f / static_cast(mRange-1); + mGenModSamples = &ModulatorState::Modulate; + } else /*if(props->Modulator.Waveform == ModulatorWaveform::Square)*/ - mGetSamples = Modulate; + { + /* For square wave, the range should be even (there should be an equal + * number of high and low samples). An odd number of samples per cycle + * would need a more complex value generator. + */ + mRange = (mRange+1) & ~1u; + mIndexScale = 1.0f / static_cast(mRange-1); + mGenModSamples = &ModulatorState::Modulate; + } float f0norm{props->Modulator.HighPassCutoff / static_cast(device->Frequency)}; f0norm = clampf(f0norm, 1.0f/512.0f, 0.49f); @@ -148,9 +189,7 @@ void ModulatorState::update(const ContextBase *context, const EffectSlot *slot, void ModulatorState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) { - mGetSamples(mModSamples.data(), mIndex, mStep, samplesToDo); - mIndex += static_cast(mStep * samplesToDo); - mIndex &= WAVEFORM_FRACMASK; + (this->*mGenModSamples)(samplesToDo); auto chandata = std::begin(mChans); for(const auto &input : samplesIn) -- cgit v1.2.3 From c53ee243ec5af8392a15d4e315b36dec4b5f41cf Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 30 Aug 2023 23:45:15 -0700 Subject: Combine separate loops into one --- alc/backends/pipewire.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'alc') diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index ede4399b..6a39df72 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -1444,16 +1444,14 @@ void PipeWirePlayback::outputCallback() noexcept length = minu(length, data.maxsize/sizeof(float)); *chanptr_end = static_cast(data.data); ++chanptr_end; - } - - mDevice->renderSamples({mChannelPtrs.get(), chanptr_end}, length); - for(const auto &data : datas) - { data.chunk->offset = 0; data.chunk->stride = sizeof(float); data.chunk->size = length * sizeof(float); } + + mDevice->renderSamples({mChannelPtrs.get(), chanptr_end}, length); + pw_buf->size = length; pw_stream_queue_buffer(mStream.get(), pw_buf); } @@ -1745,7 +1743,10 @@ void PipeWirePlayback::start() } #endif if(!--wait_count) + { + ERR("Timeout getting PipeWire stream buffering info\n"); break; + } plock.unlock(); std::this_thread::sleep_for(milliseconds{20}); -- cgit v1.2.3 From d2d6365b3f965922f6c25198bcd9de30ccf9f6bb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 31 Aug 2023 04:25:03 -0700 Subject: Handle a null string in DeviceHelper::OnDefaultDeviceChanged --- alc/backends/wasapi.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 96c56fa8..c9ea7980 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -526,18 +526,18 @@ struct DeviceHelper final : private IMMNotificationClient if(role != eMultimedia) return S_OK; + const std::wstring_view devid{pwstrDefaultDeviceId ? pwstrDefaultDeviceId + : std::wstring_view{}}; if(flow == eRender) { - DeviceListLock{gDeviceList}.setPlaybackDefaultId(pwstrDefaultDeviceId); - const std::string msg{"Default playback device changed: "+ - wstr_to_utf8(pwstrDefaultDeviceId)}; + DeviceListLock{gDeviceList}.setPlaybackDefaultId(devid); + const std::string msg{"Default playback device changed: " + wstr_to_utf8(devid)}; alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, msg); } else if(flow == eCapture) { - DeviceListLock{gDeviceList}.setCaptureDefaultId(pwstrDefaultDeviceId); - const std::string msg{"Default capture device changed: "+ - wstr_to_utf8(pwstrDefaultDeviceId)}; + DeviceListLock{gDeviceList}.setCaptureDefaultId(devid); + const std::string msg{"Default capture device changed: " + wstr_to_utf8(devid)}; alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, msg); } return S_OK; -- cgit v1.2.3 From 7d895a9b8b847df55e2a97a216ac7d04d757d1c8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 2 Sep 2023 07:53:23 -0700 Subject: Avoid putting strings in fixed arrays of char arrays --- alc/backends/wasapi.cpp | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index c9ea7980..0dda4d66 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -851,17 +851,22 @@ enum class MsgType { StopDevice, CloseDevice, - Count, - QuitThread = Count + QuitThread }; -constexpr char MessageStr[static_cast(MsgType::Count)][16]{ - "Open Device", - "Reset Device", - "Start Device", - "Stop Device", - "Close Device", -}; +constexpr const char *GetMessageTypeName(MsgType type) noexcept +{ + switch(type) + { + case MsgType::OpenDevice: return "Open Device"; + case MsgType::ResetDevice: return "Reset Device"; + case MsgType::StartDevice: return "Start Device"; + case MsgType::StopDevice: return "Stop Device"; + case MsgType::CloseDevice: return "Close Device"; + case MsgType::QuitThread: break; + } + return ""; +} /* Proxy interface used by the message handler. */ @@ -883,11 +888,11 @@ struct WasapiProxy { explicit operator bool() const noexcept { return mType != MsgType::QuitThread; } }; - static std::deque mMsgQueue; - static std::mutex mMsgQueueLock; - static std::condition_variable mMsgQueueCond; + static inline std::deque mMsgQueue; + static inline std::mutex mMsgQueueLock; + static inline std::condition_variable mMsgQueueCond; - static std::optional sDeviceHelper; + static inline std::optional sDeviceHelper; std::future pushMessage(MsgType type, std::string_view param={}) { @@ -924,10 +929,6 @@ struct WasapiProxy { static int messageHandler(std::promise *promise); }; -std::deque WasapiProxy::mMsgQueue; -std::mutex WasapiProxy::mMsgQueueLock; -std::condition_variable WasapiProxy::mMsgQueueCond; -std::optional WasapiProxy::sDeviceHelper; int WasapiProxy::messageHandler(std::promise *promise) { @@ -958,10 +959,10 @@ int WasapiProxy::messageHandler(std::promise *promise) TRACE("Starting message loop\n"); while(Msg msg{popMessage()}) { - TRACE("Got message \"%s\" (0x%04x, this=%p, param={%p,%zu})\n", - MessageStr[static_cast(msg.mType)], static_cast(msg.mType), - static_cast(msg.mProxy), static_cast(msg.mParam.data()), - msg.mParam.length()); + TRACE("Got message \"%s\" (0x%04x, this=%p, param=\"%.*s\")\n", + GetMessageTypeName(msg.mType), static_cast(msg.mType), + static_cast(msg.mProxy), static_cast(msg.mParam.length()), + msg.mParam.data()); switch(msg.mType) { -- cgit v1.2.3 From 73cad63efd4f34937a7b00a7df18f004eeb832a6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 3 Sep 2023 10:53:08 -0700 Subject: Don't use a custom config for the pipewire event loop --- alc/backends/pipewire.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 6a39df72..1c4e2cc4 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -1146,7 +1146,7 @@ bool EventManager::init() return false; } - mContext = mLoop.newContext(pw_properties_new(PW_KEY_CONFIG_NAME, "client-rt.conf", nullptr)); + mContext = mLoop.newContext(); if(!mContext) { ERR("Failed to create PipeWire event context (errno: %d)\n", errno); -- cgit v1.2.3 From a1841b46a086530174177cb5f3e2cdd1eb1848a2 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 5 Sep 2023 12:05:08 -0700 Subject: Include the early and late reverb gain for the decay fade timer --- alc/effects/reverb.cpp | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'alc') diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index 330c404d..a4155792 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -1244,9 +1244,36 @@ void ReverbState::update(const ContextBase *Context, const EffectSlot *Slot, props->Reverb.DecayTime, hfDecayTime, lf0norm, hf0norm, frequency); } - const float decaySamples{(props->Reverb.ReflectionsDelay + props->Reverb.LateReverbDelay - + props->Reverb.DecayTime) * frequency}; - pipeline.mFadeSampleCount = static_cast(minf(decaySamples, 1'000'000.0f)); + /* Calculate the gain at the start of the late reverb stage, and the gain + * difference from the decay target (0.001, or -60dB). + */ + const float decayBase{props->Reverb.ReflectionsGain * props->Reverb.LateReverbGain}; + const float decayDiff{ReverbDecayGain / decayBase}; + + if(decayDiff < 1.0f) + { + /* Given the DecayTime (the amount of time for the late reverb to decay + * by -60dB), calculate the time to decay to -60dB from the start of + * the late reverb. + */ + const float diffTime{std::log10(decayDiff)*(20.0f / -60.0f) * props->Reverb.DecayTime}; + + const float decaySamples{(props->Reverb.ReflectionsDelay + props->Reverb.LateReverbDelay + + diffTime) * frequency}; + /* Limit to 100,000 samples (a touch over 2 seconds at 48khz) to + * avoid excessive double-processing. + */ + pipeline.mFadeSampleCount = static_cast(minf(decaySamples, 100'000.0f)); + } + else + { + /* Otherwise, if the late reverb already starts at -60dB or less, only + * include the time to get to the late reverb. + */ + const float decaySamples{(props->Reverb.ReflectionsDelay + props->Reverb.LateReverbDelay) + * frequency}; + pipeline.mFadeSampleCount = static_cast(minf(decaySamples, 100'000.0f)); + } } -- cgit v1.2.3 From a89345540520cb4fca40fc394eeac4b5f071680d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 10 Sep 2023 22:50:02 -0700 Subject: Combine multiple divisions into one --- alc/effects/reverb.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'alc') diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index a4155792..429d0225 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -461,8 +461,9 @@ struct ReverbPipeline { void updateDelayLine(const float earlyDelay, const float lateDelay, const float density_mult, const float decayTime, const float frequency); - void update3DPanning(const float *ReflectionsPan, const float *LateReverbPan, - const float earlyGain, const float lateGain, const bool doUpmix, const MixParams *mainMix); + void update3DPanning(const al::span ReflectionsPan, + const al::span LateReverbPan, const float earlyGain, const float lateGain, + const bool doUpmix, const MixParams *mainMix); void processEarly(size_t offset, const size_t samplesToDo, const al::span tempSamples, @@ -1028,7 +1029,7 @@ void ReverbPipeline::updateDelayLine(const float earlyDelay, const float lateDel * focal strength. This function results in a B-Format transformation matrix * that spatially focuses the signal in the desired direction. */ -std::array,4> GetTransformFromVector(const float *vec) +std::array,4> GetTransformFromVector(const al::span vec) { /* Normalize the panning vector according to the N3D scale, which has an * extra sqrt(3) term on the directional components. Converting from OpenAL @@ -1041,9 +1042,10 @@ std::array,4> GetTransformFromVector(const float *vec) float mag{std::sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2])}; if(mag > 1.0f) { - norm[0] = vec[0] / mag * -al::numbers::sqrt3_v; - norm[1] = vec[1] / mag * al::numbers::sqrt3_v; - norm[2] = vec[2] / mag * al::numbers::sqrt3_v; + const float scale{al::numbers::sqrt3_v / mag}; + norm[0] = vec[0] * -scale; + norm[1] = vec[1] * scale; + norm[2] = vec[2] * scale; mag = 1.0f; } else @@ -1066,8 +1068,9 @@ std::array,4> GetTransformFromVector(const float *vec) } /* Update the early and late 3D panning gains. */ -void ReverbPipeline::update3DPanning(const float *ReflectionsPan, const float *LateReverbPan, - const float earlyGain, const float lateGain, const bool doUpmix, const MixParams *mainMix) +void ReverbPipeline::update3DPanning(const al::span ReflectionsPan, + const al::span LateReverbPan, const float earlyGain, const float lateGain, + const bool doUpmix, const MixParams *mainMix) { /* Create matrices that transform a B-Format signal according to the * panning vectors. -- cgit v1.2.3 From 43fac7e95568a2b7205db365a49e3938b05e913b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 11 Sep 2023 02:56:14 -0700 Subject: Approximate sin for the reverb modulator LFO Reverb needs to prioritize efficiency since it's expected that an app may use multiple reverb effects simultaneously, and each individual effect may process twice during a pipeline transition. Approximating sin helps by replacing a per- sample libc call that we don't need to be perfectly accurate. --- alc/effects/reverb.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'alc') diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index 429d0225..b00f638b 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -1505,14 +1505,19 @@ void ReverbPipeline::processEarly(size_t offset, const size_t samplesToDo, void Modulation::calcDelays(size_t todo) { - constexpr float mod_scale{al::numbers::pi_v * 2.0f / MOD_FRACONE}; uint idx{Index}; const uint step{Step}; const float depth{Depth}; for(size_t i{0};i < todo;++i) { idx += step; - const float lfo{std::sin(static_cast(idx&MOD_FRACMASK) * mod_scale)}; + const float x{static_cast(idx&MOD_FRACMASK) * (1.0f/MOD_FRACONE)}; + /* Approximate sin(x*2pi). As long as it roughly fits a sinusoid shape + * and stays within [-1...+1], it needn't be perfect. + */ + const float lfo{!(idx&(MOD_FRACONE>>1)) + ? ((-16.0f * x * x) + (8.0f * x)) + : ((16.0f * x * x) + (-8.0f * x) + (-16.0f * x) + 8.0f)}; ModDelays[i] = (lfo+1.0f) * depth; } Index = idx; -- cgit v1.2.3 From 6722ad196145ef7334d7478bdd375308801e7096 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 11 Sep 2023 19:34:55 -0700 Subject: Make some global and static member variables inline This also seems to work around the problematic MinGW code generation, so the indirection to access it can be removed. --- alc/context.cpp | 8 -------- alc/context.h | 11 +---------- router/al.cpp | 2 -- router/router.cpp | 9 --------- router/router.h | 18 +++++------------- 5 files changed, 6 insertions(+), 42 deletions(-) (limited to 'alc') diff --git a/alc/context.cpp b/alc/context.cpp index bba74a59..3b1de7b9 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -102,7 +102,6 @@ std::vector getContextExtensions() noexcept std::atomic ALCcontext::sGlobalContextLock{false}; std::atomic ALCcontext::sGlobalContext{nullptr}; -thread_local ALCcontext *ALCcontext::sLocalContext{nullptr}; ALCcontext::ThreadCtx::~ThreadCtx() { if(ALCcontext *ctx{std::exchange(ALCcontext::sLocalContext, nullptr)}) @@ -117,13 +116,6 @@ thread_local ALCcontext::ThreadCtx ALCcontext::sThreadContext; ALeffect ALCcontext::sDefaultEffect; -#ifdef __MINGW32__ -ALCcontext *ALCcontext::getThreadContext() noexcept -{ return sLocalContext; } -void ALCcontext::setThreadContext(ALCcontext *context) noexcept -{ sThreadContext.set(context); } -#endif - ALCcontext::ALCcontext(al::intrusive_ptr device, ContextFlagBitset flags) : ContextBase{device.get()}, mALDevice{std::move(device)}, mContextFlags{flags} { diff --git a/alc/context.h b/alc/context.h index f936bbe8..201c8873 100644 --- a/alc/context.h +++ b/alc/context.h @@ -211,7 +211,7 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { private: /* Thread-local current context. */ - static thread_local ALCcontext *sLocalContext; + static inline thread_local ALCcontext *sLocalContext{}; /* Thread-local context handling. This handles attempting to release the * context which may have been left current when the thread is destroyed. @@ -224,17 +224,8 @@ private: static thread_local ThreadCtx sThreadContext; public: - /* HACK: MinGW generates bad code when accessing an extern thread_local - * object. Add a wrapper function for it that only accesses it where it's - * defined. - */ -#ifdef __MINGW32__ - static ALCcontext *getThreadContext() noexcept; - static void setThreadContext(ALCcontext *context) noexcept; -#else static ALCcontext *getThreadContext() noexcept { return sLocalContext; } static void setThreadContext(ALCcontext *context) noexcept { sThreadContext.set(context); } -#endif /* Default effect that applies to sources that don't have an effect on send 0. */ static ALeffect sDefaultEffect; diff --git a/router/al.cpp b/router/al.cpp index c7e01d51..6ed8a626 100644 --- a/router/al.cpp +++ b/router/al.cpp @@ -7,8 +7,6 @@ #include "router.h" -std::atomic CurrentCtxDriver{nullptr}; - #define DECL_THUNK1(R,n,T1) AL_API R AL_APIENTRY n(T1 a) noexcept \ { \ DriverIface *iface = GetThreadDriver(); \ diff --git a/router/router.cpp b/router/router.cpp index b2274c0b..e2ba91d1 100644 --- a/router/router.cpp +++ b/router/router.cpp @@ -17,18 +17,9 @@ #include "version.h" -std::vector DriverList; - -thread_local DriverIface *ThreadCtxDriver; - enum LogLevel LogLevel = LogLevel_Error; FILE *LogFile; -#ifdef __MINGW32__ -DriverIface *GetThreadDriver() noexcept { return ThreadCtxDriver; } -void SetThreadDriver(DriverIface *driver) noexcept { ThreadCtxDriver = driver; } -#endif - static void LoadDriverList(void); diff --git a/router/router.h b/router/router.h index 2a126d42..f5c7f455 100644 --- a/router/router.h +++ b/router/router.h @@ -173,21 +173,13 @@ struct DriverIface { }; using DriverIfacePtr = std::unique_ptr; -extern std::vector DriverList; - -extern thread_local DriverIface *ThreadCtxDriver; -extern std::atomic CurrentCtxDriver; - -/* HACK: MinGW generates bad code when accessing an extern thread_local object. - * Add a wrapper function for it that only accesses it where it's defined. - */ -#ifdef __MINGW32__ -DriverIface *GetThreadDriver() noexcept; -void SetThreadDriver(DriverIface *driver) noexcept; -#else +inline std::vector DriverList; + +inline thread_local DriverIface *ThreadCtxDriver{}; +inline std::atomic CurrentCtxDriver{}; + inline DriverIface *GetThreadDriver() noexcept { return ThreadCtxDriver; } inline void SetThreadDriver(DriverIface *driver) noexcept { ThreadCtxDriver = driver; } -#endif class PtrIntMap { -- cgit v1.2.3 From a7fc952036668d6e6bdf7737cc13e92b4002259c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 12 Sep 2023 22:32:34 -0700 Subject: Add a alcGetProcAddress2 function This is essentially just a copy of alcGetProcAddress. It's purpose is to bypass Creative's router's alcGetProcAddress implementation, which returns its own functions even if given a device handle. When combined with it also wrapping the drivers' device and context handles, that prevents any extention function that needs a recognizable device or context handle from working, like the *Direct functions, as there's no way for the app to get a device or context handle the driver can know about). An alternate function to get function pointers allows a driver to return its own implementation for standard and extension functions, which an application can use to "bootstrap" audio to use a particular driver directly, enabling use of extensions that the router gets in the way of (and also avoid the overhead of the router, however small that may be). --- alc/alc.cpp | 3 +++ alc/export_list.h | 1 + alc/inprogext.h | 4 ++++ 3 files changed, 8 insertions(+) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index 0c42edbc..baa4788f 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2564,6 +2564,9 @@ ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const A } +ALCvoid* ALC_APIENTRY alcGetProcAddress2(ALCdevice *device, const ALCchar *funcName) noexcept +{ return alcGetProcAddress(device, funcName); } + ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName) noexcept { if(!funcName) diff --git a/alc/export_list.h b/alc/export_list.h index 9e92570e..cefe7a09 100644 --- a/alc/export_list.h +++ b/alc/export_list.h @@ -220,6 +220,7 @@ inline const FuncExport alcFunctions[]{ DECL(alGetDebugMessageLogEXT), /* Direct Context functions */ + DECL(alcGetProcAddress2), DECL(alEnableDirect), DECL(alDisableDirect), DECL(alIsEnabledDirect), diff --git a/alc/inprogext.h b/alc/inprogext.h index fe2a1437..2fa425bb 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -65,6 +65,8 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #ifndef AL_EXT_direct_context #define AL_EXT_direct_context +typedef ALCvoid* (ALC_APIENTRY *LPALCGETPROCADDRESS2)(ALCdevice *device, const ALCchar *funcname) AL_API_NOEXCEPT17; + typedef void (AL_APIENTRY *LPALENABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY *LPALDISABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; typedef ALboolean (AL_APIENTRY *LPALISENABLEDDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; @@ -224,6 +226,8 @@ typedef ALenum (AL_APIENTRY *LPEAXGETDIRECT)(ALCcontext *context, const struct _ typedef ALboolean (AL_APIENTRY *LPEAXSETBUFFERMODEDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) AL_API_NOEXCEPT17; typedef ALenum (AL_APIENTRY *LPEAXGETBUFFERMODEDIRECT)(ALCcontext *context, ALuint buffer, ALint *pReserved) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES +ALCvoid* AL_APIENTRY alcGetProcAddress2(ALCdevice *device, const ALchar *funcName) AL_API_NOEXCEPT; + void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; -- cgit v1.2.3 From 2ea092d6ad43c636713f53532d7e68bd5444b91d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 13 Sep 2023 06:06:14 -0700 Subject: Use a span instead of an auto&& to array --- alc/alu.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'alc') diff --git a/alc/alu.cpp b/alc/alu.cpp index 8a4df3d4..b7df47e1 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -921,25 +921,25 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con { if(voice->mAmbiOrder == 1) { - auto&& upsampler = Is2DAmbisonic(voice->mFmtChannels) ? - AmbiScale::FirstOrder2DUp : AmbiScale::FirstOrderUp; + const auto upsampler = Is2DAmbisonic(voice->mFmtChannels) ? + al::span{AmbiScale::FirstOrder2DUp} : al::span{AmbiScale::FirstOrderUp}; UpsampleBFormatTransform(mixmatrix, upsampler, shrot, Device->mAmbiOrder); } else if(voice->mAmbiOrder == 2) { - auto&& upsampler = Is2DAmbisonic(voice->mFmtChannels) ? - AmbiScale::SecondOrder2DUp : AmbiScale::SecondOrderUp; + const auto upsampler = Is2DAmbisonic(voice->mFmtChannels) ? + al::span{AmbiScale::SecondOrder2DUp} : al::span{AmbiScale::SecondOrderUp}; UpsampleBFormatTransform(mixmatrix, upsampler, shrot, Device->mAmbiOrder); } else if(voice->mAmbiOrder == 3) { - auto&& upsampler = Is2DAmbisonic(voice->mFmtChannels) ? - AmbiScale::ThirdOrder2DUp : AmbiScale::ThirdOrderUp; + const auto upsampler = Is2DAmbisonic(voice->mFmtChannels) ? + al::span{AmbiScale::ThirdOrder2DUp} : al::span{AmbiScale::ThirdOrderUp}; UpsampleBFormatTransform(mixmatrix, upsampler, shrot, Device->mAmbiOrder); } else if(voice->mAmbiOrder == 4) { - auto&& upsampler = AmbiScale::FourthOrder2DUp; + const auto upsampler = al::span{AmbiScale::FourthOrder2DUp}; UpsampleBFormatTransform(mixmatrix, upsampler, shrot, Device->mAmbiOrder); } else -- cgit v1.2.3 From f098f253324d4d9b0669e061fab006295d826a53 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 14 Sep 2023 07:31:25 -0700 Subject: Store channel positions as vectors instead of angles To avoid extraneous conversions between angles and vectors --- alc/alu.cpp | 279 ++++++++++++++++++++++++++------------------- alc/effects/chorus.cpp | 8 +- alc/effects/dedicated.cpp | 2 +- alc/effects/distortion.cpp | 2 +- alc/effects/fshifter.cpp | 8 +- alc/effects/pshifter.cpp | 2 +- core/mixer.h | 4 +- 7 files changed, 175 insertions(+), 130 deletions(-) (limited to 'alc') diff --git a/alc/alu.cpp b/alc/alu.cpp index b7df47e1..1fa9d1d4 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -135,12 +135,6 @@ float ZScale{1.0f}; float NfcScale{1.0f}; -struct ChanMap { - Channel channel; - float angle; - float elevation; -}; - using HrtfDirectMixerFunc = void(*)(const FloatBufferSpan LeftOut, const FloatBufferSpan RightOut, const al::span InSamples, float2 *AccumSamples, float *TempBuf, HrtfChannelState *ChanState, const size_t IrSize, const size_t BufferSize); @@ -520,27 +514,76 @@ bool CalcEffectSlotParams(EffectSlot *slot, EffectSlot **sorted_slots, ContextBa } -/* Scales the given azimuth toward the side (+/- pi/2 radians) for positions in - * front. +/* Scales the azimuth of the given vector by 3 if it's in front. Effectively + * scales +/-30 degrees to +/-90 degrees, leaving > +90 and < -90 alone. */ -inline float ScaleAzimuthFront(float azimuth, float scale) +inline std::array ScaleAzimuthFront3(std::array pos) { - const float abs_azi{std::fabs(azimuth)}; - if(!(abs_azi >= al::numbers::pi_v*0.5f)) - return std::copysign(minf(abs_azi*scale, al::numbers::pi_v*0.5f), azimuth); - return azimuth; + if(pos[2] < 0.0f) + { + /* Normalize the length of the x,z components for a 2D vector of the + * azimuth angle. Negate Z since {0,0,-1} is angle 0. + */ + const float len2d{std::sqrt(pos[0]*pos[0] + pos[2]*pos[2])}; + float x{pos[0] / len2d}; + float z{-pos[2] / len2d}; + + /* Z > cos(pi/6) = -30 < azimuth < 30 degrees. */ + if(z > 0.866025403785f) + { + /* Triple the angle represented by x,z. */ + x = x*3.0f - x*x*x*4.0f; + z = z*z*z*4.0f - z*3.0f; + + /* Scale the vector back to fit in 3D. */ + pos[0] = x * len2d; + pos[2] = -z * len2d; + } + else + { + /* If azimuth >= 30 degrees, clamp to 90 degrees. */ + pos[0] = std::copysign(len2d, pos[0]); + pos[2] = 0.0f; + } + } + return pos; } -/* Wraps the given value in radians to stay between [-pi,+pi] */ -inline float WrapRadians(float r) +/* Scales the azimuth of the given vector by 1.5 (3/2) if it's in front. */ +inline std::array ScaleAzimuthFront3_2(std::array pos) { - static constexpr float Pi{al::numbers::pi_v}; - static constexpr float Pi2{Pi*2.0f}; - if(r > Pi) return std::fmod(Pi+r, Pi2) - Pi; - if(r < -Pi) return Pi - std::fmod(Pi-r, Pi2); - return r; + if(pos[2] < 0.0f) + { + const float len2d{std::sqrt(pos[0]*pos[0] + pos[2]*pos[2])}; + float x{pos[0] / len2d}; + float z{-pos[2] / len2d}; + + /* Z > cos(pi/3) = -60 < azimuth < 60 degrees. */ + if(z > 0.5f) + { + /* Halve the angle represented by x,z. */ + x = std::copysign(std::sqrt((1.0f - z) * 0.5f), x); + z = std::sqrt((1.0f + z) * 0.5f); + + /* Triple the angle represented by x,z. */ + x = x*3.0f - x*x*x*4.0f; + z = z*z*z*4.0f - z*3.0f; + + /* Scale the vector back to fit in 3D. */ + pos[0] = x * len2d; + pos[2] = -z * len2d; + } + else + { + /* If azimuth >= 60 degrees, clamp to 90 degrees. */ + pos[0] = std::copysign(len2d, pos[0]); + pos[2] = 0.0f; + } + } + return pos; } + /* Begin ambisonic rotation helpers. * * Rotating first-order B-Format just needs a straight-forward X/Y/Z rotation @@ -696,8 +739,18 @@ void AmbiRotator(AmbiRotateMatrix &matrix, const int order) /* End ambisonic rotation helpers. */ -constexpr float Deg2Rad(float x) noexcept -{ return static_cast(al::numbers::pi / 180.0 * x); } +constexpr float sin30{0.5f}; +constexpr float cos30{0.866025403785f}; +constexpr float sin45{al::numbers::sqrt2_v*0.5f}; +constexpr float cos45{al::numbers::sqrt2_v*0.5f}; +constexpr float sin110{ 0.939692620786f}; +constexpr float cos110{-0.342020143326f}; + +struct ChanPosMap { + Channel channel; + std::array pos; +}; + struct GainTriplet { float Base, HF, LF; }; @@ -706,45 +759,45 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con const al::span WetGain, EffectSlot *(&SendSlots)[MAX_SENDS], const VoiceProps *props, const ContextParams &Context, DeviceBase *Device) { - static constexpr ChanMap MonoMap[1]{ - { FrontCenter, 0.0f, 0.0f } + static constexpr ChanPosMap MonoMap[1]{ + { FrontCenter, std::array{0.0f, 0.0f, -1.0f} } }, RearMap[2]{ - { BackLeft, Deg2Rad(-150.0f), Deg2Rad(0.0f) }, - { BackRight, Deg2Rad( 150.0f), Deg2Rad(0.0f) } + { BackLeft, std::array{-sin30, 0.0f, cos30} }, + { BackRight, std::array{ sin30, 0.0f, cos30} }, }, QuadMap[4]{ - { FrontLeft, Deg2Rad( -45.0f), Deg2Rad(0.0f) }, - { FrontRight, Deg2Rad( 45.0f), Deg2Rad(0.0f) }, - { BackLeft, Deg2Rad(-135.0f), Deg2Rad(0.0f) }, - { BackRight, Deg2Rad( 135.0f), Deg2Rad(0.0f) } + { FrontLeft, std::array{-sin45, 0.0f, -cos45} }, + { FrontRight, std::array{ sin45, 0.0f, -cos45} }, + { BackLeft, std::array{-sin45, 0.0f, cos45} }, + { BackRight, std::array{ sin45, 0.0f, cos45} }, }, X51Map[6]{ - { FrontLeft, Deg2Rad( -30.0f), Deg2Rad(0.0f) }, - { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) }, - { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) }, - { LFE, 0.0f, 0.0f }, - { SideLeft, Deg2Rad(-110.0f), Deg2Rad(0.0f) }, - { SideRight, Deg2Rad( 110.0f), Deg2Rad(0.0f) } + { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, + { FrontRight, std::array{ sin30, 0.0f, -cos30} }, + { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, + { LFE, {} }, + { SideLeft, std::array{-sin110, 0.0f, -cos110} }, + { SideRight, std::array{ sin110, 0.0f, -cos110} }, }, X61Map[7]{ - { FrontLeft, Deg2Rad(-30.0f), Deg2Rad(0.0f) }, - { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) }, - { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) }, - { LFE, 0.0f, 0.0f }, - { BackCenter, Deg2Rad(180.0f), Deg2Rad(0.0f) }, - { SideLeft, Deg2Rad(-90.0f), Deg2Rad(0.0f) }, - { SideRight, Deg2Rad( 90.0f), Deg2Rad(0.0f) } + { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, + { FrontRight, std::array{ sin30, 0.0f, -cos30} }, + { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, + { LFE, {} }, + { BackCenter, std::array{ 0.0f, 0.0f, 1.0f} }, + { SideLeft, std::array{-1.0f, 0.0f, 0.0f} }, + { SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, }, X71Map[8]{ - { FrontLeft, Deg2Rad( -30.0f), Deg2Rad(0.0f) }, - { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) }, - { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) }, - { LFE, 0.0f, 0.0f }, - { BackLeft, Deg2Rad(-150.0f), Deg2Rad(0.0f) }, - { BackRight, Deg2Rad( 150.0f), Deg2Rad(0.0f) }, - { SideLeft, Deg2Rad( -90.0f), Deg2Rad(0.0f) }, - { SideRight, Deg2Rad( 90.0f), Deg2Rad(0.0f) } + { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, + { FrontRight, std::array{ sin30, 0.0f, -cos30} }, + { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, + { LFE, {} }, + { BackLeft, std::array{-sin30, 0.0f, cos30} }, + { BackRight, std::array{ sin30, 0.0f, cos30} }, + { SideLeft, std::array{ -1.0f, 0.0f, 0.0f} }, + { SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, }; - ChanMap StereoMap[2]{ - { FrontLeft, Deg2Rad(-30.0f), Deg2Rad(0.0f) }, - { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) } + ChanPosMap StereoMap[2]{ + { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, + { FrontRight, std::array{ sin30, 0.0f, -cos30} }, }; const auto Frequency = static_cast(Device->Frequency); @@ -762,7 +815,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con } DirectMode DirectChannels{props->DirectChannels}; - const ChanMap *chans{nullptr}; + const ChanPosMap *chans{nullptr}; switch(voice->mFmtChannels) { case FmtMono: @@ -774,11 +827,13 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con case FmtStereo: if(DirectChannels == DirectMode::Off) { - /* Convert counter-clockwise to clock-wise, and wrap between - * [-pi,+pi]. - */ - StereoMap[0].angle = WrapRadians(-props->StereoPan[0]); - StereoMap[1].angle = WrapRadians(-props->StereoPan[1]); + for(size_t i{0};i < 2;++i) + { + /* StereoPan is counter-clockwise in radians. */ + const float a{props->StereoPan[i]}; + StereoMap[i].pos[0] = -std::sin(a); + StereoMap[i].pos[2] = -std::cos(a); + } } chans = StereoMap; break; @@ -844,20 +899,9 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con auto calc_coeffs = [xpos,ypos,zpos](RenderMode mode) { if(mode != RenderMode::Pairwise) - return CalcDirectionCoeffs({xpos, ypos, zpos}); - - /* Clamp Y, in case rounding errors caused it to end up outside - * of -1...+1. - */ - const float ev{std::asin(clampf(ypos, -1.0f, 1.0f))}; - /* Negate Z for right-handed coords with -Z in front. */ - const float az{std::atan2(xpos, -zpos)}; - - /* A scalar of 1.5 for plain stereo results in +/-60 degrees - * being moved to +/-90 degrees for direct right and left - * speaker responses. - */ - return CalcAngleCoeffs(ScaleAzimuthFront(az, 1.5f), ev, 0.0f); + return CalcDirectionCoeffs(std::array{xpos, ypos, zpos}, 0.0f); + const auto pos = ScaleAzimuthFront3_2(std::array{xpos, ypos, zpos}); + return CalcDirectionCoeffs(pos, 0.0f); }; const auto scales = GetAmbiScales(voice->mAmbiScaling); auto coeffs = calc_coeffs(Device->mRenderMode); @@ -1027,7 +1071,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con if(chans[c].channel == LFE) continue; - const auto coeffs = CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f); + const auto coeffs = CalcDirectionCoeffs(chans[c].pos, 0.0f); for(uint i{0};i < NumSends;i++) { @@ -1046,17 +1090,17 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con if(Distance > std::numeric_limits::epsilon()) { - const float src_ev{std::asin(clampf(ypos, -1.0f, 1.0f))}; - const float src_az{std::atan2(xpos, -zpos)}; - if(voice->mFmtChannels == FmtMono) { + const float src_ev{std::asin(clampf(ypos, -1.0f, 1.0f))}; + const float src_az{std::atan2(xpos, -zpos)}; + Device->mHrtf->getCoeffs(src_ev, src_az, Distance*NfcScale, Spread, voice->mChans[0].mDryParams.Hrtf.Target.Coeffs, voice->mChans[0].mDryParams.Hrtf.Target.Delay); voice->mChans[0].mDryParams.Hrtf.Target.Gain = DryGain.Base; - const auto coeffs = CalcAngleCoeffs(src_az, src_ev, Spread); + const auto coeffs = CalcDirectionCoeffs(std::array{xpos, ypos, zpos}, Spread); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) @@ -1076,24 +1120,28 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con * the source position, at full spread (pi*2), each channel is * left unchanged. */ - const float ev{lerpf(src_ev, chans[c].elevation, inv_pi_v/2.0f * Spread)}; - - float az{chans[c].angle - src_az}; - if(az < -pi_v) az += pi_v*2.0f; - else if(az > pi_v) az -= pi_v*2.0f; - - az *= inv_pi_v/2.0f * Spread; + const float a{1.0f - (inv_pi_v/2.0f)*Spread}; + std::array pos{ + lerpf(chans[c].pos[0], xpos, a), + lerpf(chans[c].pos[1], ypos, a), + lerpf(chans[c].pos[2], zpos, a)}; + const float len{std::sqrt(pos[0]*pos[0] + pos[1]*pos[1] + pos[2]*pos[2])}; + if(len < 1.0f) + { + pos[0] /= len; + pos[1] /= len; + pos[2] /= len; + } - az += src_az; - if(az < -pi_v) az += pi_v*2.0f; - else if(az > pi_v) az -= pi_v*2.0f; + const float ev{std::asin(clampf(pos[1], -1.0f, 1.0f))}; + const float az{std::atan2(pos[0], -pos[2])}; Device->mHrtf->getCoeffs(ev, az, Distance*NfcScale, 0.0f, voice->mChans[c].mDryParams.Hrtf.Target.Coeffs, voice->mChans[c].mDryParams.Hrtf.Target.Delay); voice->mChans[c].mDryParams.Hrtf.Target.Gain = DryGain.Base; - const auto coeffs = CalcAngleCoeffs(az, ev, 0.0f); + const auto coeffs = CalcDirectionCoeffs(pos, 0.0f); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) @@ -1123,14 +1171,16 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con /* Get the HRIR coefficients and delays for this channel * position. */ - Device->mHrtf->getCoeffs(chans[c].elevation, chans[c].angle, - std::numeric_limits::infinity(), spread, + const float ev{std::asin(chans[c].pos[1])}; + const float az{std::atan2(chans[c].pos[0], -chans[c].pos[2])}; + + Device->mHrtf->getCoeffs(ev, az, std::numeric_limits::infinity(), spread, voice->mChans[c].mDryParams.Hrtf.Target.Coeffs, voice->mChans[c].mDryParams.Hrtf.Target.Delay); voice->mChans[c].mDryParams.Hrtf.Target.Gain = DryGain.Base; /* Normal panning for auxiliary sends. */ - const auto coeffs = CalcAngleCoeffs(chans[c].angle, chans[c].elevation, spread); + const auto coeffs = CalcDirectionCoeffs(chans[c].pos, spread); for(uint i{0};i < NumSends;i++) { @@ -1170,10 +1220,9 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con auto calc_coeffs = [xpos,ypos,zpos,Spread](RenderMode mode) { if(mode != RenderMode::Pairwise) - return CalcDirectionCoeffs({xpos, ypos, zpos}, Spread); - const float ev{std::asin(clampf(ypos, -1.0f, 1.0f))}; - const float az{std::atan2(xpos, -zpos)}; - return CalcAngleCoeffs(ScaleAzimuthFront(az, 1.5f), ev, Spread); + return CalcDirectionCoeffs(std::array{xpos, ypos, zpos}, Spread); + const auto pos = ScaleAzimuthFront3_2(std::array{xpos, ypos, zpos}); + return CalcDirectionCoeffs(pos, Spread); }; const auto coeffs = calc_coeffs(Device->mRenderMode); @@ -1190,9 +1239,6 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con { using namespace al::numbers; - const float src_ev{std::asin(clampf(ypos, -1.0f, 1.0f))}; - const float src_az{std::atan2(xpos, -zpos)}; - for(size_t c{0};c < num_channels;c++) { /* Special-case LFE */ @@ -1212,22 +1258,22 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con * at the source position, at full spread (pi*2), each * channel position is left unchanged. */ - const float ev{lerpf(src_ev, chans[c].elevation, - inv_pi_v/2.0f * Spread)}; - - float az{chans[c].angle - src_az}; - if(az < -pi_v) az += pi_v*2.0f; - else if(az > pi_v) az -= pi_v*2.0f; - - az *= inv_pi_v/2.0f * Spread; - - az += src_az; - if(az < -pi_v) az += pi_v*2.0f; - else if(az > pi_v) az -= pi_v*2.0f; + const float a{1.0f - (inv_pi_v/2.0f)*Spread}; + std::array pos{ + lerpf(chans[c].pos[0], xpos, a), + lerpf(chans[c].pos[1], ypos, a), + lerpf(chans[c].pos[2], zpos, a)}; + const float len{std::sqrt(pos[0]*pos[0] + pos[1]*pos[1] + pos[2]*pos[2])}; + if(len < 1.0f) + { + pos[0] /= len; + pos[1] /= len; + pos[2] /= len; + } if(Device->mRenderMode == RenderMode::Pairwise) - az = ScaleAzimuthFront(az, 3.0f); - const auto coeffs = CalcAngleCoeffs(az, ev, 0.0f); + pos = ScaleAzimuthFront3(pos); + const auto coeffs = CalcDirectionCoeffs(pos, 0.0f); ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, voice->mChans[c].mDryParams.Gains.Target); @@ -1273,9 +1319,8 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con continue; } - const auto coeffs = CalcAngleCoeffs((Device->mRenderMode == RenderMode::Pairwise) - ? ScaleAzimuthFront(chans[c].angle, 3.0f) : chans[c].angle, - chans[c].elevation, spread); + const auto coeffs = CalcDirectionCoeffs((Device->mRenderMode==RenderMode::Pairwise) + ? ScaleAzimuthFront3(chans[c].pos) : chans[c].pos, spread); ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, voice->mChans[c].mDryParams.Gains.Target); diff --git a/alc/effects/chorus.cpp b/alc/effects/chorus.cpp index 7c281aa5..c84531d4 100644 --- a/alc/effects/chorus.cpp +++ b/alc/effects/chorus.cpp @@ -125,10 +125,10 @@ void ChorusState::update(const ContextBase *Context, const EffectSlot *Slot, /* Gains for left and right sides */ static constexpr auto inv_sqrt2 = static_cast(1.0 / al::numbers::sqrt2); - static constexpr auto lcoeffs_pw = CalcDirectionCoeffs({-1.0f, 0.0f, 0.0f}); - static constexpr auto rcoeffs_pw = CalcDirectionCoeffs({ 1.0f, 0.0f, 0.0f}); - static constexpr auto lcoeffs_nrml = CalcDirectionCoeffs({-inv_sqrt2, 0.0f, inv_sqrt2}); - static constexpr auto rcoeffs_nrml = CalcDirectionCoeffs({ inv_sqrt2, 0.0f, inv_sqrt2}); + static constexpr auto lcoeffs_pw = CalcDirectionCoeffs(std::array{-1.0f, 0.0f, 0.0f}); + static constexpr auto rcoeffs_pw = CalcDirectionCoeffs(std::array{ 1.0f, 0.0f, 0.0f}); + static constexpr auto lcoeffs_nrml = CalcDirectionCoeffs(std::array{-inv_sqrt2, 0.0f, inv_sqrt2}); + static constexpr auto rcoeffs_nrml = CalcDirectionCoeffs(std::array{ inv_sqrt2, 0.0f, inv_sqrt2}); auto &lcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? lcoeffs_nrml : lcoeffs_pw; auto &rcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? rcoeffs_nrml : rcoeffs_pw; diff --git a/alc/effects/dedicated.cpp b/alc/effects/dedicated.cpp index 047e6761..e82b13d9 100644 --- a/alc/effects/dedicated.cpp +++ b/alc/effects/dedicated.cpp @@ -94,7 +94,7 @@ void DedicatedState::update(const ContextBase*, const EffectSlot *slot, } else { - static constexpr auto coeffs = CalcDirectionCoeffs({0.0f, 0.0f, -1.0f}); + static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f}); mOutTarget = target.Main->Buffer; ComputePanGains(target.Main, coeffs.data(), Gain, mTargetGains); diff --git a/alc/effects/distortion.cpp b/alc/effects/distortion.cpp index b4e2167e..392d81c8 100644 --- a/alc/effects/distortion.cpp +++ b/alc/effects/distortion.cpp @@ -95,7 +95,7 @@ void DistortionState::update(const ContextBase *context, const EffectSlot *slot, bandwidth = props->Distortion.EQBandwidth / (cutoff * 0.67f); mBandpass.setParamsFromBandwidth(BiquadType::BandPass, cutoff/frequency/4.0f, 1.0f, bandwidth); - static constexpr auto coeffs = CalcDirectionCoeffs({0.0f, 0.0f, -1.0f}); + static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f}); mOutTarget = target.Main->Buffer; ComputePanGains(target.Main, coeffs.data(), slot->Gain*props->Distortion.Gain, mGain); diff --git a/alc/effects/fshifter.cpp b/alc/effects/fshifter.cpp index 3e6a7385..ec0cc29f 100644 --- a/alc/effects/fshifter.cpp +++ b/alc/effects/fshifter.cpp @@ -164,10 +164,10 @@ void FshifterState::update(const ContextBase *context, const EffectSlot *slot, } static constexpr auto inv_sqrt2 = static_cast(1.0 / al::numbers::sqrt2); - static constexpr auto lcoeffs_pw = CalcDirectionCoeffs({-1.0f, 0.0f, 0.0f}); - static constexpr auto rcoeffs_pw = CalcDirectionCoeffs({ 1.0f, 0.0f, 0.0f}); - static constexpr auto lcoeffs_nrml = CalcDirectionCoeffs({-inv_sqrt2, 0.0f, inv_sqrt2}); - static constexpr auto rcoeffs_nrml = CalcDirectionCoeffs({ inv_sqrt2, 0.0f, inv_sqrt2}); + static constexpr auto lcoeffs_pw = CalcDirectionCoeffs(std::array{-1.0f, 0.0f, 0.0f}); + static constexpr auto rcoeffs_pw = CalcDirectionCoeffs(std::array{ 1.0f, 0.0f, 0.0f}); + static constexpr auto lcoeffs_nrml = CalcDirectionCoeffs(std::array{-inv_sqrt2, 0.0f, inv_sqrt2}); + static constexpr auto rcoeffs_nrml = CalcDirectionCoeffs(std::array{ inv_sqrt2, 0.0f, inv_sqrt2}); auto &lcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? lcoeffs_nrml : lcoeffs_pw; auto &rcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? rcoeffs_nrml : rcoeffs_pw; diff --git a/alc/effects/pshifter.cpp b/alc/effects/pshifter.cpp index 3cec1df9..2460cf78 100644 --- a/alc/effects/pshifter.cpp +++ b/alc/effects/pshifter.cpp @@ -142,7 +142,7 @@ void PshifterState::update(const ContextBase*, const EffectSlot *slot, mPitchShiftI = clampu(fastf2u(pitch*MixerFracOne), MixerFracHalf, MixerFracOne*2); mPitchShift = static_cast(mPitchShiftI) * float{1.0f/MixerFracOne}; - static constexpr auto coeffs = CalcDirectionCoeffs({0.0f, 0.0f, -1.0f}); + static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f}); mOutTarget = target.Main->Buffer; ComputePanGains(target.Main, coeffs.data(), slot->Gain, mTargetGains); diff --git a/core/mixer.h b/core/mixer.h index aa7597bb..a9c1f931 100644 --- a/core/mixer.h +++ b/core/mixer.h @@ -58,7 +58,7 @@ std::array CalcAmbiCoeffs(const float y, const float z, c * vector must be normalized (unit length), and the spread is the angular width * of the sound (0...tau). */ -inline std::array CalcDirectionCoeffs(const float (&dir)[3], +inline std::array CalcDirectionCoeffs(const al::span dir, const float spread) { /* Convert from OpenAL coords to Ambisonics. */ @@ -71,7 +71,7 @@ inline std::array CalcDirectionCoeffs(const float (&dir)[ * Calculates ambisonic coefficients based on an OpenAL direction vector. The * vector must be normalized (unit length). */ -constexpr std::array CalcDirectionCoeffs(const float (&dir)[3]) +constexpr std::array CalcDirectionCoeffs(const al::span dir) { /* Convert from OpenAL coords to Ambisonics. */ return CalcAmbiCoeffs(-dir[0], dir[1], -dir[2]); -- cgit v1.2.3 From b20e1ef178605491326fa94c7b5005c9fab3ba37 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 18 Sep 2023 05:45:33 -0700 Subject: Replace some more unnecessary angles with vectors --- alc/effects/convolution.cpp | 124 +++++++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 47 deletions(-) (limited to 'alc') diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index bc25963e..f46422d4 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -118,15 +118,18 @@ constexpr auto GetAmbi2DLayout(AmbiLayout layouttype) noexcept } -struct ChanMap { +constexpr float sin30{0.5f}; +constexpr float cos30{0.866025403785f}; +constexpr float sin45{al::numbers::sqrt2_v*0.5f}; +constexpr float cos45{al::numbers::sqrt2_v*0.5f}; +constexpr float sin110{ 0.939692620786f}; +constexpr float cos110{-0.342020143326f}; + +struct ChanPosMap { Channel channel; - float angle; - float elevation; + std::array pos; }; -constexpr float Deg2Rad(float x) noexcept -{ return static_cast(al::numbers::pi / 180.0 * x); } - using complex_f = std::complex; @@ -378,43 +381,43 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot * to have its own output target since the main mixing buffer won't have an * LFE channel (due to being B-Format). */ - static constexpr ChanMap MonoMap[1]{ - { FrontCenter, 0.0f, 0.0f } + static constexpr ChanPosMap MonoMap[1]{ + { FrontCenter, std::array{0.0f, 0.0f, -1.0f} } }, StereoMap[2]{ - { FrontLeft, Deg2Rad(-45.0f), Deg2Rad(0.0f) }, - { FrontRight, Deg2Rad( 45.0f), Deg2Rad(0.0f) } + { FrontLeft, std::array{-sin45, 0.0f, -cos45} }, + { FrontRight, std::array{ sin45, 0.0f, -cos45} }, }, RearMap[2]{ - { BackLeft, Deg2Rad(-135.0f), Deg2Rad(0.0f) }, - { BackRight, Deg2Rad( 135.0f), Deg2Rad(0.0f) } + { BackLeft, std::array{-sin45, 0.0f, cos45} }, + { BackRight, std::array{ sin45, 0.0f, cos45} }, }, QuadMap[4]{ - { FrontLeft, Deg2Rad( -45.0f), Deg2Rad(0.0f) }, - { FrontRight, Deg2Rad( 45.0f), Deg2Rad(0.0f) }, - { BackLeft, Deg2Rad(-135.0f), Deg2Rad(0.0f) }, - { BackRight, Deg2Rad( 135.0f), Deg2Rad(0.0f) } + { FrontLeft, std::array{-sin45, 0.0f, -cos45} }, + { FrontRight, std::array{ sin45, 0.0f, -cos45} }, + { BackLeft, std::array{-sin45, 0.0f, cos45} }, + { BackRight, std::array{ sin45, 0.0f, cos45} }, }, X51Map[6]{ - { FrontLeft, Deg2Rad( -30.0f), Deg2Rad(0.0f) }, - { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) }, - { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) }, - { LFE, 0.0f, 0.0f }, - { SideLeft, Deg2Rad(-110.0f), Deg2Rad(0.0f) }, - { SideRight, Deg2Rad( 110.0f), Deg2Rad(0.0f) } + { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, + { FrontRight, std::array{ sin30, 0.0f, -cos30} }, + { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, + { LFE, {} }, + { SideLeft, std::array{-sin110, 0.0f, -cos110} }, + { SideRight, std::array{ sin110, 0.0f, -cos110} }, }, X61Map[7]{ - { FrontLeft, Deg2Rad(-30.0f), Deg2Rad(0.0f) }, - { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) }, - { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) }, - { LFE, 0.0f, 0.0f }, - { BackCenter, Deg2Rad(180.0f), Deg2Rad(0.0f) }, - { SideLeft, Deg2Rad(-90.0f), Deg2Rad(0.0f) }, - { SideRight, Deg2Rad( 90.0f), Deg2Rad(0.0f) } + { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, + { FrontRight, std::array{ sin30, 0.0f, -cos30} }, + { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, + { LFE, {} }, + { BackCenter, std::array{ 0.0f, 0.0f, 1.0f} }, + { SideLeft, std::array{-1.0f, 0.0f, 0.0f} }, + { SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, }, X71Map[8]{ - { FrontLeft, Deg2Rad( -30.0f), Deg2Rad(0.0f) }, - { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) }, - { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) }, - { LFE, 0.0f, 0.0f }, - { BackLeft, Deg2Rad(-150.0f), Deg2Rad(0.0f) }, - { BackRight, Deg2Rad( 150.0f), Deg2Rad(0.0f) }, - { SideLeft, Deg2Rad( -90.0f), Deg2Rad(0.0f) }, - { SideRight, Deg2Rad( 90.0f), Deg2Rad(0.0f) } + { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, + { FrontRight, std::array{ sin30, 0.0f, -cos30} }, + { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, + { LFE, {} }, + { BackLeft, std::array{-sin30, 0.0f, cos30} }, + { BackRight, std::array{ sin30, 0.0f, cos30} }, + { SideLeft, std::array{ -1.0f, 0.0f, 0.0f} }, + { SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, }; if(mNumConvolveSegs < 1) UNLIKELY @@ -470,7 +473,7 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot else { DeviceBase *device{context->mDevice}; - al::span chanmap{}; + al::span chanmap{}; switch(mChannels) { case FmtMono: chanmap = MonoMap; break; @@ -492,27 +495,54 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot mOutTarget = target.Main->Buffer; if(device->mRenderMode == RenderMode::Pairwise) { - auto ScaleAzimuthFront = [](float azimuth, float scale) -> float + /* Scales the azimuth of the given vector by 3 if it's in front. + * Effectively scales +/-45 degrees to +/-90 degrees, leaving > +90 + * and < -90 alone. + */ + auto ScaleAzimuthFront = [](std::array pos) -> std::array { - constexpr float half_pi{al::numbers::pi_v*0.5f}; - const float abs_azi{std::fabs(azimuth)}; - if(!(abs_azi >= half_pi)) - return std::copysign(minf(abs_azi*scale, half_pi), azimuth); - return azimuth; + if(pos[2] < 0.0f) + { + /* Normalize the length of the x,z components for a 2D + * vector of the azimuth angle. Negate Z since {0,0,-1} is + * angle 0. + */ + const float len2d{std::sqrt(pos[0]*pos[0] + pos[2]*pos[2])}; + float x{pos[0] / len2d}; + float z{-pos[2] / len2d}; + + /* Z > cos(pi/4) = -45 < azimuth < 45 degrees. */ + if(z > cos45) + { + /* Double the angle represented by x,z. */ + const float resx{2.0f*x * z}; + const float resz{z*z - x*x}; + + /* Scale the vector back to fit in 3D. */ + pos[0] = resx * len2d; + pos[2] = -resz * len2d; + } + else + { + /* If azimuth >= 45 degrees, clamp to 90 degrees. */ + pos[0] = std::copysign(len2d, pos[0]); + pos[2] = 0.0f; + } + } + return pos; }; for(size_t i{0};i < chanmap.size();++i) { if(chanmap[i].channel == LFE) continue; - const auto coeffs = CalcAngleCoeffs(ScaleAzimuthFront(chanmap[i].angle, 2.0f), - chanmap[i].elevation, 0.0f); + const auto coeffs = CalcDirectionCoeffs(ScaleAzimuthFront(chanmap[i].pos), 0.0f); ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[i].Target); } } else for(size_t i{0};i < chanmap.size();++i) { if(chanmap[i].channel == LFE) continue; - const auto coeffs = CalcAngleCoeffs(chanmap[i].angle, chanmap[i].elevation, 0.0f); + const auto coeffs = CalcDirectionCoeffs(chanmap[i].pos, 0.0f); ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[i].Target); } } -- cgit v1.2.3 From 0eeb3c29f412dd38666dc57e9bc117e3e1073d78 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 20 Sep 2023 19:48:04 -0700 Subject: Preliminary implementation of WASAPI spatial audio playback --- alc/backends/wasapi.cpp | 699 +++++++++++++++++++++++++++++++++++++----------- alsoftrc.sample | 6 + core/device.h | 5 + 3 files changed, 549 insertions(+), 161 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 0dda4d66..4129ac9d 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -31,7 +31,9 @@ #include #include +#include #include +#include #include #include #include @@ -106,6 +108,9 @@ using ReferenceTime = std::chrono::duration(n)}; } +constexpr AudioObjectType operator|(AudioObjectType lhs, AudioObjectType rhs) noexcept +{ return static_cast(lhs | al::to_underlying(rhs)); } + #define MONO SPEAKER_FRONT_CENTER #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT) @@ -134,10 +139,40 @@ constexpr DWORD X61Mask{MaskFromTopBits(X6DOT1)}; constexpr DWORD X71Mask{MaskFromTopBits(X7DOT1)}; constexpr DWORD X714Mask{MaskFromTopBits(X7DOT1DOT4)}; +constexpr AudioObjectType ChannelMask_Mono{AudioObjectType_FrontCenter}; +constexpr AudioObjectType ChannelMask_Stereo{AudioObjectType_FrontLeft + | AudioObjectType_FrontRight}; +constexpr AudioObjectType ChannelMask_Quad{AudioObjectType_FrontLeft | AudioObjectType_FrontRight + | AudioObjectType_BackLeft | AudioObjectType_BackRight}; +constexpr AudioObjectType ChannelMask_X51{AudioObjectType_FrontLeft | AudioObjectType_FrontRight + | AudioObjectType_FrontCenter | AudioObjectType_LowFrequency | AudioObjectType_SideLeft + | AudioObjectType_SideRight}; +constexpr AudioObjectType ChannelMask_X51Rear{AudioObjectType_FrontLeft + | AudioObjectType_FrontRight | AudioObjectType_FrontCenter | AudioObjectType_LowFrequency + | AudioObjectType_BackLeft | AudioObjectType_BackRight}; +constexpr AudioObjectType ChannelMask_X61{AudioObjectType_FrontLeft | AudioObjectType_FrontRight + | AudioObjectType_FrontCenter | AudioObjectType_LowFrequency | AudioObjectType_SideLeft + | AudioObjectType_SideRight | AudioObjectType_BackCenter}; +constexpr AudioObjectType ChannelMask_X71{AudioObjectType_FrontLeft | AudioObjectType_FrontRight + | AudioObjectType_FrontCenter | AudioObjectType_LowFrequency | AudioObjectType_SideLeft + | AudioObjectType_SideRight | AudioObjectType_BackLeft | AudioObjectType_BackRight}; +constexpr AudioObjectType ChannelMask_X714{AudioObjectType_FrontLeft | AudioObjectType_FrontRight + | AudioObjectType_FrontCenter | AudioObjectType_LowFrequency | AudioObjectType_SideLeft + | AudioObjectType_SideRight | AudioObjectType_BackLeft | AudioObjectType_BackRight + | AudioObjectType_TopFrontLeft | AudioObjectType_TopFrontRight | AudioObjectType_TopBackLeft + | AudioObjectType_TopBackRight}; + constexpr char DevNameHead[] = "OpenAL Soft on "; constexpr size_t DevNameHeadLen{std::size(DevNameHead) - 1}; +template +struct overloaded : Ts... { using Ts::operator()...; }; + +template +overloaded(Ts...) -> overloaded; + + /* Scales the given reftime value, rounding the result. */ inline uint RefTime2Samples(const ReferenceTime &val, uint srate) { @@ -1011,6 +1046,7 @@ struct WasapiPlayback final : public BackendBase, WasapiProxy { ~WasapiPlayback() override; int mixerProc(); + int mixerSpatialProc(); void open(std::string_view name) override; HRESULT openProxy(std::string_view name) override; @@ -1025,10 +1061,22 @@ struct WasapiPlayback final : public BackendBase, WasapiProxy { ClockLatency getClockLatency() override; + void prepareFormat(WAVEFORMATEXTENSIBLE &OutputType); + void finalizeFormat(WAVEFORMATEXTENSIBLE &OutputType); + HRESULT mOpenStatus{E_FAIL}; DeviceHandle mMMDev{nullptr}; - ComPtr mClient{nullptr}; - ComPtr mRender{nullptr}; + + struct PlainDevice { + ComPtr mClient{nullptr}; + ComPtr mRender{nullptr}; + }; + struct SpatialDevice { + ComPtr mClient{nullptr}; + ComPtr mRender{nullptr}; + AudioObjectType mStaticMask{}; + }; + std::variant mAudio; HANDLE mNotifyEvent{nullptr}; UINT32 mOrigBufferSize{}, mOrigUpdateSize{}; @@ -1069,6 +1117,8 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() return 1; } + auto &audio = std::get(mAudio); + SetRTPriority(); althrd_setname(MIXER_THREAD_NAME); @@ -1078,7 +1128,7 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() while(!mKillNow.load(std::memory_order_relaxed)) { UINT32 written; - hr = mClient->GetCurrentPadding(&written); + hr = audio.mClient->GetCurrentPadding(&written); if(FAILED(hr)) { ERR("Failed to get padding: 0x%08lx\n", hr); @@ -1097,7 +1147,7 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() } BYTE *buffer; - hr = mRender->GetBuffer(len, &buffer); + hr = audio.mRender->GetBuffer(len, &buffer); if(SUCCEEDED(hr)) { if(mResampler) @@ -1133,7 +1183,7 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() mDevice->renderSamples(buffer, len, mFormat.Format.nChannels); mPadding.store(written + len, std::memory_order_relaxed); } - hr = mRender->ReleaseBuffer(len, 0); + hr = audio.mRender->ReleaseBuffer(len, 0); } if(FAILED(hr)) { @@ -1148,6 +1198,90 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() return 0; } +FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() +{ + HRESULT hr{CoInitializeEx(nullptr, COINIT_MULTITHREADED)}; + if(FAILED(hr)) + { + ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr); + mDevice->handleDisconnect("COM init failed: 0x%08lx", hr); + return 1; + } + + auto &audio = std::get(mAudio); + + SetRTPriority(); + althrd_setname(MIXER_THREAD_NAME); + + std::vector> channels; + std::vector buffers; + + /* TODO: Set mPadding appropriately. There doesn't seem to be a way to + * update it dynamically based on the stream, so it may need to be set to a + * fixed size. + */ + + while(!mKillNow.load(std::memory_order_relaxed)) + { + if(DWORD res{WaitForSingleObjectEx(mNotifyEvent, 1000, FALSE)}; res != WAIT_OBJECT_0) + { + ERR("WaitForSingleObjectEx error: 0x%lx\n", res); + + hr = audio.mRender->Reset(); + if(FAILED(hr)) + { + ERR("ISpatialAudioObjectRenderStream::Reset failed: 0x%08lx\n", hr); + mDevice->handleDisconnect("Device lost: 0x%08lx", hr); + break; + } + } + + UINT32 dynamicCount{}, framesToDo{}; + hr = audio.mRender->BeginUpdatingAudioObjects(&dynamicCount, &framesToDo); + if(SUCCEEDED(hr)) + { + if(channels.empty()) UNLIKELY + { + DWORD flags{audio.mStaticMask}; + channels.reserve(static_cast(al::popcount(flags))); + while(flags) + { + DWORD id{1u << al::countr_zero(flags)}; + flags &= ~id; + + channels.emplace_back(); + audio.mRender->ActivateSpatialAudioObject(static_cast(id), + al::out_ptr(channels.back())); + } + buffers.resize(channels.size()); + } + + /* We have to call to get each channel's buffer individually every + * update, unfortunately. + */ + std::transform(channels.cbegin(), channels.cend(), buffers.begin(), + [](const ComPtr &obj) -> float* + { + BYTE *buffer{}; + UINT32 size{}; + obj->GetBuffer(&buffer, &size); + return reinterpret_cast(buffer); + }); + + mDevice->renderSamples(buffers, framesToDo); + + hr = audio.mRender->EndUpdatingAudioObjects(); + } + + if(FAILED(hr)) + ERR("Failed to update playback objects: 0x%08lx\n", hr); + } + mPadding.store(0u, std::memory_order_release); + + CoUninitialize(); + return 0; +} + void WasapiPlayback::open(std::string_view name) { @@ -1209,7 +1343,6 @@ HRESULT WasapiPlayback::openProxy(std::string_view name) WARN("Failed to open device \"%s\"\n", devname.empty() ? "(default)" : devname.c_str()); return hr; } - mClient = nullptr; if(!devname.empty()) mDevice->DeviceName = DevNameHead + std::move(devname); else @@ -1220,50 +1353,13 @@ HRESULT WasapiPlayback::openProxy(std::string_view name) void WasapiPlayback::closeProxy() { - mClient = nullptr; + mAudio.emplace(); mMMDev = nullptr; } -bool WasapiPlayback::reset() -{ - HRESULT hr{pushMessage(MsgType::ResetDevice).get()}; - if(FAILED(hr)) - throw al::backend_exception{al::backend_error::DeviceError, "0x%08lx", hr}; - return true; -} - -HRESULT WasapiPlayback::resetProxy() +void WasapiPlayback::prepareFormat(WAVEFORMATEXTENSIBLE &OutputType) { - mClient = nullptr; - HRESULT hr{sDeviceHelper->activateAudioClient(mMMDev, __uuidof(IAudioClient), - al::out_ptr(mClient))}; - if(FAILED(hr)) - { - ERR("Failed to reactivate audio client: 0x%08lx\n", hr); - return hr; - } - - WAVEFORMATEX *wfx; - hr = mClient->GetMixFormat(&wfx); - if(FAILED(hr)) - { - ERR("Failed to get mix format: 0x%08lx\n", hr); - return hr; - } - TraceFormat("Device mix format", wfx); - - WAVEFORMATEXTENSIBLE OutputType; - if(!MakeExtensible(&OutputType, wfx)) - { - CoTaskMemFree(wfx); - return E_FAIL; - } - CoTaskMemFree(wfx); - wfx = nullptr; - - const ReferenceTime per_time{ReferenceTime{seconds{mDevice->UpdateSize}} / mDevice->Frequency}; - const ReferenceTime buf_time{ReferenceTime{seconds{mDevice->BufferSize}} / mDevice->Frequency}; bool isRear51{false}; if(!mDevice->Flags.test(FrequencyRequest)) @@ -1379,132 +1475,372 @@ HRESULT WasapiPlayback::resetProxy() OutputType.Format.wBitsPerSample / 8); OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * OutputType.Format.nBlockAlign; +} - TraceFormat("Requesting playback format", &OutputType.Format); - hr = mClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx); - if(FAILED(hr)) +void WasapiPlayback::finalizeFormat(WAVEFORMATEXTENSIBLE &OutputType) +{ + if(!GetConfigValueBool(mDevice->DeviceName.c_str(), "wasapi", "allow-resampler", true)) + mDevice->Frequency = OutputType.Format.nSamplesPerSec; + else + mDevice->Frequency = minu(mDevice->Frequency, OutputType.Format.nSamplesPerSec); + + const uint32_t chancount{OutputType.Format.nChannels}; + const DWORD chanmask{OutputType.dwChannelMask}; + /* Don't update the channel format if the requested format fits what's + * supported. + */ + bool chansok{false}; + if(mDevice->Flags.test(ChannelsRequest)) + { + /* When requesting a channel configuration, make sure it fits the + * mask's lsb (to ensure no gaps in the output channels). If there's no + * mask, assume the request fits with enough channels. + */ + switch(mDevice->FmtChans) + { + case DevFmtMono: + chansok = (chancount >= 1 && ((chanmask&MonoMask) == MONO || !chanmask)); + break; + case DevFmtStereo: + chansok = (chancount >= 2 && ((chanmask&StereoMask) == STEREO || !chanmask)); + break; + case DevFmtQuad: + chansok = (chancount >= 4 && ((chanmask&QuadMask) == QUAD || !chanmask)); + break; + case DevFmtX51: + chansok = (chancount >= 6 && ((chanmask&X51Mask) == X5DOT1 + || (chanmask&X51RearMask) == X5DOT1REAR || !chanmask)); + break; + case DevFmtX61: + chansok = (chancount >= 7 && ((chanmask&X61Mask) == X6DOT1 || !chanmask)); + break; + case DevFmtX71: + case DevFmtX3D71: + chansok = (chancount >= 8 && ((chanmask&X71Mask) == X7DOT1 || !chanmask)); + break; + case DevFmtX714: + chansok = (chancount >= 12 && ((chanmask&X714Mask) == X7DOT1DOT4 || !chanmask)); + case DevFmtAmbi3D: + break; + } + } + if(!chansok) { - WARN("Failed to check format support: 0x%08lx\n", hr); - hr = mClient->GetMixFormat(&wfx); + if(chancount >= 12 && (chanmask&X714Mask) == X7DOT1DOT4) + mDevice->FmtChans = DevFmtX714; + else if(chancount >= 8 && (chanmask&X71Mask) == X7DOT1) + mDevice->FmtChans = DevFmtX71; + else if(chancount >= 7 && (chanmask&X61Mask) == X6DOT1) + mDevice->FmtChans = DevFmtX61; + else if(chancount >= 6 && ((chanmask&X51Mask) == X5DOT1 + || (chanmask&X51RearMask) == X5DOT1REAR)) + mDevice->FmtChans = DevFmtX51; + else if(chancount >= 4 && (chanmask&QuadMask) == QUAD) + mDevice->FmtChans = DevFmtQuad; + else if(chancount >= 2 && ((chanmask&StereoMask) == STEREO || !chanmask)) + mDevice->FmtChans = DevFmtStereo; + else if(chancount >= 1 && ((chanmask&MonoMask) == MONO || !chanmask)) + mDevice->FmtChans = DevFmtMono; + else + { + ERR("Unhandled extensible channels: %d -- 0x%08lx\n", OutputType.Format.nChannels, + OutputType.dwChannelMask); + mDevice->FmtChans = DevFmtStereo; + OutputType.Format.nChannels = 2; + OutputType.dwChannelMask = STEREO; + } } - if(FAILED(hr)) + + if(IsEqualGUID(OutputType.SubFormat, KSDATAFORMAT_SUBTYPE_PCM)) { - ERR("Failed to find a supported format: 0x%08lx\n", hr); - return hr; + if(OutputType.Format.wBitsPerSample == 8) + mDevice->FmtType = DevFmtUByte; + else if(OutputType.Format.wBitsPerSample == 16) + mDevice->FmtType = DevFmtShort; + else if(OutputType.Format.wBitsPerSample == 32) + mDevice->FmtType = DevFmtInt; + else + { + mDevice->FmtType = DevFmtShort; + OutputType.Format.wBitsPerSample = 16; + } + } + else if(IsEqualGUID(OutputType.SubFormat, KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) + { + mDevice->FmtType = DevFmtFloat; + OutputType.Format.wBitsPerSample = 32; } + else + { + ERR("Unhandled format sub-type: %s\n", GuidPrinter{OutputType.SubFormat}.c_str()); + mDevice->FmtType = DevFmtShort; + if(OutputType.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) + OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; + OutputType.Format.wBitsPerSample = 16; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + } + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; +} - if(wfx != nullptr) + +bool WasapiPlayback::reset() +{ + HRESULT hr{pushMessage(MsgType::ResetDevice).get()}; + if(FAILED(hr)) + throw al::backend_exception{al::backend_error::DeviceError, "0x%08lx", hr}; + return true; +} + +HRESULT WasapiPlayback::resetProxy() +{ + if(GetConfigValueBool(mDevice->DeviceName.c_str(), "wasapi", "spatial-api", false)) { - TraceFormat("Got playback format", wfx); - if(!MakeExtensible(&OutputType, wfx)) + auto &audio = mAudio.emplace(); + HRESULT hr{sDeviceHelper->activateAudioClient(mMMDev, __uuidof(ISpatialAudioClient), + al::out_ptr(audio.mClient))}; + if(FAILED(hr)) { - CoTaskMemFree(wfx); - return E_FAIL; + ERR("Failed to activate spatial audio client: 0x%08lx\n", hr); + goto no_spatial; } - CoTaskMemFree(wfx); - wfx = nullptr; - if(!GetConfigValueBool(mDevice->DeviceName.c_str(), "wasapi", "allow-resampler", true)) - mDevice->Frequency = OutputType.Format.nSamplesPerSec; - else - mDevice->Frequency = minu(mDevice->Frequency, OutputType.Format.nSamplesPerSec); + ComPtr fmtenum; + hr = audio.mClient->GetSupportedAudioObjectFormatEnumerator(al::out_ptr(fmtenum)); + if(FAILED(hr)) + { + ERR("Failed to get format enumerator: 0x%08lx\n", hr); + goto no_spatial; + } - const uint32_t chancount{OutputType.Format.nChannels}; - const DWORD chanmask{OutputType.dwChannelMask}; - /* Don't update the channel format if the requested format fits what's - * supported. - */ - bool chansok{false}; - if(mDevice->Flags.test(ChannelsRequest)) + UINT32 fmtcount{}; + hr = fmtenum->GetCount(&fmtcount); + if(FAILED(hr) || fmtcount == 0) { - /* When requesting a channel configuration, make sure it fits the - * mask's lsb (to ensure no gaps in the output channels). If - * there's no mask, assume the request fits with enough channels. - */ - switch(mDevice->FmtChans) + ERR("Failed to get format count: 0x%08lx\n", hr); + goto no_spatial; + } + + WAVEFORMATEX *preferredFormat{}; + hr = fmtenum->GetFormat(0, &preferredFormat); + if(FAILED(hr)) + { + ERR("Failed to get preferred format: 0x%08lx\n", hr); + goto no_spatial; + } + TraceFormat("Preferred mix format", preferredFormat); + + UINT32 maxFrames{}; + hr = audio.mClient->GetMaxFrameCount(preferredFormat, &maxFrames); + if(FAILED(hr)) + ERR("Failed to get max frames: 0x%08lx\n", hr); + else + TRACE("Max frames: %u\n", maxFrames); + for(UINT32 i{1};i < fmtcount;++i) + { + WAVEFORMATEX *other{}; + hr = fmtenum->GetFormat(i, &other); + if(FAILED(hr)) + ERR("Failed to format %u: 0x%08lx\n", i+1, hr); + else { - case DevFmtMono: - chansok = (chancount >= 1 && ((chanmask&MonoMask) == MONO || !chanmask)); - break; - case DevFmtStereo: - chansok = (chancount >= 2 && ((chanmask&StereoMask) == STEREO || !chanmask)); - break; - case DevFmtQuad: - chansok = (chancount >= 4 && ((chanmask&QuadMask) == QUAD || !chanmask)); - break; - case DevFmtX51: - chansok = (chancount >= 6 && ((chanmask&X51Mask) == X5DOT1 - || (chanmask&X51RearMask) == X5DOT1REAR || !chanmask)); - break; - case DevFmtX61: - chansok = (chancount >= 7 && ((chanmask&X61Mask) == X6DOT1 || !chanmask)); - break; - case DevFmtX71: - case DevFmtX3D71: - chansok = (chancount >= 8 && ((chanmask&X71Mask) == X7DOT1 || !chanmask)); - break; - case DevFmtX714: - chansok = (chancount >= 12 && ((chanmask&X714Mask) == X7DOT1DOT4 || !chanmask)); - case DevFmtAmbi3D: - break; + TraceFormat("Other mix format", other); + hr = audio.mClient->GetMaxFrameCount(other, &maxFrames); + if(FAILED(hr)) + ERR("Failed to get max frames: 0x%08lx\n", hr); + else + TRACE("Max frames: %u\n", maxFrames); } } - if(!chansok) + + WAVEFORMATEXTENSIBLE OutputType; + if(!MakeExtensible(&OutputType, preferredFormat)) + goto no_spatial; + + /* Force 32-bit float. This is currently required for planar output. */ + if(OutputType.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE + && OutputType.Format.wFormatTag != WAVE_FORMAT_IEEE_FLOAT) + { + OutputType.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + OutputType.Format.cbSize = 0; + } + if(OutputType.Format.wBitsPerSample != 32) { + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nAvgBytesPerSec * 32u + / OutputType.Format.wBitsPerSample; + OutputType.Format.nBlockAlign = static_cast(OutputType.Format.nBlockAlign * 32 + / OutputType.Format.wBitsPerSample); + OutputType.Format.wBitsPerSample = 32; + } + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + + bool isRear51{false}; + if(!mDevice->Flags.test(ChannelsRequest)) + { + const uint32_t chancount{OutputType.Format.nChannels}; + const DWORD chanmask{OutputType.dwChannelMask}; if(chancount >= 12 && (chanmask&X714Mask) == X7DOT1DOT4) mDevice->FmtChans = DevFmtX714; else if(chancount >= 8 && (chanmask&X71Mask) == X7DOT1) mDevice->FmtChans = DevFmtX71; else if(chancount >= 7 && (chanmask&X61Mask) == X6DOT1) mDevice->FmtChans = DevFmtX61; - else if(chancount >= 6 && ((chanmask&X51Mask) == X5DOT1 - || (chanmask&X51RearMask) == X5DOT1REAR)) + else if(chancount >= 6 && (chanmask&X51Mask) == X5DOT1) + mDevice->FmtChans = DevFmtX51; + else if(chancount >= 6 && (chanmask&X51RearMask) == X5DOT1REAR) + { mDevice->FmtChans = DevFmtX51; + isRear51 = true; + } else if(chancount >= 4 && (chanmask&QuadMask) == QUAD) mDevice->FmtChans = DevFmtQuad; else if(chancount >= 2 && ((chanmask&StereoMask) == STEREO || !chanmask)) mDevice->FmtChans = DevFmtStereo; - else if(chancount >= 1 && ((chanmask&MonoMask) == MONO || !chanmask)) - mDevice->FmtChans = DevFmtMono; - else - { - ERR("Unhandled extensible channels: %d -- 0x%08lx\n", OutputType.Format.nChannels, - OutputType.dwChannelMask); - mDevice->FmtChans = DevFmtStereo; - OutputType.Format.nChannels = 2; - OutputType.dwChannelMask = STEREO; - } + /* HACK: Don't autoselect mono. Wine returns this and makes the + * audio terrible. + */ + else if(!(chancount >= 1 && ((chanmask&MonoMask) == MONO || !chanmask))) + ERR("Unhandled channel config: %d -- 0x%08lx\n", chancount, chanmask); + } + else + { + const uint32_t chancount{OutputType.Format.nChannels}; + const DWORD chanmask{OutputType.dwChannelMask}; + isRear51 = (chancount == 6 && (chanmask&X51RearMask) == X5DOT1REAR); } - if(IsEqualGUID(OutputType.SubFormat, KSDATAFORMAT_SUBTYPE_PCM)) + auto getTypeMask = [isRear51](DevFmtChannels chans) noexcept { - if(OutputType.Format.wBitsPerSample == 8) - mDevice->FmtType = DevFmtUByte; - else if(OutputType.Format.wBitsPerSample == 16) - mDevice->FmtType = DevFmtShort; - else if(OutputType.Format.wBitsPerSample == 32) - mDevice->FmtType = DevFmtInt; - else + switch(chans) { - mDevice->FmtType = DevFmtShort; - OutputType.Format.wBitsPerSample = 16; + case DevFmtMono: return ChannelMask_Mono; + case DevFmtStereo: return ChannelMask_Stereo; + case DevFmtQuad: return ChannelMask_Quad; + case DevFmtX51: return isRear51 ? ChannelMask_X51Rear : ChannelMask_X51; + case DevFmtX61: return ChannelMask_X61; + case DevFmtX3D71: + case DevFmtX71: return ChannelMask_X71; + case DevFmtX714: return ChannelMask_X714; + case DevFmtAmbi3D: + break; } - } - else if(IsEqualGUID(OutputType.SubFormat, KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) + return ChannelMask_Stereo; + }; + + SpatialAudioObjectRenderStreamActivationParams streamParams{}; + streamParams.ObjectFormat = &OutputType.Format; + streamParams.StaticObjectTypeMask = getTypeMask(mDevice->FmtChans); + streamParams.Category = AudioCategory_Media; + streamParams.EventHandle = mNotifyEvent; + + PropVariant paramProp{}; + paramProp->vt = VT_BLOB; + paramProp->blob.cbSize = sizeof(streamParams); + paramProp->blob.pBlobData = reinterpret_cast(&streamParams); + + hr = audio.mClient->ActivateSpatialAudioStream(paramProp.get(), + __uuidof(ISpatialAudioObjectRenderStream), al::out_ptr(audio.mRender)); + if(FAILED(hr)) { - mDevice->FmtType = DevFmtFloat; - OutputType.Format.wBitsPerSample = 32; + ERR("Failed to activate spatial audio stream: 0x%08lx\n", hr); + goto no_spatial; } - else + + audio.mStaticMask = streamParams.StaticObjectTypeMask; + mFormat = OutputType; + + /* TODO: Support resampling. */ + mDevice->FmtType = DevFmtFloat; + mDevice->Flags.reset(DirectEar).set(Virtualization); + if(streamParams.StaticObjectTypeMask == ChannelMask_Stereo) + mDevice->FmtChans = DevFmtStereo; + mDevice->Frequency = mFormat.Format.nSamplesPerSec; + + setDefaultWFXChannelOrder(); + + /* TODO: Get the real update and buffer size. Does + * ISpatialAudioClient::GetMaxFrameCount give the buffer size, update + * size, or neither? According to MSDN, it + * + * "Gets the maximum possible frame count per processing pass." + * + * If it tries to keep a full buffer, the max possible could be a full + * buffer for the first update or underrun. Though if it always does a + * period at a time, it doesn't make sense for a pass to be less. + * + * Perhaps activating a normal IAudioClient to get the period size is + * the proper thing to do (still won't get us the buffer size though). + */ + mOrigBufferSize = mDevice->BufferSize; + mOrigUpdateSize = mDevice->UpdateSize; + + mResampler = nullptr; + mResampleBuffer = nullptr; + mBufferFilled = 0; + + return S_OK; + } + +no_spatial: + mDevice->Flags.reset(Virtualization); + + auto &audio = mAudio.emplace(); + HRESULT hr{sDeviceHelper->activateAudioClient(mMMDev, __uuidof(IAudioClient), + al::out_ptr(audio.mClient))}; + if(FAILED(hr)) + { + ERR("Failed to reactivate audio client: 0x%08lx\n", hr); + return hr; + } + + WAVEFORMATEX *wfx; + hr = audio.mClient->GetMixFormat(&wfx); + if(FAILED(hr)) + { + ERR("Failed to get mix format: 0x%08lx\n", hr); + return hr; + } + TraceFormat("Device mix format", wfx); + + WAVEFORMATEXTENSIBLE OutputType; + if(!MakeExtensible(&OutputType, wfx)) + { + CoTaskMemFree(wfx); + return E_FAIL; + } + CoTaskMemFree(wfx); + wfx = nullptr; + + const ReferenceTime per_time{ReferenceTime{seconds{mDevice->UpdateSize}} / mDevice->Frequency}; + const ReferenceTime buf_time{ReferenceTime{seconds{mDevice->BufferSize}} / mDevice->Frequency}; + + prepareFormat(OutputType); + + TraceFormat("Requesting playback format", &OutputType.Format); + hr = audio.mClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx); + if(FAILED(hr)) + { + WARN("Failed to check format support: 0x%08lx\n", hr); + hr = audio.mClient->GetMixFormat(&wfx); + } + if(FAILED(hr)) + { + ERR("Failed to find a supported format: 0x%08lx\n", hr); + return hr; + } + + if(wfx != nullptr) + { + TraceFormat("Got playback format", wfx); + if(!MakeExtensible(&OutputType, wfx)) { - ERR("Unhandled format sub-type: %s\n", GuidPrinter{OutputType.SubFormat}.c_str()); - mDevice->FmtType = DevFmtShort; - if(OutputType.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) - OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; - OutputType.Format.wBitsPerSample = 16; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + CoTaskMemFree(wfx); + return E_FAIL; } - OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; + CoTaskMemFree(wfx); + wfx = nullptr; + + finalizeFormat(OutputType); } mFormat = OutputType; @@ -1516,7 +1852,7 @@ HRESULT WasapiPlayback::resetProxy() #endif setDefaultWFXChannelOrder(); - hr = mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + hr = audio.mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, buf_time.count(), 0, &OutputType.Format, nullptr); if(FAILED(hr)) { @@ -1526,15 +1862,22 @@ HRESULT WasapiPlayback::resetProxy() UINT32 buffer_len{}; ReferenceTime min_per{}; - hr = mClient->GetDevicePeriod(&reinterpret_cast(min_per), nullptr); + hr = audio.mClient->GetDevicePeriod(&reinterpret_cast(min_per), nullptr); if(SUCCEEDED(hr)) - hr = mClient->GetBufferSize(&buffer_len); + hr = audio.mClient->GetBufferSize(&buffer_len); if(FAILED(hr)) { ERR("Failed to get audio buffer info: 0x%08lx\n", hr); return hr; } + hr = audio.mClient->SetEventHandle(mNotifyEvent); + if(FAILED(hr)) + { + ERR("Failed to set event handle: 0x%08lx\n", hr); + return hr; + } + /* Find the nearest multiple of the period size to the update size */ if(min_per < per_time) min_per *= maxi64((per_time + min_per/2) / min_per, 1); @@ -1564,13 +1907,6 @@ HRESULT WasapiPlayback::resetProxy() mDevice->UpdateSize); } - hr = mClient->SetEventHandle(mNotifyEvent); - if(FAILED(hr)) - { - ERR("Failed to set event handle: 0x%08lx\n", hr); - return hr; - } - return hr; } @@ -1587,31 +1923,61 @@ HRESULT WasapiPlayback::startProxy() { ResetEvent(mNotifyEvent); - HRESULT hr{mClient->Start()}; - if(FAILED(hr)) + auto mstate_fallback = [](std::monostate) -> HRESULT + { return E_FAIL; }; + auto start_plain = [&](PlainDevice &audio) -> HRESULT { - ERR("Failed to start audio client: 0x%08lx\n", hr); - return hr; - } + HRESULT hr{audio.mClient->Start()}; + if(FAILED(hr)) + { + ERR("Failed to start audio client: 0x%08lx\n", hr); + return hr; + } - hr = mClient->GetService(__uuidof(IAudioRenderClient), al::out_ptr(mRender)); - if(SUCCEEDED(hr)) + hr = audio.mClient->GetService(__uuidof(IAudioRenderClient), al::out_ptr(audio.mRender)); + if(SUCCEEDED(hr)) + { + try { + mKillNow.store(false, std::memory_order_release); + mThread = std::thread{std::mem_fn(&WasapiPlayback::mixerProc), this}; + } + catch(...) { + audio.mRender = nullptr; + ERR("Failed to start thread\n"); + hr = E_FAIL; + } + } + if(FAILED(hr)) + audio.mClient->Stop(); + return hr; + }; + auto start_spatial = [&](SpatialDevice &audio) -> HRESULT { + HRESULT hr{audio.mRender->Start()}; + if(FAILED(hr)) + { + ERR("Failed to start spatial audio stream: 0x%08lx\n", hr); + return hr; + } + try { mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&WasapiPlayback::mixerProc), this}; + mThread = std::thread{std::mem_fn(&WasapiPlayback::mixerSpatialProc), this}; } catch(...) { - mRender = nullptr; ERR("Failed to start thread\n"); hr = E_FAIL; } - } - if(FAILED(hr)) - mClient->Stop(); + if(FAILED(hr)) + { + audio.mRender->Stop(); + audio.mRender->Reset(); + } + return hr; + }; - return hr; + return std::visit(overloaded{mstate_fallback, start_plain, start_spatial}, mAudio); } @@ -1620,14 +1986,25 @@ void WasapiPlayback::stop() void WasapiPlayback::stopProxy() { - if(!mRender || !mThread.joinable()) + if(!mThread.joinable()) return; mKillNow.store(true, std::memory_order_release); mThread.join(); - mRender = nullptr; - mClient->Stop(); + auto mstate_fallback = [](std::monostate) -> void + { }; + auto stop_plain = [](PlainDevice &audio) -> void + { + audio.mRender = nullptr; + audio.mClient->Stop(); + }; + auto stop_spatial = [](SpatialDevice &audio) -> void + { + audio.mRender->Stop(); + audio.mRender->Reset(); + }; + std::visit(overloaded{mstate_fallback, stop_plain, stop_spatial}, mAudio); } diff --git a/alsoftrc.sample b/alsoftrc.sample index 8ba14389..42802184 100644 --- a/alsoftrc.sample +++ b/alsoftrc.sample @@ -579,6 +579,12 @@ ## [wasapi] +## spatial-api: +# Specifies whether to use a Spatial Audio stream for playback. This may +# provide expanded capabilities for surround sound and with-height speaker +# configurations. Very experimental. +#spatial-api = false + ## allow-resampler: # Specifies whether to allow an extra resampler pass on the output. Enabling # this will allow the playback device to be set to a different sample rate diff --git a/core/device.h b/core/device.h index 33cdfe89..b088e130 100644 --- a/core/device.h +++ b/core/device.h @@ -165,6 +165,11 @@ enum { // ear buds, etc). DirectEar, + /* Specifies if output is using speaker virtualization (e.g. Windows + * Spatial Audio). + */ + Virtualization, + DeviceFlagsCount }; -- cgit v1.2.3 From 3d5bd75559ff85ea2a019968361212482afd904b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 20 Sep 2023 20:03:39 -0700 Subject: Fix MSVC compilation MinGW's headers don't seem to define operator| for AudioObjectType. --- alc/backends/wasapi.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 4129ac9d..de974774 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -108,8 +108,10 @@ using ReferenceTime = std::chrono::duration(n)}; } +#ifndef _MSC_VER constexpr AudioObjectType operator|(AudioObjectType lhs, AudioObjectType rhs) noexcept { return static_cast(lhs | al::to_underlying(rhs)); } +#endif #define MONO SPEAKER_FRONT_CENTER -- cgit v1.2.3 From dda61d7b0fe1de983c7af10efd321fa01c4831d8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 20 Sep 2023 20:14:33 -0700 Subject: Don't assume an enum's underlying type --- alc/backends/wasapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index de974774..25845527 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -1244,7 +1244,7 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() { if(channels.empty()) UNLIKELY { - DWORD flags{audio.mStaticMask}; + auto flags = al::to_underlying(audio.mStaticMask); channels.reserve(static_cast(al::popcount(flags))); while(flags) { -- cgit v1.2.3 From de9d6d722bd14ed452c02dbaa41a37bdca5df9ca Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 20 Sep 2023 20:37:04 -0700 Subject: Again try to fix handling an enum type --- alc/backends/wasapi.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 25845527..1fd37e37 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -1244,7 +1244,8 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() { if(channels.empty()) UNLIKELY { - auto flags = al::to_underlying(audio.mStaticMask); + using UT = std::make_unsigned_t; + auto flags = static_cast(al::to_underlying(audio.mStaticMask)); channels.reserve(static_cast(al::popcount(flags))); while(flags) { -- cgit v1.2.3 From 36de3493c1c2fcab966d72c73520e625da1f1e31 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 21 Sep 2023 07:09:05 -0700 Subject: Don't assume the size of AudioObjectType --- alc/backends/wasapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 1fd37e37..9c2553d1 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -1249,7 +1249,7 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() channels.reserve(static_cast(al::popcount(flags))); while(flags) { - DWORD id{1u << al::countr_zero(flags)}; + auto id = UT{1} << al::countr_zero(flags); flags &= ~id; channels.emplace_back(); -- cgit v1.2.3 From 1b8c63910fc36a292ae591f5bedc8654c0173be9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 21 Sep 2023 13:04:46 -0700 Subject: Try to get the device period for spatial audio streams --- alc/backends/wasapi.cpp | 82 +++++++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 30 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 9c2553d1..d06d7401 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -176,10 +176,11 @@ overloaded(Ts...) -> overloaded; /* Scales the given reftime value, rounding the result. */ -inline uint RefTime2Samples(const ReferenceTime &val, uint srate) +template +constexpr uint RefTime2Samples(const ReferenceTime &val, T srate) noexcept { const auto retval = (val*srate + ReferenceTime{seconds{1}}/2) / seconds{1}; - return static_cast(mini64(retval, std::numeric_limits::max())); + return static_cast(std::min(retval, std::numeric_limits::max())); } @@ -1637,21 +1638,22 @@ HRESULT WasapiPlayback::resetProxy() if(FAILED(hr)) ERR("Failed to get max frames: 0x%08lx\n", hr); else - TRACE("Max frames: %u\n", maxFrames); + TRACE("Max sample frames: %u\n", maxFrames); for(UINT32 i{1};i < fmtcount;++i) { - WAVEFORMATEX *other{}; - hr = fmtenum->GetFormat(i, &other); + WAVEFORMATEX *otherFormat{}; + hr = fmtenum->GetFormat(i, &otherFormat); if(FAILED(hr)) ERR("Failed to format %u: 0x%08lx\n", i+1, hr); else { - TraceFormat("Other mix format", other); - hr = audio.mClient->GetMaxFrameCount(other, &maxFrames); + TraceFormat("Other mix format", otherFormat); + UINT32 otherMaxFrames{}; + hr = audio.mClient->GetMaxFrameCount(otherFormat, &otherMaxFrames); if(FAILED(hr)) ERR("Failed to get max frames: 0x%08lx\n", hr); else - TRACE("Max frames: %u\n", maxFrames); + TRACE("Max sample frames: %u\n", otherMaxFrames); } } @@ -1716,16 +1718,16 @@ HRESULT WasapiPlayback::resetProxy() { switch(chans) { - case DevFmtMono: return ChannelMask_Mono; - case DevFmtStereo: return ChannelMask_Stereo; - case DevFmtQuad: return ChannelMask_Quad; - case DevFmtX51: return isRear51 ? ChannelMask_X51Rear : ChannelMask_X51; - case DevFmtX61: return ChannelMask_X61; - case DevFmtX3D71: - case DevFmtX71: return ChannelMask_X71; - case DevFmtX714: return ChannelMask_X714; - case DevFmtAmbi3D: - break; + case DevFmtMono: return ChannelMask_Mono; + case DevFmtStereo: return ChannelMask_Stereo; + case DevFmtQuad: return ChannelMask_Quad; + case DevFmtX51: return isRear51 ? ChannelMask_X51Rear : ChannelMask_X51; + case DevFmtX61: return ChannelMask_X61; + case DevFmtX3D71: + case DevFmtX71: return ChannelMask_X71; + case DevFmtX714: return ChannelMask_X714; + case DevFmtAmbi3D: + break; } return ChannelMask_Stereo; }; @@ -1761,21 +1763,41 @@ HRESULT WasapiPlayback::resetProxy() setDefaultWFXChannelOrder(); - /* TODO: Get the real update and buffer size. Does - * ISpatialAudioClient::GetMaxFrameCount give the buffer size, update - * size, or neither? According to MSDN, it - * - * "Gets the maximum possible frame count per processing pass." + /* FIXME: Get the real update and buffer size. Presumably the actual + * device is configured once ActivateSpatialAudioStream succeeds, and + * an IAudioClient from the same IMMDevice accesses the same device + * configuration. This isn't obviously correct, but for now assume + * IAudioClient::GetDevicePeriod returns the current device period time + * that ISpatialAudioObjectRenderStream will try to wake up at. * - * If it tries to keep a full buffer, the max possible could be a full - * buffer for the first update or underrun. Though if it always does a - * period at a time, it doesn't make sense for a pass to be less. - * - * Perhaps activating a normal IAudioClient to get the period size is - * the proper thing to do (still won't get us the buffer size though). + * Unfortunately this won't get the buffer size of the + * ISpatialAudioObjectRenderStream, so we only assume there's two + * periods. */ - mOrigBufferSize = mDevice->BufferSize; mOrigUpdateSize = mDevice->UpdateSize; + mOrigBufferSize = mOrigUpdateSize*2; + ReferenceTime per_time{ReferenceTime{seconds{mDevice->UpdateSize}} / mDevice->Frequency}; + + ComPtr tmpClient; + hr = sDeviceHelper->activateAudioClient(mMMDev, __uuidof(IAudioClient), + al::out_ptr(tmpClient)); + if(FAILED(hr)) + ERR("Failed to activate audio client: 0x%08lx\n", hr); + else + { + hr = tmpClient->GetDevicePeriod(&reinterpret_cast(per_time), nullptr); + if(FAILED(hr)) + ERR("Failed to get device period: 0x%08lx\n", hr); + else + { + mOrigUpdateSize = RefTime2Samples(per_time, mFormat.Format.nSamplesPerSec); + mOrigBufferSize = mOrigUpdateSize*2; + } + } + tmpClient = nullptr; + + mDevice->UpdateSize = RefTime2Samples(per_time, mDevice->Frequency); + mDevice->BufferSize = mDevice->UpdateSize*2; mResampler = nullptr; mResampleBuffer = nullptr; -- cgit v1.2.3 From 6f33ba65d6470a99dac860dcd8472d47370be77f Mon Sep 17 00:00:00 2001 From: Deal Date: Sat, 23 Sep 2023 00:33:09 +0800 Subject: UWP: migrate C++/CX to C++/WinRT (#916) --- CMakeLists.txt | 28 +++++------ alc/alconfig.cpp | 10 +++- alc/backends/wasapi.cpp | 123 ++++++++++++++++++++++-------------------------- 3 files changed, 78 insertions(+), 83 deletions(-) (limited to 'alc') diff --git a/CMakeLists.txt b/CMakeLists.txt index b75514b2..7a01eb9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1062,19 +1062,8 @@ if(WIN32) set(HAVE_WASAPI 1) set(BACKENDS "${BACKENDS} WASAPI,") set(ALC_OBJS ${ALC_OBJS} alc/backends/wasapi.cpp alc/backends/wasapi.h) - if(ALSOFT_UWP) - set_source_files_properties(alc/backends/wasapi.cpp alc/alconfig.cpp PROPERTIES COMPILE_FLAGS /ZW) - endif() endif() endif() - - # Setup properly link flags for UWP - if(ALSOFT_UWP AND HAVE_WASAPI) - # Add compile and link flags required C++/CX - set(C_FLAGS "/Zc:twoPhase-" ${C_FLAGS}) - set(LINKER_FLAGS_DEBUG "/nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib ${LINKER_FLAGS_DEBUG}") - set(LINKER_FLAGS_RELEASE "/nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib ${LINKER_FLAGS_RELEASE}") - endif() endif() if(ALSOFT_REQUIRE_WINMM AND NOT HAVE_WINMM) message(FATAL_ERROR "Failed to enabled required WinMM backend") @@ -1419,13 +1408,20 @@ else() endif() target_link_libraries(${IMPL_TARGET} PRIVATE alcommon ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB}) - if(ALSOFT_UWP AND HAVE_WASAPI) + if(ALSOFT_UWP) + find_program(NUGET_EXE NAMES nuget) + if(NOT NUGET_EXE) + message("NUGET.EXE not found.") + message(FATAL_ERROR "Please install this executable, and run CMake again.") + endif() + + exec_program(${NUGET_EXE} + ARGS install "Microsoft.Windows.CppWinRT" -Version 2.0.230706.1 -ExcludeVersion -OutputDirectory "\"${CMAKE_BINARY_DIR}/packages\"") + set_target_properties(${IMPL_TARGET} PROPERTIES - LINK_FLAGS_DEBUG "${LINKER_FLAGS_DEBUG}" - LINK_FLAGS_RELEASE "${LINKER_FLAGS_RELEASE}" - LINK_FLAGS_MINSIZEREL "${LINKER_FLAGS_RELEASE}" - LINK_FLAGS_RELWITHDEBINFO "${LINKER_FLAGS_RELEASE}" + VS_PROJECT_IMPORT ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT/build/native/Microsoft.Windows.CppWinRT.props ) + target_link_libraries(${IMPL_TARGET} PRIVATE ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT/build/native/Microsoft.Windows.CppWinRT.targets) endif() if(NOT WIN32 AND NOT APPLE) diff --git a/alc/alconfig.cpp b/alc/alconfig.cpp index 03139abe..097ba3a0 100644 --- a/alc/alconfig.cpp +++ b/alc/alconfig.cpp @@ -45,6 +45,13 @@ #include "strutils.h" #include "vector.h" +#if defined(ALSOFT_UWP) +#include // !!This is important!! +#include +#include +#include +using namespace winrt; +#endif namespace { @@ -336,7 +343,8 @@ void ReadALConfig() if (!SHGetSpecialFolderPathW(nullptr, buffer, CSIDL_APPDATA, FALSE)) return; #else - auto buffer = Windows::Storage::ApplicationData::Current->RoamingFolder->Path->Data(); + winrt::Windows::Storage::ApplicationDataContainer localSettings = winrt::Windows::Storage::ApplicationData::Current().LocalSettings(); + auto buffer = Windows::Storage::ApplicationData::Current().RoamingFolder().Path(); #endif std::string filepath{wstr_to_utf8(buffer)}; filepath += "\\alsoft.ini"; diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index d06d7401..fc626fc6 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -73,8 +73,15 @@ #include "strutils.h" #if defined(ALSOFT_UWP) -#include -using namespace Platform; + +#include // !!This is important!! +#include +#include +#include +#include +#include + +using namespace winrt; using namespace Windows::Foundation; using namespace Windows::Media::Devices; using namespace Windows::Devices::Enumeration; @@ -276,8 +283,8 @@ enum EDataFlow { #endif #if defined(ALSOFT_UWP) -using DeviceHandle = DeviceInformation^; -using EventRegistrationToken = Windows::Foundation::EventRegistrationToken; +using DeviceHandle = Windows::Devices::Enumeration::DeviceInformation; +using EventRegistrationToken = winrt::event_token; #else using DeviceHandle = ComPtr; #endif @@ -329,11 +336,11 @@ static NameGUIDPair GetDeviceNameAndGuid(const DeviceHandle &device) guid = UnknownGuid; } #else - std::string name{wstr_to_utf8(device->Name->Data())}; + std::string name{wstr_to_utf8(device.Name())}; std::string guid; // device->Id is DeviceInterfacePath: \\?\SWD#MMDEVAPI#{0.0.0.00000000}.{a21c17a0-fc1d-405e-ab5a-b513422b57d1}#{e6327cad-dcec-4949-ae8a-991e976a79d2} - Platform::String^ devIfPath = device->Id; - if(auto devIdStart = wcsstr(devIfPath->Data(), L"}.")) + auto devIfPath = device.Id(); + if(auto devIdStart = wcsstr(devIfPath.data(), L"}.")) { devIdStart += 2; // L"}." if(auto devIdStartEnd = wcschr(devIdStart, L'#')) @@ -388,35 +395,32 @@ struct DeviceHelper final : private IMMNotificationClient */ mActiveClientEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr); - mRenderDeviceChangedToken = MediaDevice::DefaultAudioRenderDeviceChanged += - ref new TypedEventHandler( - [this](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { - if(args->Role == AudioDeviceRole::Default) - { - const std::string msg{"Default playback device changed: "+ - wstr_to_utf8(args->Id->Data())}; - alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, - msg); - } + mRenderDeviceChangedToken = MediaDevice::DefaultAudioRenderDeviceChanged([this](const IInspectable& /*sender*/, const DefaultAudioRenderDeviceChangedEventArgs& args) { + if (args.Role() == AudioDeviceRole::Default) + { + const std::string msg{ "Default playback device changed: " + + wstr_to_utf8(args.Id())}; + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, + msg); + } }); - mCaptureDeviceChangedToken = MediaDevice::DefaultAudioCaptureDeviceChanged += - ref new TypedEventHandler( - [this](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { - if(args->Role == AudioDeviceRole::Default) - { - const std::string msg{"Default capture device changed: "+ - wstr_to_utf8(args->Id->Data())}; - alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, - msg); - } + + mCaptureDeviceChangedToken = MediaDevice::DefaultAudioCaptureDeviceChanged([this](const IInspectable& /*sender*/, const DefaultAudioCaptureDeviceChangedEventArgs& args) { + if (args.Role() == AudioDeviceRole::Default) + { + const std::string msg{ "Default capture device changed: " + + wstr_to_utf8(args.Id()) }; + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, + msg); + } }); #endif } ~DeviceHelper() { #if defined(ALSOFT_UWP) - MediaDevice::DefaultAudioRenderDeviceChanged -= mRenderDeviceChangedToken; - MediaDevice::DefaultAudioCaptureDeviceChanged -= mCaptureDeviceChangedToken; + MediaDevice::DefaultAudioRenderDeviceChanged(mRenderDeviceChangedToken); + MediaDevice::DefaultAudioCaptureDeviceChanged(mCaptureDeviceChangedToken); if(mActiveClientEvent != nullptr) CloseHandle(mActiveClientEvent); @@ -612,21 +616,16 @@ struct DeviceHelper final : private IMMNotificationClient return hr; #else const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; - Platform::String^ devIfPath = + auto devIfPath = devid.empty() ? (flow == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole)) - : ref new Platform::String(devid.data()); - if (!devIfPath) + : winrt::hstring(devid.data()); + if (devIfPath.empty()) return E_POINTER; - Concurrency::task createDeviceOp( - DeviceInformation::CreateFromIdAsync(devIfPath, nullptr, DeviceInformationKind::DeviceInterface)); - auto status = createDeviceOp.then([&](DeviceInformation^ deviceInfo) - { - device = deviceInfo; - }).wait(); - if(status != Concurrency::task_status::completed) - { + + auto&& deviceInfo = DeviceInformation::CreateFromIdAsync(devIfPath, nullptr, DeviceInformationKind::DeviceInterface).get(); + if (!deviceInfo) return E_NOINTERFACE; - } + device = deviceInfo; return S_OK; #endif } @@ -638,7 +637,7 @@ struct DeviceHelper final : private IMMNotificationClient HRESULT activateAudioClient(_In_ DeviceHandle &device, _In_ REFIID iid, void **ppv) { ComPtr asyncOp; - HRESULT hr{ActivateAudioInterfaceAsync(device->Id->Data(), iid, nullptr, this, + HRESULT hr{ActivateAudioInterfaceAsync(device.Id().data(), iid, nullptr, this, al::out_ptr(asyncOp))}; if(FAILED(hr)) return hr; @@ -713,40 +712,32 @@ struct DeviceHelper final : private IMMNotificationClient const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; auto DefaultAudioId = flowdir == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole); - if (!DefaultAudioId) + if (DefaultAudioId.empty()) return defaultId; - Concurrency::task createDefaultOp(DeviceInformation::CreateFromIdAsync(DefaultAudioId, nullptr, DeviceInformationKind::DeviceInterface)); - auto task_status = createDefaultOp.then([&defaultId](DeviceInformation ^ deviceInfo) - { - if(deviceInfo) - defaultId = deviceInfo->Id->Data(); - }).wait(); - if(task_status != Concurrency::task_group_status::completed) + + auto deviceInfo = DeviceInformation::CreateFromIdAsync(DefaultAudioId, nullptr, DeviceInformationKind::DeviceInterface).get(); + if(!deviceInfo) return defaultId; // Get the string identifier of the audio renderer auto AudioSelector = flowdir == eRender ? MediaDevice::GetAudioRenderSelector() : MediaDevice::GetAudioCaptureSelector(); // Setup the asynchronous callback - Concurrency::task enumOperation( - DeviceInformation::FindAllAsync(AudioSelector, /*PropertyList*/nullptr, DeviceInformationKind::DeviceInterface)); - task_status = enumOperation.then([this,&list](DeviceInformationCollection ^ DeviceInfoCollection) + auto&& DeviceInfoCollection = DeviceInformation::FindAllAsync(AudioSelector, /*PropertyList*/nullptr, DeviceInformationKind::DeviceInterface).get(); + if(DeviceInfoCollection) { - if(DeviceInfoCollection) - { - try { - auto deviceCount = DeviceInfoCollection->Size; - for(unsigned int i{0};i < deviceCount;++i) - { - DeviceInformation^ deviceInfo = DeviceInfoCollection->GetAt(i); - if(deviceInfo) - std::ignore = AddDevice(deviceInfo, deviceInfo->Id->Data(), list); - } - } - catch (Platform::Exception ^ e) { + try { + auto deviceCount = DeviceInfoCollection.Size(); + for(unsigned int i{0};i < deviceCount;++i) + { + deviceInfo = DeviceInfoCollection.GetAt(i); + if(deviceInfo) + std::ignore = AddDevice(deviceInfo, deviceInfo.Id().data(), list); } } - }).wait(); + catch (std::exception& /*ex*/) { + } + } #endif return defaultId; -- cgit v1.2.3 From c53ed17c59345526ba41b62bd886c2cbaaca423b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 22 Sep 2023 13:13:09 -0700 Subject: Avoid casting an integer literal --- al/auxeffectslot.cpp | 2 +- al/buffer.cpp | 2 +- al/eax/call.h | 2 +- al/effect.cpp | 2 +- al/filter.cpp | 2 +- al/source.cpp | 29 +++++++++++++++++------------ al/state.cpp | 2 +- alc/alu.cpp | 2 +- alc/backends/wave.cpp | 4 ++-- alc/context.cpp | 4 ++-- alc/device.cpp | 6 +++--- core/hrtf.cpp | 2 +- core/mixer/mixer_neon.cpp | 4 ++-- core/mixer/mixer_sse.cpp | 4 ++-- core/voice.cpp | 4 ++-- 15 files changed, 38 insertions(+), 33 deletions(-) (limited to 'alc') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 66a65b5c..33252410 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -239,7 +239,7 @@ EffectSlotType EffectSlotTypeFromEnum(ALenum type) bool EnsureEffectSlots(ALCcontext *context, size_t needed) { size_t count{std::accumulate(context->mEffectSlotList.cbegin(), - context->mEffectSlotList.cend(), size_t{0}, + context->mEffectSlotList.cend(), 0_uz, [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(sublist.FreeMask)); })}; diff --git a/al/buffer.cpp b/al/buffer.cpp index 28afc7c0..8ba874e4 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -174,7 +174,7 @@ constexpr ALbitfieldSOFT INVALID_MAP_FLAGS{~unsigned(AL_MAP_READ_BIT_SOFT | AL_M bool EnsureBuffers(ALCdevice *device, size_t needed) { - size_t count{std::accumulate(device->BufferList.cbegin(), device->BufferList.cend(), size_t{0}, + size_t count{std::accumulate(device->BufferList.cbegin(), device->BufferList.cend(), 0_uz, [](size_t cur, const BufferSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(sublist.FreeMask)); })}; diff --git a/al/eax/call.h b/al/eax/call.h index f2ad529e..45ff328c 100644 --- a/al/eax/call.h +++ b/al/eax/call.h @@ -61,7 +61,7 @@ public: template al::span get_values() const { - return get_values(~size_t{}); + return get_values(~0_uz); } template diff --git a/al/effect.cpp b/al/effect.cpp index 5c7f9627..c4b06407 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -162,7 +162,7 @@ void InitEffectParams(ALeffect *effect, ALenum type) bool EnsureEffects(ALCdevice *device, size_t needed) { - size_t count{std::accumulate(device->EffectList.cbegin(), device->EffectList.cend(), size_t{0}, + size_t count{std::accumulate(device->EffectList.cbegin(), device->EffectList.cend(), 0_uz, [](size_t cur, const EffectSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(sublist.FreeMask)); })}; diff --git a/al/filter.cpp b/al/filter.cpp index e6520e6a..f0a078b7 100644 --- a/al/filter.cpp +++ b/al/filter.cpp @@ -117,7 +117,7 @@ void InitFilterParams(ALfilter *filter, ALenum type) bool EnsureFilters(ALCdevice *device, size_t needed) { - size_t count{std::accumulate(device->FilterList.cbegin(), device->FilterList.cend(), size_t{0}, + size_t count{std::accumulate(device->FilterList.cbegin(), device->FilterList.cend(), 0_uz, [](size_t cur, const FilterSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(sublist.FreeMask)); })}; diff --git a/al/source.cpp b/al/source.cpp index 01a981d3..2fbd1703 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -719,8 +719,7 @@ inline ALenum GetSourceState(ALsource *source, Voice *voice) bool EnsureSources(ALCcontext *context, size_t needed) { - size_t count{std::accumulate(context->mSourceList.cbegin(), context->mSourceList.cend(), - size_t{0}, + size_t count{std::accumulate(context->mSourceList.cbegin(), context->mSourceList.cend(), 0_uz, [](size_t cur, const SourceSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(sublist.FreeMask)); })}; @@ -3697,7 +3696,8 @@ ALsource* ALsource::EaxLookupSource(ALCcontext& al_context, ALuint source_id) no void ALsource::eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) noexcept { - for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i) { + for(size_t i{0};i < EAX_MAX_FXSLOTS;++i) + { auto& send = sends[i]; send.guidReceivingFXSlotID = *(ids[i]); send.lSend = EAXSOURCE_DEFAULTSEND; @@ -3809,7 +3809,8 @@ void ALsource::eax5_set_active_fx_slots_defaults(EAX50ACTIVEFXSLOTS& slots) noex void ALsource::eax5_set_speaker_levels_defaults(EaxSpeakerLevels& speaker_levels) noexcept { - for (auto i = size_t{}; i < eax_max_speakers; ++i) { + for(size_t i{0};i < eax_max_speakers;++i) + { auto& speaker_level = speaker_levels[i]; speaker_level.lSpeakerID = static_cast(EAXSPEAKER_FRONT_LEFT + i); speaker_level.lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL; @@ -3912,7 +3913,7 @@ void ALsource::eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept // dst.sends = src.sends; - for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i) + for(size_t i{0};i < EAX_MAX_FXSLOTS;++i) dst.sends[i].guidReceivingFXSlotID = *(eax5_fx_slot_ids[i]); // Active FX slots. @@ -3974,19 +3975,21 @@ EaxAlLowPassParam ALsource::eax_create_direct_filter_param() const noexcept static_cast(mEax.source.lDirectHF) + static_cast(mEax.source.lObstruction); - for (auto i = std::size_t{}; i < EAX_MAX_FXSLOTS; ++i) + for(size_t i{0};i < EAX_MAX_FXSLOTS;++i) { if(!mEaxActiveFxSlots[i]) continue; - if(has_source_occlusion) { + if(has_source_occlusion) + { const auto& fx_slot = mEaxAlContext->eaxGetFxSlot(i); const auto& fx_slot_eax = fx_slot.eax_get_eax_fx_slot(); const auto is_environmental_fx = ((fx_slot_eax.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0); const auto is_primary = (mEaxPrimaryFxSlotId.value_or(-1) == fx_slot.eax_get_index()); const auto is_listener_environment = (is_environmental_fx && is_primary); - if(is_listener_environment) { + if(is_listener_environment) + { gain_mb += eax_calculate_dst_occlusion_mb( mEax.source.lOcclusion, mEax.source.flOcclusionDirectRatio, @@ -3998,7 +4001,8 @@ EaxAlLowPassParam ALsource::eax_create_direct_filter_param() const noexcept const auto& send = mEax.sends[i]; - if(send.lOcclusion != 0) { + if(send.lOcclusion != 0) + { gain_mb += eax_calculate_dst_occlusion_mb( send.lOcclusion, send.flOcclusionDirectRatio, @@ -4073,8 +4077,9 @@ void ALsource::eax_update_direct_filter() void ALsource::eax_update_room_filters() { - for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i) { - if (!mEaxActiveFxSlots[i]) + for(size_t i{0};i < EAX_MAX_FXSLOTS;++i) + { + if(!mEaxActiveFxSlots[i]) continue; auto& fx_slot = mEaxAlContext->eaxGetFxSlot(i); @@ -4880,7 +4885,7 @@ void ALsource::eax_commit_active_fx_slots() // Deactivate EFX auxiliary effect slots for inactive slots. Active slots // will be updated with the room filters. - for(auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i) + for(size_t i{0};i < EAX_MAX_FXSLOTS;++i) { if(!mEaxActiveFxSlots[i]) eax_set_al_source_send(nullptr, i, EaxAlLowPassParam{1.0f, 1.0f}); diff --git a/al/state.cpp b/al/state.cpp index 1c41d63c..5131edd9 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -229,7 +229,7 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT: { std::lock_guard _{context->mDebugCbLock}; - *values = cast_value(context->mDebugLog.empty() ? size_t{0} + *values = cast_value(context->mDebugLog.empty() ? 0_uz : (context->mDebugLog.front().mMessage.size()+1)); return; } diff --git a/alc/alu.cpp b/alc/alu.cpp index 1fa9d1d4..6eb4691e 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -733,7 +733,7 @@ void AmbiRotator(AmbiRotateMatrix &matrix, const int order) } } last_band = band_idx; - band_idx += static_cast(l)*size_t{2} + 1; + band_idx += static_cast(l)*2_uz + 1; } } /* End ambisonic rotation helpers. */ diff --git a/alc/backends/wave.cpp b/alc/backends/wave.cpp index 1078c654..794d5cb8 100644 --- a/alc/backends/wave.cpp +++ b/alc/backends/wave.cpp @@ -154,13 +154,13 @@ int WaveBackend::mixerProc() if(bytesize == 2) { - const size_t len{mBuffer.size() & ~size_t{1}}; + const size_t len{mBuffer.size() & ~1_uz}; for(size_t i{0};i < len;i+=2) std::swap(mBuffer[i], mBuffer[i+1]); } else if(bytesize == 4) { - const size_t len{mBuffer.size() & ~size_t{3}}; + const size_t len{mBuffer.size() & ~3_uz}; for(size_t i{0};i < len;i+=4) { std::swap(mBuffer[i ], mBuffer[i+3]); diff --git a/alc/context.cpp b/alc/context.cpp index 3b1de7b9..8c930056 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -127,7 +127,7 @@ ALCcontext::~ALCcontext() { TRACE("Freeing context %p\n", voidp{this}); - size_t count{std::accumulate(mSourceList.cbegin(), mSourceList.cend(), size_t{0u}, + size_t count{std::accumulate(mSourceList.cbegin(), mSourceList.cend(), 0_uz, [](size_t cur, const SourceSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(~sublist.FreeMask)); })}; if(count > 0) @@ -140,7 +140,7 @@ ALCcontext::~ALCcontext() #endif // ALSOFT_EAX mDefaultSlot = nullptr; - count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u}, + count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), 0_uz, [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(~sublist.FreeMask)); }); if(count > 0) diff --git a/alc/device.cpp b/alc/device.cpp index 66b13c5e..27aa6f36 100644 --- a/alc/device.cpp +++ b/alc/device.cpp @@ -34,19 +34,19 @@ ALCdevice::~ALCdevice() Backend = nullptr; - size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), size_t{0u}, + size_t count{std::accumulate(BufferList.cbegin(), BufferList.cend(), 0_uz, [](size_t cur, const BufferSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(~sublist.FreeMask)); })}; if(count > 0) WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s"); - count = std::accumulate(EffectList.cbegin(), EffectList.cend(), size_t{0u}, + count = std::accumulate(EffectList.cbegin(), EffectList.cend(), 0_uz, [](size_t cur, const EffectSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(~sublist.FreeMask)); }); if(count > 0) WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s"); - count = std::accumulate(FilterList.cbegin(), FilterList.cend(), size_t{0u}, + count = std::accumulate(FilterList.cbegin(), FilterList.cend(), 0_uz, [](size_t cur, const FilterSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(~sublist.FreeMask)); }); if(count > 0) diff --git a/core/hrtf.cpp b/core/hrtf.cpp index f131e72d..9a13a004 100644 --- a/core/hrtf.cpp +++ b/core/hrtf.cpp @@ -1368,7 +1368,7 @@ HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate) TRACE("Resampling HRTF %s (%uhz -> %uhz)\n", name.c_str(), hrtf->mSampleRate, devrate); /* Calculate the last elevation's index and get the total IR count. */ - const size_t lastEv{std::accumulate(hrtf->mFields.begin(), hrtf->mFields.end(), size_t{0}, + const size_t lastEv{std::accumulate(hrtf->mFields.begin(), hrtf->mFields.end(), 0_uz, [](const size_t curval, const HrtfStore::Field &field) noexcept -> size_t { return curval + field.evCount; } ) - 1}; diff --git a/core/mixer/mixer_neon.cpp b/core/mixer/mixer_neon.cpp index ef2936b3..ead775af 100644 --- a/core/mixer/mixer_neon.cpp +++ b/core/mixer/mixer_neon.cpp @@ -342,7 +342,7 @@ void Mix_(const al::span InSamples, const al::span 0) ? 1.0f / static_cast(Counter) : 0.0f}; const auto min_len = minz(Counter, InSamples.size()); - const auto aligned_len = minz((min_len+3) & ~size_t{3}, InSamples.size()) - min_len; + const auto aligned_len = minz((min_len+3) & ~3_uz, InSamples.size()) - min_len; for(FloatBufferLine &output : OutBuffer) MixLine(InSamples, al::assume_aligned<16>(output.data()+OutPos), *CurrentGains++, @@ -355,7 +355,7 @@ void Mix_(const al::span InSamples, float *OutBuffer, floa { const float delta{(Counter > 0) ? 1.0f / static_cast(Counter) : 0.0f}; const auto min_len = minz(Counter, InSamples.size()); - const auto aligned_len = minz((min_len+3) & ~size_t{3}, InSamples.size()) - min_len; + const auto aligned_len = minz((min_len+3) & ~3_uz, InSamples.size()) - min_len; MixLine(InSamples, al::assume_aligned<16>(OutBuffer), CurrentGain, TargetGain, delta, min_len, aligned_len, Counter); diff --git a/core/mixer/mixer_sse.cpp b/core/mixer/mixer_sse.cpp index 0aa5d5fb..70f77c14 100644 --- a/core/mixer/mixer_sse.cpp +++ b/core/mixer/mixer_sse.cpp @@ -307,7 +307,7 @@ void Mix_(const al::span InSamples, const al::span 0) ? 1.0f / static_cast(Counter) : 0.0f}; const auto min_len = minz(Counter, InSamples.size()); - const auto aligned_len = minz((min_len+3) & ~size_t{3}, InSamples.size()) - min_len; + const auto aligned_len = minz((min_len+3) & ~3_uz, InSamples.size()) - min_len; for(FloatBufferLine &output : OutBuffer) MixLine(InSamples, al::assume_aligned<16>(output.data()+OutPos), *CurrentGains++, @@ -320,7 +320,7 @@ void Mix_(const al::span InSamples, float *OutBuffer, float { const float delta{(Counter > 0) ? 1.0f / static_cast(Counter) : 0.0f}; const auto min_len = minz(Counter, InSamples.size()); - const auto aligned_len = minz((min_len+3) & ~size_t{3}, InSamples.size()) - min_len; + const auto aligned_len = minz((min_len+3) & ~3_uz, InSamples.size()) - min_len; MixLine(InSamples, al::assume_aligned<16>(OutBuffer), CurrentGain, TargetGain, delta, min_len, aligned_len, Counter); diff --git a/core/voice.cpp b/core/voice.cpp index 92da3e76..b8acc7a6 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -330,7 +330,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const std::byte *sr for(;skip;--skip) { const size_t byteShift{(nibbleOffset&1) * 4}; - const size_t wordOffset{(nibbleOffset>>1) & ~size_t{3}}; + const size_t wordOffset{(nibbleOffset>>1) & ~3_uz}; const size_t byteOffset{wordOffset*srcStep + ((nibbleOffset>>1)&3u)}; ++nibbleOffset; @@ -344,7 +344,7 @@ inline void LoadSamples(float *RESTRICT dstSamples, const std::byte *sr for(size_t i{0};i < todo;++i) { const size_t byteShift{(nibbleOffset&1) * 4}; - const size_t wordOffset{(nibbleOffset>>1) & ~size_t{3}}; + const size_t wordOffset{(nibbleOffset>>1) & ~3_uz}; const size_t byteOffset{wordOffset*srcStep + ((nibbleOffset>>1)&3u)}; ++nibbleOffset; -- cgit v1.2.3 From 2e24d1ed773c2fb0f5b85acb9c02acb9c8b5462d Mon Sep 17 00:00:00 2001 From: Deal Date: Sun, 24 Sep 2023 00:13:00 +0800 Subject: Fix cppwinrt exception type capture (#918) --- alc/backends/wasapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index fc626fc6..ebd095fd 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -735,7 +735,7 @@ struct DeviceHelper final : private IMMNotificationClient std::ignore = AddDevice(deviceInfo, deviceInfo.Id().data(), list); } } - catch (std::exception& /*ex*/) { + catch (const winrt::hresult_error& /*ex*/) { } } #endif -- cgit v1.2.3 From 64746158a139b6389e656c8640e456dd623c4bd1 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 24 Sep 2023 15:58:49 -0700 Subject: Support resampling with WASAPI spatial audio output --- alc/backends/wasapi.cpp | 81 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 14 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index ebd095fd..4494317a 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -115,11 +115,6 @@ using ReferenceTime = std::chrono::duration(n)}; } -#ifndef _MSC_VER -constexpr AudioObjectType operator|(AudioObjectType lhs, AudioObjectType rhs) noexcept -{ return static_cast(lhs | al::to_underlying(rhs)); } -#endif - #define MONO SPEAKER_FRONT_CENTER #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT) @@ -148,6 +143,12 @@ constexpr DWORD X61Mask{MaskFromTopBits(X6DOT1)}; constexpr DWORD X71Mask{MaskFromTopBits(X7DOT1)}; constexpr DWORD X714Mask{MaskFromTopBits(X7DOT1DOT4)}; + +#ifndef _MSC_VER +constexpr AudioObjectType operator|(AudioObjectType lhs, AudioObjectType rhs) noexcept +{ return static_cast(lhs | al::to_underlying(rhs)); } +#endif + constexpr AudioObjectType ChannelMask_Mono{AudioObjectType_FrontCenter}; constexpr AudioObjectType ChannelMask_Stereo{AudioObjectType_FrontLeft | AudioObjectType_FrontRight}; @@ -171,6 +172,7 @@ constexpr AudioObjectType ChannelMask_X714{AudioObjectType_FrontLeft | AudioObje | AudioObjectType_TopFrontLeft | AudioObjectType_TopFrontRight | AudioObjectType_TopBackLeft | AudioObjectType_TopBackRight}; + constexpr char DevNameHead[] = "OpenAL Soft on "; constexpr size_t DevNameHeadLen{std::size(DevNameHead) - 1}; @@ -182,6 +184,14 @@ template overloaded(Ts...) -> overloaded; +template +auto as_unsigned(T value) noexcept +{ + using UT = std::make_unsigned_t; + return static_cast(value); +} + + /* Scales the given reftime value, rounding the result. */ template constexpr uint RefTime2Samples(const ReferenceTime &val, T srate) noexcept @@ -1209,11 +1219,14 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() std::vector> channels; std::vector buffers; + std::vector resbuffers; + std::vector tmpbuffers; /* TODO: Set mPadding appropriately. There doesn't seem to be a way to - * update it dynamically based on the stream, so it may need to be set to a - * fixed size. + * update it dynamically based on the stream, so a fixed size may be the + * best we can do. */ + mPadding.store(mDevice->BufferSize-mDevice->UpdateSize, std::memory_order_release); while(!mKillNow.load(std::memory_order_relaxed)) { @@ -1236,12 +1249,11 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() { if(channels.empty()) UNLIKELY { - using UT = std::make_unsigned_t; - auto flags = static_cast(al::to_underlying(audio.mStaticMask)); - channels.reserve(static_cast(al::popcount(flags))); + auto flags = as_unsigned(audio.mStaticMask); + channels.reserve(as_unsigned(al::popcount(flags))); while(flags) { - auto id = UT{1} << al::countr_zero(flags); + auto id = decltype(flags){1} << al::countr_zero(flags); flags &= ~id; channels.emplace_back(); @@ -1249,6 +1261,14 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() al::out_ptr(channels.back())); } buffers.resize(channels.size()); + if(mResampler) + { + tmpbuffers.resize(buffers.size()); + resbuffers.resize(buffers.size()); + for(size_t i{0};i < tmpbuffers.size();++i) + resbuffers[i] = reinterpret_cast(mResampleBuffer.get()) + + mDevice->UpdateSize*i; + } } /* We have to call to get each channel's buffer individually every @@ -1263,7 +1283,27 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() return reinterpret_cast(buffer); }); - mDevice->renderSamples(buffers, framesToDo); + if(!mResampler) + mDevice->renderSamples(buffers, framesToDo); + else + { + std::lock_guard _{mMutex}; + for(UINT32 pos{0};pos < framesToDo;) + { + if(mBufferFilled == 0) + { + mDevice->renderSamples(resbuffers, mDevice->UpdateSize); + std::copy(resbuffers.cbegin(), resbuffers.cend(), tmpbuffers.begin()); + mBufferFilled = mDevice->UpdateSize; + } + + const uint got{mResampler->convertPlanar(tmpbuffers.data(), &mBufferFilled, + reinterpret_cast(buffers.data()), framesToDo-pos)}; + for(auto &buf : buffers) + buf += got; + pos += got; + } + } hr = audio.mRender->EndUpdatingAudioObjects(); } @@ -1745,12 +1785,10 @@ HRESULT WasapiPlayback::resetProxy() audio.mStaticMask = streamParams.StaticObjectTypeMask; mFormat = OutputType; - /* TODO: Support resampling. */ mDevice->FmtType = DevFmtFloat; mDevice->Flags.reset(DirectEar).set(Virtualization); if(streamParams.StaticObjectTypeMask == ChannelMask_Stereo) mDevice->FmtChans = DevFmtStereo; - mDevice->Frequency = mFormat.Format.nSamplesPerSec; setDefaultWFXChannelOrder(); @@ -1793,6 +1831,21 @@ HRESULT WasapiPlayback::resetProxy() mResampler = nullptr; mResampleBuffer = nullptr; mBufferFilled = 0; + if(mDevice->Frequency != mFormat.Format.nSamplesPerSec) + { + const auto flags = as_unsigned(streamParams.StaticObjectTypeMask); + const auto channelCount = as_unsigned(al::popcount(flags)); + mResampler = SampleConverter::Create(mDevice->FmtType, mDevice->FmtType, + channelCount, mDevice->Frequency, mFormat.Format.nSamplesPerSec, + Resampler::FastBSinc24); + mResampleBuffer = std::make_unique(size_t{mDevice->UpdateSize} * channelCount * + mFormat.Format.wBitsPerSample / 8); + + TRACE("Created converter for %s/%s format, dst: %luhz (%u), src: %uhz (%u)\n", + DevFmtChannelsString(mDevice->FmtChans), DevFmtTypeString(mDevice->FmtType), + mFormat.Format.nSamplesPerSec, mOrigUpdateSize, mDevice->Frequency, + mDevice->UpdateSize); + } return S_OK; } -- cgit v1.2.3 From acc618a1a68c99d61bf0c1897ba1af24e4ebed01 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 24 Sep 2023 16:06:15 -0700 Subject: Match the output sample rate if not requesting one --- alc/backends/wasapi.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 4494317a..516ac02c 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -1710,6 +1710,10 @@ HRESULT WasapiPlayback::resetProxy() OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + /* Match the output rate if not requesting anything specific. */ + if(!mDevice->Flags.test(FrequencyRequest)) + mDevice->Frequency = OutputType.Format.nSamplesPerSec; + bool isRear51{false}; if(!mDevice->Flags.test(ChannelsRequest)) { -- cgit v1.2.3 From 4fb1c23ca3679cc8e9840ebcab975176bd034ab4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 24 Sep 2023 19:10:06 -0700 Subject: Honor the wasapi allow-resampler option with spatial sound output --- alc/backends/wasapi.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 516ac02c..e26af7c9 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -1793,6 +1793,10 @@ HRESULT WasapiPlayback::resetProxy() mDevice->Flags.reset(DirectEar).set(Virtualization); if(streamParams.StaticObjectTypeMask == ChannelMask_Stereo) mDevice->FmtChans = DevFmtStereo; + if(!GetConfigValueBool(mDevice->DeviceName.c_str(), "wasapi", "allow-resampler", true)) + mDevice->Frequency = OutputType.Format.nSamplesPerSec; + else + mDevice->Frequency = minu(mDevice->Frequency, OutputType.Format.nSamplesPerSec); setDefaultWFXChannelOrder(); -- cgit v1.2.3 From 3ab2ca28f82073e0baeb25f49163f7353be4b2ca Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 25 Sep 2023 19:55:06 -0700 Subject: Constify some pointers to indicate they won't change --- alc/backends/wasapi.cpp | 2 +- core/converter.cpp | 2 +- core/converter.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index e26af7c9..7eae84c1 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -1298,7 +1298,7 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() } const uint got{mResampler->convertPlanar(tmpbuffers.data(), &mBufferFilled, - reinterpret_cast(buffers.data()), framesToDo-pos)}; + reinterpret_cast(buffers.data()), framesToDo-pos)}; for(auto &buf : buffers) buf += got; pos += got; diff --git a/core/converter.cpp b/core/converter.cpp index dea31bd5..5b2f3e15 100644 --- a/core/converter.cpp +++ b/core/converter.cpp @@ -309,7 +309,7 @@ uint SampleConverter::convert(const void **src, uint *srcframes, void *dst, uint return pos; } -uint SampleConverter::convertPlanar(const void **src, uint *srcframes, void **dst, uint dstframes) +uint SampleConverter::convertPlanar(const void **src, uint *srcframes, void *const*dst, uint dstframes) { const uint increment{mIncrement}; uint NumSrcSamples{*srcframes}; diff --git a/core/converter.h b/core/converter.h index d811b46b..49ca124d 100644 --- a/core/converter.h +++ b/core/converter.h @@ -36,7 +36,7 @@ struct SampleConverter { SampleConverter(size_t numchans) : mChan{numchans} { } uint convert(const void **src, uint *srcframes, void *dst, uint dstframes); - uint convertPlanar(const void **src, uint *srcframes, void **dst, uint dstframes); + uint convertPlanar(const void **src, uint *srcframes, void *const*dst, uint dstframes); uint availableOut(uint srcframes) const; using SampleOffset = std::chrono::duration>; -- cgit v1.2.3 From 43a57e02ea5b767960b9da2899d5765dae46a035 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 26 Sep 2023 18:34:51 -0700 Subject: Set the appropriate padding size It's based on the original/stream size, not the ALCdevice's. --- alc/backends/wasapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 7eae84c1..b68439a8 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -1226,7 +1226,7 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() * update it dynamically based on the stream, so a fixed size may be the * best we can do. */ - mPadding.store(mDevice->BufferSize-mDevice->UpdateSize, std::memory_order_release); + mPadding.store(mOrigBufferSize-mOrigUpdateSize, std::memory_order_release); while(!mKillNow.load(std::memory_order_relaxed)) { -- cgit v1.2.3 From fbe9d42d8a48330bb3ccc3966d1d94b438565f35 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 29 Sep 2023 12:26:17 -0700 Subject: Ensure the WASAPI resample buffer is cleared when mixing starts Otherwise, stopping and restarting without resetting could leave it with invalid pointers. --- alc/backends/wasapi.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index b68439a8..71975b55 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -1129,6 +1129,9 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() const uint frame_size{mFormat.Format.nChannels * mFormat.Format.wBitsPerSample / 8u}; const uint update_size{mOrigUpdateSize}; const UINT32 buffer_len{mOrigBufferSize}; + const void *resbufferptr{}; + + mBufferFilled = 0; while(!mKillNow.load(std::memory_order_relaxed)) { UINT32 written; @@ -1163,22 +1166,15 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() { mDevice->renderSamples(mResampleBuffer.get(), mDevice->UpdateSize, mFormat.Format.nChannels); + resbufferptr = mResampleBuffer.get(); mBufferFilled = mDevice->UpdateSize; } - const void *src{mResampleBuffer.get()}; - uint srclen{mBufferFilled}; - uint got{mResampler->convert(&src, &srclen, buffer, len-done)}; + uint got{mResampler->convert(&resbufferptr, &mBufferFilled, buffer, len-done)}; buffer += got*frame_size; done += got; mPadding.store(written + done, std::memory_order_relaxed); - if(srclen) - { - const char *bsrc{static_cast(src)}; - std::copy(bsrc, bsrc + srclen*frame_size, mResampleBuffer.get()); - } - mBufferFilled = srclen; } } else @@ -1228,6 +1224,7 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() */ mPadding.store(mOrigBufferSize-mOrigUpdateSize, std::memory_order_release); + mBufferFilled = 0; while(!mKillNow.load(std::memory_order_relaxed)) { if(DWORD res{WaitForSingleObjectEx(mNotifyEvent, 1000, FALSE)}; res != WAIT_OBJECT_0) -- cgit v1.2.3 From 014fb03d8353c8a495b4df4c44a7f29c93adba79 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 29 Sep 2023 13:29:51 -0700 Subject: Add a wrapper for COM initialization This helps ensure COM is initialized and deinitialized in order relative to other objects (e.g. ComPtr). --- alc/backends/dsound.cpp | 12 +++--------- alc/backends/wasapi.cpp | 46 +++++++++++++++++++++------------------------- common/comptr.h | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 34 deletions(-) (limited to 'alc') diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index b5596f1c..58aa69b2 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -307,12 +307,10 @@ void DSoundPlayback::open(std::string_view name) if(PlaybackDevices.empty()) { /* Initialize COM to prevent name truncation */ - HRESULT hrcom{CoInitialize(nullptr)}; + ComWrapper com{}; hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices); if(FAILED(hr)) ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr); - if(SUCCEEDED(hrcom)) - CoUninitialize(); } const GUID *guid{nullptr}; @@ -583,12 +581,10 @@ void DSoundCapture::open(std::string_view name) if(CaptureDevices.empty()) { /* Initialize COM to prevent name truncation */ - HRESULT hrcom{CoInitialize(nullptr)}; + ComWrapper com{}; hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices); if(FAILED(hr)) ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr); - if(SUCCEEDED(hrcom)) - CoUninitialize(); } const GUID *guid{nullptr}; @@ -815,8 +811,8 @@ std::string DSoundBackendFactory::probe(BackendType type) }; /* Initialize COM to prevent name truncation */ + ComWrapper com{}; HRESULT hr; - HRESULT hrcom{CoInitialize(nullptr)}; switch(type) { case BackendType::Playback: @@ -835,8 +831,6 @@ std::string DSoundBackendFactory::probe(BackendType type) std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device); break; } - if(SUCCEEDED(hrcom)) - CoUninitialize(); return outnames; } diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 71975b55..62c4c58a 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -973,15 +973,15 @@ int WasapiProxy::messageHandler(std::promise *promise) { TRACE("Starting message thread\n"); - HRESULT hr{CoInitializeEx(nullptr, COINIT_MULTITHREADED)}; - if(FAILED(hr)) + ComWrapper com{COINIT_MULTITHREADED}; + if(!com) { - WARN("Failed to initialize COM: 0x%08lx\n", hr); - promise->set_value(hr); + WARN("Failed to initialize COM: 0x%08lx\n", com.status()); + promise->set_value(com.status()); return 0; } - hr = sDeviceHelper.emplace().init(); + HRESULT hr{sDeviceHelper.emplace().init()}; promise->set_value(hr); promise = nullptr; if(FAILED(hr)) @@ -1040,7 +1040,6 @@ int WasapiProxy::messageHandler(std::promise *promise) skip_loop: sDeviceHelper.reset(); - CoUninitialize(); return 0; } @@ -1113,11 +1112,11 @@ WasapiPlayback::~WasapiPlayback() FORCE_ALIGN int WasapiPlayback::mixerProc() { - HRESULT hr{CoInitializeEx(nullptr, COINIT_MULTITHREADED)}; - if(FAILED(hr)) + ComWrapper com{COINIT_MULTITHREADED}; + if(!com) { - ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr); - mDevice->handleDisconnect("COM init failed: 0x%08lx", hr); + ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", com.status()); + mDevice->handleDisconnect("COM init failed: 0x%08lx", com.status()); return 1; } @@ -1135,7 +1134,7 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() while(!mKillNow.load(std::memory_order_relaxed)) { UINT32 written; - hr = audio.mClient->GetCurrentPadding(&written); + HRESULT hr{audio.mClient->GetCurrentPadding(&written)}; if(FAILED(hr)) { ERR("Failed to get padding: 0x%08lx\n", hr); @@ -1194,17 +1193,16 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() } mPadding.store(0u, std::memory_order_release); - CoUninitialize(); return 0; } FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() { - HRESULT hr{CoInitializeEx(nullptr, COINIT_MULTITHREADED)}; - if(FAILED(hr)) + ComWrapper com{COINIT_MULTITHREADED}; + if(!com) { - ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr); - mDevice->handleDisconnect("COM init failed: 0x%08lx", hr); + ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", com.status()); + mDevice->handleDisconnect("COM init failed: 0x%08lx", com.status()); return 1; } @@ -1231,7 +1229,7 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() { ERR("WaitForSingleObjectEx error: 0x%lx\n", res); - hr = audio.mRender->Reset(); + HRESULT hr{audio.mRender->Reset()}; if(FAILED(hr)) { ERR("ISpatialAudioObjectRenderStream::Reset failed: 0x%08lx\n", hr); @@ -1241,7 +1239,7 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() } UINT32 dynamicCount{}, framesToDo{}; - hr = audio.mRender->BeginUpdatingAudioObjects(&dynamicCount, &framesToDo); + HRESULT hr{audio.mRender->BeginUpdatingAudioObjects(&dynamicCount, &framesToDo)}; if(SUCCEEDED(hr)) { if(channels.empty()) UNLIKELY @@ -1310,7 +1308,6 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() } mPadding.store(0u, std::memory_order_release); - CoUninitialize(); return 0; } @@ -2150,11 +2147,11 @@ WasapiCapture::~WasapiCapture() FORCE_ALIGN int WasapiCapture::recordProc() { - HRESULT hr{CoInitializeEx(nullptr, COINIT_MULTITHREADED)}; - if(FAILED(hr)) + ComWrapper com{COINIT_MULTITHREADED}; + if(!com) { - ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr); - mDevice->handleDisconnect("COM init failed: 0x%08lx", hr); + ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", com.status()); + mDevice->handleDisconnect("COM init failed: 0x%08lx", com.status()); return 1; } @@ -2164,7 +2161,7 @@ FORCE_ALIGN int WasapiCapture::recordProc() while(!mKillNow.load(std::memory_order_relaxed)) { UINT32 avail; - hr = mCapture->GetNextPacketSize(&avail); + HRESULT hr{mCapture->GetNextPacketSize(&avail)}; if(FAILED(hr)) ERR("Failed to get next packet size: 0x%08lx\n", hr); else if(avail > 0) @@ -2235,7 +2232,6 @@ FORCE_ALIGN int WasapiCapture::recordProc() ERR("WaitForSingleObjectEx error: 0x%lx\n", res); } - CoUninitialize(); return 0; } diff --git a/common/comptr.h b/common/comptr.h index 5a733ea2..9f8fd294 100644 --- a/common/comptr.h +++ b/common/comptr.h @@ -7,6 +7,44 @@ #include #include +#define WIN32_LEAN_AND_MEAN +#include +#include + +struct ComWrapper { + HRESULT mStatus{}; + + ComWrapper(void *reserved, DWORD coinit) + : mStatus{CoInitializeEx(reserved, coinit)} + { } + ComWrapper(DWORD coinit=COINIT_APARTMENTTHREADED) + : mStatus{CoInitializeEx(nullptr, coinit)} + { } + ComWrapper(ComWrapper&& rhs) { mStatus = std::exchange(rhs.mStatus, E_FAIL); } + ComWrapper(const ComWrapper&) = delete; + ~ComWrapper() { if(SUCCEEDED(mStatus)) CoUninitialize(); } + + ComWrapper& operator=(ComWrapper&& rhs) + { + if(SUCCEEDED(mStatus)) + CoUninitialize(); + mStatus = std::exchange(rhs.mStatus, E_FAIL); + return *this; + } + ComWrapper& operator=(const ComWrapper&) = delete; + + HRESULT status() const noexcept { return mStatus; } + explicit operator bool() const noexcept { return SUCCEEDED(status()); } + + void uninit() + { + if(SUCCEEDED(mStatus)) + CoUninitialize(); + mStatus = E_FAIL; + } +}; + + template struct ComPtr { using element_type = T; -- cgit v1.2.3 From cd09bd95ca655011cf1654f1cd8775f3edbcbb71 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 1 Oct 2023 14:47:14 -0700 Subject: Get the default WASAPI device on UWP --- alc/backends/wasapi.cpp | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 62c4c58a..b6d7aaed 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -110,9 +110,9 @@ using std::chrono::nanoseconds; using std::chrono::milliseconds; using std::chrono::seconds; -using ReferenceTime = std::chrono::duration>; +using ReferenceTime = std::chrono::duration>; -inline constexpr ReferenceTime operator "" _reftime(unsigned long long int n) noexcept +constexpr ReferenceTime operator "" _reftime(unsigned long long int n) noexcept { return ReferenceTime{static_cast(n)}; } @@ -185,7 +185,7 @@ overloaded(Ts...) -> overloaded; template -auto as_unsigned(T value) noexcept +constexpr auto as_unsigned(T value) noexcept { using UT = std::make_unsigned_t; return static_cast(value); @@ -248,9 +248,9 @@ struct DevMap { }; DevMap::~DevMap() = default; -bool checkName(const al::span list, const std::string &name) +bool checkName(const al::span list, const std::string_view name) { - auto match_name = [&name](const DevMap &entry) -> bool { return entry.name == name; }; + auto match_name = [name](const DevMap &entry) -> bool { return entry.name == name; }; return std::find_if(list.cbegin(), list.cend(), match_name) != list.cend(); } @@ -309,7 +309,7 @@ static NameGUIDPair GetDeviceNameAndGuid(const DeviceHandle &device) std::string name, guid; ComPtr ps; - HRESULT hr = device->OpenPropertyStore(STGM_READ, al::out_ptr(ps)); + HRESULT hr{device->OpenPropertyStore(STGM_READ, al::out_ptr(ps))}; if(FAILED(hr)) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); @@ -319,32 +319,20 @@ static NameGUIDPair GetDeviceNameAndGuid(const DeviceHandle &device) PropVariant pvprop; hr = ps->GetValue(al::bit_cast(DEVPKEY_Device_FriendlyName), pvprop.get()); if(FAILED(hr)) - { WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); - name = UnknownName; - } else if(pvprop->vt == VT_LPWSTR) name = wstr_to_utf8(pvprop->pwszVal); else - { WARN("Unexpected Device_FriendlyName PROPVARIANT type: 0x%04x\n", pvprop->vt); - name = UnknownName; - } pvprop.clear(); hr = ps->GetValue(al::bit_cast(PKEY_AudioEndpoint_GUID), pvprop.get()); if(FAILED(hr)) - { WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); - guid = UnknownGuid; - } else if(pvprop->vt == VT_LPWSTR) guid = wstr_to_utf8(pvprop->pwszVal); else - { WARN("Unexpected AudioEndpoint_GUID PROPVARIANT type: 0x%04x\n", pvprop->vt); - guid = UnknownGuid; - } #else std::string name{wstr_to_utf8(device.Name())}; std::string guid; @@ -361,9 +349,9 @@ static NameGUIDPair GetDeviceNameAndGuid(const DeviceHandle &device) [](char ch) { return static_cast(std::toupper(ch)); }); } } +#endif if(name.empty()) name = UnknownName; if(guid.empty()) guid = UnknownGuid; -#endif return std::make_pair(std::move(name), std::move(guid)); } #if !defined(ALSOFT_UWP) @@ -722,12 +710,13 @@ struct DeviceHelper final : private IMMNotificationClient const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; auto DefaultAudioId = flowdir == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole); - if (DefaultAudioId.empty()) - return defaultId; - - auto deviceInfo = DeviceInformation::CreateFromIdAsync(DefaultAudioId, nullptr, DeviceInformationKind::DeviceInterface).get(); - if(!deviceInfo) - return defaultId; + if(!DefaultAudioId.empty()) + { + auto deviceInfo = DeviceInformation::CreateFromIdAsync(DefaultAudioId, nullptr, + DeviceInformationKind::DeviceInterface).get(); + if(deviceInfo) + defaultId = deviceInfo.Id().data(); + } // Get the string identifier of the audio renderer auto AudioSelector = flowdir == eRender ? MediaDevice::GetAudioRenderSelector() : MediaDevice::GetAudioCaptureSelector(); -- cgit v1.2.3 From 32b89db9aee9b30ce37469a670750bfeb63e57c9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 1 Oct 2023 23:20:08 -0700 Subject: Declare a missing variable --- alc/backends/wasapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index b6d7aaed..37151ef9 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -729,7 +729,7 @@ struct DeviceHelper final : private IMMNotificationClient auto deviceCount = DeviceInfoCollection.Size(); for(unsigned int i{0};i < deviceCount;++i) { - deviceInfo = DeviceInfoCollection.GetAt(i); + auto deviceInfo = DeviceInfoCollection.GetAt(i); if(deviceInfo) std::ignore = AddDevice(deviceInfo, deviceInfo.Id().data(), list); } -- cgit v1.2.3 From 340a22be6befeb308745bea871396da94b873245 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 2 Oct 2023 18:51:16 -0700 Subject: Improve ambisonic rotator coefficient accuracy --- alc/alu.cpp | 55 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 17 deletions(-) (limited to 'alc') diff --git a/alc/alu.cpp b/alc/alu.cpp index 6eb4691e..1585b8f2 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -627,17 +627,38 @@ struct RotatorCoeffs { { for(int m{-l};m <= l;++m) { - // compute u,v,w terms of Eq.8.1 (Table I) - const bool d{m == 0}; // the delta function d_m0 - const float denom{static_cast((std::abs(n) == l) ? - (2*l) * (2*l - 1) : (l*l - n*n))}; - - const int abs_m{std::abs(m)}; - coeffs->u = std::sqrt(static_cast(l*l - m*m)/denom); - coeffs->v = std::sqrt(static_cast(l+abs_m-1) * - static_cast(l+abs_m) / denom) * (1.0f+d) * (1.0f - 2.0f*d) * 0.5f; - coeffs->w = std::sqrt(static_cast(l-abs_m-1) * - static_cast(l-abs_m) / denom) * (1.0f-d) * -0.5f; + /* compute u,v,w terms of Eq.8.1 (Table I) + * + * const bool d{m == 0}; // the delta function d_m0 + * const double denom{(std::abs(n) == l) ? + * (2*l) * (2*l - 1) : (l*l - n*n)}; + * + * const int abs_m{std::abs(m)}; + * coeffs->u = std::sqrt((l*l - m*m) / denom); + * coeffs->v = std::sqrt((l+abs_m-1) * (l+abs_m) / denom) * + * (1.0+d) * (1.0 - 2.0*d) * 0.5; + * coeffs->w = std::sqrt((l-abs_m-1) * (l-abs_m) / denom) * + * (1.0-d) * -0.5; + */ + + const double denom{static_cast((std::abs(n) == l) ? + (2*l) * (2*l - 1) : (l*l - n*n))}; + + if(m == 0) + { + coeffs->u = static_cast(std::sqrt(l * l / denom)); + coeffs->v = static_cast(std::sqrt((l-1) * l / denom) * -1.0); + coeffs->w = 0.0f; + } + else + { + const int abs_m{std::abs(m)}; + coeffs->u = static_cast(std::sqrt((l*l - m*m) / denom)); + coeffs->v = static_cast(std::sqrt((l+abs_m-1) * (l+abs_m) / denom) * + 0.5); + coeffs->w = static_cast(std::sqrt((l-abs_m-1) * (l-abs_m) / denom) * + -0.5); + } ++coeffs; } } @@ -721,12 +742,12 @@ void AmbiRotator(AmbiRotateMatrix &matrix, const int order) float r{0.0f}; // computes Eq.8.1 - const float u{coeffs->u}; - if(u != 0.0f) r += u * U(l, m, n, last_band, matrix); - const float v{coeffs->v}; - if(v != 0.0f) r += v * V(l, m, n, last_band, matrix); - const float w{coeffs->w}; - if(w != 0.0f) r += w * W(l, m, n, last_band, matrix); + if(const float u{coeffs->u}; u != 0.0f) + r += u * U(l, m, n, last_band, matrix); + if(const float v{coeffs->v}; v != 0.0f) + r += v * V(l, m, n, last_band, matrix); + if(const float w{coeffs->w}; w != 0.0f) + r += w * W(l, m, n, last_band, matrix); matrix[y][x] = r; ++coeffs; -- cgit v1.2.3 From f1bf7a42ac66124b6f6dc5e01897a5f052519df3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 6 Oct 2023 00:58:21 -0700 Subject: Use PFFFT for the convolution effect --- alc/effects/convolution.cpp | 132 ++++++++++++++++++++++++++++++-------------- 1 file changed, 92 insertions(+), 40 deletions(-) (limited to 'alc') diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index f46422d4..c7a342dc 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -34,6 +34,7 @@ #include "core/fmt_traits.h" #include "core/mixer.h" #include "intrusive_ptr.h" +#include "pffft.h" #include "polyphase_resampler.h" #include "vector.h" @@ -45,6 +46,10 @@ namespace { * each segment has an FFT applied with a 256-sample buffer (the latter half * left silent) to get its frequency-domain response. The resulting response * has its positive/non-mirrored frequencies saved (129 bins) in each segment. + * Note that since the 0th and 129th bins are real for a real signal, their + * imaginary components are always 0 and can be dropped, allowing their real + * components to be combined so only 128 complex values are stored for the 129 + * bins. * * Input samples are similarly broken up into 128-sample segments, with an FFT * applied to each new incoming segment to get its 129 bins. A history of FFT'd @@ -52,8 +57,8 @@ namespace { * * To apply the reverberation, each impulse response segment is convolved with * its paired input segment (using complex multiplies, far cheaper than FIRs), - * accumulating into a 256-bin FFT buffer. The input history is then shifted to - * align with later impulse response segments for next time. + * accumulating into a 129-bin FFT buffer. The input history is then shifted to + * align with later impulse response segments for the next input segment. * * An inverse FFT is then applied to the accumulated FFT buffer to get a 256- * sample time-domain response for output, which is split in two halves. The @@ -183,6 +188,35 @@ void apply_fir(al::span dst, const float *RESTRICT src, const float *REST #endif } + +template +struct AlignedDeleter { }; + +template +struct AlignedDeleter { + static_assert(std::is_trivially_destructible_v); + using type = T; + + void operator()(T *ptr) { al_free(ptr); } +}; +template +using AlignedUPtr = std::unique_ptr>; + +template +auto MakeAlignedPtr(size_t count) -> AlignedUPtr +{ + using Type = typename AlignedDeleter::type; + void *ptr{al_calloc(A, sizeof(Type)*count)}; + return AlignedUPtr{::new(ptr) Type[count]}; +} + + +struct PFFFTSetupDeleter { + void operator()(PFFFT_Setup *ptr) { pffft_destroy_setup(ptr); } +}; +using PFFFTSetupPtr = std::unique_ptr; + + struct ConvolutionState final : public EffectState { FmtChannels mChannels{}; AmbiLayout mAmbiLayout{}; @@ -194,7 +228,9 @@ struct ConvolutionState final : public EffectState { al::vector,16> mFilter; al::vector,16> mOutput; - alignas(16) std::array mFftBuffer{}; + PFFFTSetupPtr mFft{}; + alignas(16) std::array mFftBuffer{}; + alignas(16) std::array mFftWorkBuffer{}; size_t mCurrentSegment{0}; size_t mNumConvolveSegs{0}; @@ -208,7 +244,7 @@ struct ConvolutionState final : public EffectState { }; using ChannelDataArray = al::FlexArray; std::unique_ptr mChans; - std::unique_ptr mComplexData; + AlignedUPtr mComplexData; ConvolutionState() = default; @@ -253,13 +289,17 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag using UhjDecoderType = UhjDecoder<512>; static constexpr auto DecoderPadding = UhjDecoderType::sInputPadding; - constexpr uint MaxConvolveAmbiOrder{1u}; + static constexpr uint MaxConvolveAmbiOrder{1u}; + + if(!mFft) + mFft = PFFFTSetupPtr{pffft_new_setup(ConvolveUpdateSize, PFFFT_REAL)}; mFifoPos = 0; mInput.fill(0.0f); decltype(mFilter){}.swap(mFilter); decltype(mOutput){}.swap(mOutput); - mFftBuffer.fill(complex_f{}); + mFftBuffer.fill(0.0f); + mFftWorkBuffer.fill(0.0f); mCurrentSegment = 0; mNumConvolveSegs = 0; @@ -275,7 +315,6 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag mAmbiScaling = IsUHJ(mChannels) ? AmbiScaling::UHJ : buffer->mAmbiScaling; mAmbiOrder = minu(buffer->mAmbiOrder, MaxConvolveAmbiOrder); - constexpr size_t m{ConvolveUpdateSize/2 + 1}; const auto bytesPerSample = BytesFromFmt(buffer->mType); const auto realChannels = buffer->channelsFromFmt(); const auto numChannels = (mChannels == FmtUHJ2) ? 3u : ChannelsFromFmt(mChannels, mAmbiOrder); @@ -309,9 +348,9 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag mNumConvolveSegs = (resampledCount+(ConvolveUpdateSamples-1)) / ConvolveUpdateSamples; mNumConvolveSegs = maxz(mNumConvolveSegs, 2) - 1; - const size_t complex_length{mNumConvolveSegs * m * (numChannels+1)}; - mComplexData = std::make_unique(complex_length); - std::fill_n(mComplexData.get(), complex_length, complex_f{}); + const size_t complex_length{mNumConvolveSegs * ConvolveUpdateSize * (numChannels+1)}; + mComplexData = MakeAlignedPtr(complex_length); + std::fill_n(mComplexData.get(), complex_length, 0.0f); /* Load the samples from the buffer. */ const size_t srclinelength{RoundUp(buffer->mSampleLen+DecoderPadding, 16)}; @@ -332,7 +371,10 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag auto ressamples = std::make_unique(buffer->mSampleLen + (resampler ? resampledCount : 0)); - complex_f *filteriter = mComplexData.get() + mNumConvolveSegs*m; + auto ffttmp = al::vector(ConvolveUpdateSize); + auto fftbuffer = std::vector>(ConvolveUpdateSize); + + float *filteriter = mComplexData.get() + mNumConvolveSegs*ConvolveUpdateSize; for(size_t c{0};c < numChannels;++c) { /* Resample to match the device. */ @@ -353,18 +395,34 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag std::transform(ressamples.get(), ressamples.get()+first_size, mFilter[c].rbegin(), [](const double d) noexcept -> float { return static_cast(d); }); - auto fftbuffer = std::vector>(ConvolveUpdateSize); size_t done{first_size}; for(size_t s{0};s < mNumConvolveSegs;++s) { const size_t todo{minz(resampledCount-done, ConvolveUpdateSamples)}; + /* Apply a double-precision forward FFT for more precise frequency + * measurements. + */ auto iter = std::copy_n(&ressamples[done], todo, fftbuffer.begin()); done += todo; std::fill(iter, fftbuffer.end(), std::complex{}); - forward_fft(al::span{fftbuffer}); - filteriter = std::copy_n(fftbuffer.cbegin(), m, filteriter); + + /* Convert to, and pack in, a float buffer for PFFFT. Note that the + * first bin stores the real component of the half-frequency bin in + * the imaginary component. + */ + for(size_t i{0};i < ConvolveUpdateSamples;++i) + { + ffttmp[i*2 ] = static_cast(fftbuffer[i].real()); + ffttmp[i*2 + 1] = static_cast((i == 0) ? + fftbuffer[ConvolveUpdateSamples+1].real() : fftbuffer[i].imag()); + } + /* Reorder backward to make it suitable for pffft_zconvolve and the + * subsequent pffft_transform(..., PFFFT_BACKWARD). + */ + pffft_zreorder(mFft.get(), ffttmp.data(), al::to_address(filteriter), PFFFT_BACKWARD); + filteriter += ConvolveUpdateSize; } } } @@ -554,7 +612,6 @@ void ConvolutionState::process(const size_t samplesToDo, if(mNumConvolveSegs < 1) UNLIKELY return; - constexpr size_t m{ConvolveUpdateSize/2 + 1}; size_t curseg{mCurrentSegment}; auto &chans = *mChans; @@ -591,54 +648,49 @@ void ConvolutionState::process(const size_t samplesToDo, * frequency bins to the FFT history. */ auto fftiter = std::copy_n(mInput.cbegin(), ConvolveUpdateSamples, mFftBuffer.begin()); - std::fill(fftiter, mFftBuffer.end(), complex_f{}); - forward_fft(al::span{mFftBuffer}); + std::fill(fftiter, mFftBuffer.end(), 0.0f); + pffft_transform(mFft.get(), mFftBuffer.data(), + mComplexData.get() + curseg*ConvolveUpdateSize, mFftWorkBuffer.data(), PFFFT_FORWARD); - std::copy_n(mFftBuffer.cbegin(), m, &mComplexData[curseg*m]); - - const complex_f *RESTRICT filter{mComplexData.get() + mNumConvolveSegs*m}; + const float *RESTRICT filter{mComplexData.get() + mNumConvolveSegs*ConvolveUpdateSize}; for(size_t c{0};c < chans.size();++c) { - std::fill_n(mFftBuffer.begin(), m, complex_f{}); + /* The iFFT'd response is scaled up by the number of bins, so apply + * the inverse to normalize the output. + */ + static constexpr float fftscale{1.0f / float{ConvolveUpdateSize}}; /* Convolve each input segment with its IR filter counterpart * (aligned in time). */ - const complex_f *RESTRICT input{&mComplexData[curseg*m]}; + mFftBuffer.fill(0.0f); + const float *RESTRICT input{&mComplexData[curseg*ConvolveUpdateSize]}; for(size_t s{curseg};s < mNumConvolveSegs;++s) { - for(size_t i{0};i < m;++i,++input,++filter) - mFftBuffer[i] += *input * *filter; + pffft_zconvolve_accumulate(mFft.get(), input, filter, mFftBuffer.data(), fftscale); + input += ConvolveUpdateSize; + filter += ConvolveUpdateSize; } input = mComplexData.get(); for(size_t s{0};s < curseg;++s) { - for(size_t i{0};i < m;++i,++input,++filter) - mFftBuffer[i] += *input * *filter; + pffft_zconvolve_accumulate(mFft.get(), input, filter, mFftBuffer.data(), fftscale); + input += ConvolveUpdateSize; + filter += ConvolveUpdateSize; } - /* Reconstruct the mirrored/negative frequencies to do a proper - * inverse FFT. - */ - for(size_t i{m};i < ConvolveUpdateSize;++i) - mFftBuffer[i] = std::conj(mFftBuffer[ConvolveUpdateSize-i]); - /* Apply iFFT to get the 256 (really 255) samples for output. The * 128 output samples are combined with the last output's 127 * second-half samples (and this output's second half is * subsequently saved for next time). */ - inverse_fft(al::span{mFftBuffer}); + pffft_transform(mFft.get(), mFftBuffer.data(), mFftBuffer.data(), + mFftWorkBuffer.data(), PFFFT_BACKWARD); - /* The iFFT'd response is scaled up by the number of bins, so apply - * the inverse to normalize the output. - */ for(size_t i{0};i < ConvolveUpdateSamples;++i) - mOutput[c][i] = - (mFftBuffer[i].real()+mOutput[c][ConvolveUpdateSamples+i]) * - (1.0f/float{ConvolveUpdateSize}); + mOutput[c][i] = mFftBuffer[i] + mOutput[c][ConvolveUpdateSamples+i]; for(size_t i{0};i < ConvolveUpdateSamples;++i) - mOutput[c][ConvolveUpdateSamples+i] = mFftBuffer[ConvolveUpdateSamples+i].real(); + mOutput[c][ConvolveUpdateSamples+i] = mFftBuffer[ConvolveUpdateSamples+i]; } /* Shift the input history. */ -- cgit v1.2.3 From 5149cb8c357630dba5253e2568b68d2ed069bcea Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 11 Oct 2023 15:56:11 -0700 Subject: Make and use a separate zconvolve method without scaling When you're doing hundreds or thousands of separate zconvolve calls into the same buffer, it's more efficient to do the multiply once at the end instead of in each call. --- alc/effects/convolution.cpp | 15 ++++----- common/pffft.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++-- common/pffft.h | 16 +++++++-- 3 files changed, 96 insertions(+), 14 deletions(-) (limited to 'alc') diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index c7a342dc..a98a0616 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -655,11 +655,6 @@ void ConvolutionState::process(const size_t samplesToDo, const float *RESTRICT filter{mComplexData.get() + mNumConvolveSegs*ConvolveUpdateSize}; for(size_t c{0};c < chans.size();++c) { - /* The iFFT'd response is scaled up by the number of bins, so apply - * the inverse to normalize the output. - */ - static constexpr float fftscale{1.0f / float{ConvolveUpdateSize}}; - /* Convolve each input segment with its IR filter counterpart * (aligned in time). */ @@ -667,14 +662,14 @@ void ConvolutionState::process(const size_t samplesToDo, const float *RESTRICT input{&mComplexData[curseg*ConvolveUpdateSize]}; for(size_t s{curseg};s < mNumConvolveSegs;++s) { - pffft_zconvolve_accumulate(mFft.get(), input, filter, mFftBuffer.data(), fftscale); + pffft_zconvolve_accumulate(mFft.get(), input, filter, mFftBuffer.data()); input += ConvolveUpdateSize; filter += ConvolveUpdateSize; } input = mComplexData.get(); for(size_t s{0};s < curseg;++s) { - pffft_zconvolve_accumulate(mFft.get(), input, filter, mFftBuffer.data(), fftscale); + pffft_zconvolve_accumulate(mFft.get(), input, filter, mFftBuffer.data()); input += ConvolveUpdateSize; filter += ConvolveUpdateSize; } @@ -687,8 +682,12 @@ void ConvolutionState::process(const size_t samplesToDo, pffft_transform(mFft.get(), mFftBuffer.data(), mFftBuffer.data(), mFftWorkBuffer.data(), PFFFT_BACKWARD); + /* The iFFT'd response is scaled up by the number of bins, so apply + * the inverse to normalize the output. + */ + static constexpr float fftscale{1.0f / float{ConvolveUpdateSize}}; for(size_t i{0};i < ConvolveUpdateSamples;++i) - mOutput[c][i] = mFftBuffer[i] + mOutput[c][ConvolveUpdateSamples+i]; + mOutput[c][i] = (mFftBuffer[i]+mOutput[c][ConvolveUpdateSamples+i]) * fftscale; for(size_t i{0};i < ConvolveUpdateSamples;++i) mOutput[c][ConvolveUpdateSamples+i] = mFftBuffer[ConvolveUpdateSamples+i]; } diff --git a/common/pffft.cpp b/common/pffft.cpp index 7e5ba5c3..f8568acf 100644 --- a/common/pffft.cpp +++ b/common/pffft.cpp @@ -1904,7 +1904,7 @@ void pffft_zreorder(PFFFT_Setup *setup, const float *in, float *out, pffft_direc } } -void pffft_zconvolve_accumulate(PFFFT_Setup *s, const float *a, const float *b, float *ab, +void pffft_zconvolve_scale_accumulate(PFFFT_Setup *s, const float *a, const float *b, float *ab, float scaling) { const size_t Ncvec{s->Ncvec}; @@ -2006,6 +2006,59 @@ void pffft_zconvolve_accumulate(PFFFT_Setup *s, const float *a, const float *b, } } +void pffft_zconvolve_accumulate(PFFFT_Setup *s, const float *a, const float *b, float *ab) +{ + const size_t Ncvec{s->Ncvec}; + const v4sf *RESTRICT va{reinterpret_cast(a)}; + const v4sf *RESTRICT vb{reinterpret_cast(b)}; + v4sf *RESTRICT vab{reinterpret_cast(ab)}; + +#ifdef __arm__ + __builtin_prefetch(va); + __builtin_prefetch(vb); + __builtin_prefetch(vab); + __builtin_prefetch(va+2); + __builtin_prefetch(vb+2); + __builtin_prefetch(vab+2); + __builtin_prefetch(va+4); + __builtin_prefetch(vb+4); + __builtin_prefetch(vab+4); + __builtin_prefetch(va+6); + __builtin_prefetch(vb+6); + __builtin_prefetch(vab+6); +#endif + + const float ar1{VEXTRACT0(va[0])}; + const float ai1{VEXTRACT0(va[1])}; + const float br1{VEXTRACT0(vb[0])}; + const float bi1{VEXTRACT0(vb[1])}; + const float abr1{VEXTRACT0(vab[0])}; + const float abi1{VEXTRACT0(vab[1])}; + + /* No inline assembly for this version. I'm not familiar enough with NEON + * assembly, and I don't know that it's needed with today's optimizers. + */ + for(size_t i{0};i < Ncvec;i += 2) + { + v4sf ar4{va[2*i+0]}, ai4{va[2*i+1]}; + v4sf br4{vb[2*i+0]}, bi4{vb[2*i+1]}; + VCPLXMUL(ar4, ai4, br4, bi4); + vab[2*i+0] = VADD(ar4, vab[2*i+0]); + vab[2*i+1] = VADD(ai4, vab[2*i+1]); + ar4 = va[2*i+2]; ai4 = va[2*i+3]; + br4 = vb[2*i+2]; bi4 = vb[2*i+3]; + VCPLXMUL(ar4, ai4, br4, bi4); + vab[2*i+2] = VADD(ar4, vab[2*i+2]); + vab[2*i+3] = VADD(ai4, vab[2*i+3]); + } + + if(s->transform == PFFFT_REAL) + { + vab[0] = VINSERT0(vab[0], abr1 + ar1*br1); + vab[1] = VINSERT0(vab[1], abi1 + ai1*bi1); + } +} + void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction) { @@ -2115,8 +2168,7 @@ void pffft_zreorder_nosimd(PFFFT_Setup *setup, const float *in, float *out, } } -#define pffft_zconvolve_accumulate_nosimd pffft_zconvolve_accumulate -void pffft_zconvolve_accumulate_nosimd(PFFFT_Setup *s, const float *a, const float *b, float *ab, +void pffft_zconvolve_scale_accumulate(PFFFT_Setup *s, const float *a, const float *b, float *ab, float scaling) { size_t Ncvec{s->Ncvec}; @@ -2138,6 +2190,27 @@ void pffft_zconvolve_accumulate_nosimd(PFFFT_Setup *s, const float *a, const flo } } +void pffft_zconvolve_accumulate(PFFFT_Setup *s, const float *a, const float *b, float *ab) +{ + size_t Ncvec{s->Ncvec}; + + if(s->transform == PFFFT_REAL) + { + // take care of the fftpack ordering + ab[0] += a[0]*b[0]; + ab[2*Ncvec-1] += a[2*Ncvec-1]*b[2*Ncvec-1]; + ++ab; ++a; ++b; --Ncvec; + } + for(size_t i{0};i < Ncvec;++i) + { + float ar{a[2*i+0]}, ai{a[2*i+1]}; + const float br{b[2*i+0]}, bi{b[2*i+1]}; + VCPLXMUL(ar, ai, br, bi); + ab[2*i+0] += ar; + ab[2*i+1] += ai; + } +} + void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction) { diff --git a/common/pffft.h b/common/pffft.h index 3b402ca4..4bc3ebb6 100644 --- a/common/pffft.h +++ b/common/pffft.h @@ -152,8 +152,8 @@ void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *outp void pffft_zreorder(PFFFT_Setup *setup, const float *input, float *output, pffft_direction_t direction); /** - * Perform a multiplication of the z-domain data in dft_a and dft_b and - * accumulate them into dft_ab. The arrays should have been obtained with + * Perform a multiplication of the z-domain data in dft_a and dft_b, and scale + * and accumulate into dft_ab. The arrays should have been obtained with * pffft_transform(..., PFFFT_FORWARD) or pffft_zreorder(..., PFFFT_BACKWARD) * and should *not* be in the usual order (otherwise just perform the operation * yourself as the dft coeffs are stored as interleaved complex numbers). @@ -162,7 +162,17 @@ void pffft_zreorder(PFFFT_Setup *setup, const float *input, float *output, pffft * * The dft_a, dft_b, and dft_ab parameters may alias. */ -void pffft_zconvolve_accumulate(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab, float scaling); +void pffft_zconvolve_scale_accumulate(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab, float scaling); + +/** + * Perform a multiplication of the z-domain data in dft_a and dft_b, and + * accumulate into dft_ab. + * + * The operation performed is: dft_ab += dft_a * dft_b + * + * The dft_a, dft_b, and dft_ab parameters may alias. + */ +void pffft_zconvolve_accumulate(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab); /** * The float buffers must have the correct alignment (16-byte boundary on intel -- cgit v1.2.3 From 5d48351240ed29d28517de5ab3d7985c72e4b09b Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 11 Oct 2023 16:50:20 -0700 Subject: Attenuate the convolution filter instead of the filter result --- alc/effects/convolution.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'alc') diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index a98a0616..f3a7dbe3 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -410,13 +410,15 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag /* Convert to, and pack in, a float buffer for PFFFT. Note that the * first bin stores the real component of the half-frequency bin in - * the imaginary component. + * the imaginary component. Also scale the FFT by its length so the + * iFFT'd output will be normalized. */ + static constexpr float fftscale{1.0f / float{ConvolveUpdateSize}}; for(size_t i{0};i < ConvolveUpdateSamples;++i) { - ffttmp[i*2 ] = static_cast(fftbuffer[i].real()); + ffttmp[i*2 ] = static_cast(fftbuffer[i].real()) * fftscale; ffttmp[i*2 + 1] = static_cast((i == 0) ? - fftbuffer[ConvolveUpdateSamples+1].real() : fftbuffer[i].imag()); + fftbuffer[ConvolveUpdateSamples+1].real() : fftbuffer[i].imag()) * fftscale; } /* Reorder backward to make it suitable for pffft_zconvolve and the * subsequent pffft_transform(..., PFFFT_BACKWARD). @@ -553,7 +555,7 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot mOutTarget = target.Main->Buffer; if(device->mRenderMode == RenderMode::Pairwise) { - /* Scales the azimuth of the given vector by 3 if it's in front. + /* Scales the azimuth of the given vector by 2 if it's in front. * Effectively scales +/-45 degrees to +/-90 degrees, leaving > +90 * and < -90 alone. */ @@ -682,12 +684,9 @@ void ConvolutionState::process(const size_t samplesToDo, pffft_transform(mFft.get(), mFftBuffer.data(), mFftBuffer.data(), mFftWorkBuffer.data(), PFFFT_BACKWARD); - /* The iFFT'd response is scaled up by the number of bins, so apply - * the inverse to normalize the output. - */ - static constexpr float fftscale{1.0f / float{ConvolveUpdateSize}}; + /* The filter was attenuated, so the response is already scaled. */ for(size_t i{0};i < ConvolveUpdateSamples;++i) - mOutput[c][i] = (mFftBuffer[i]+mOutput[c][ConvolveUpdateSamples+i]) * fftscale; + mOutput[c][i] = mFftBuffer[i] + mOutput[c][ConvolveUpdateSamples+i]; for(size_t i{0};i < ConvolveUpdateSamples;++i) mOutput[c][ConvolveUpdateSamples+i] = mFftBuffer[ConvolveUpdateSamples+i]; } -- cgit v1.2.3 From 8dad679dd05a8bbd9efd6b4bd2f35fb902133d28 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Oct 2023 05:14:00 -0700 Subject: Add convolution effect properties to rotate ambisonic responses --- al/effects/convolution.cpp | 2 ++ alc/effects/convolution.cpp | 26 +++++++++++++++++++++++--- core/effects/base.h | 6 ++++++ 3 files changed, 31 insertions(+), 3 deletions(-) (limited to 'alc') diff --git a/al/effects/convolution.cpp b/al/effects/convolution.cpp index 8e850fd3..a9426ce4 100644 --- a/al/effects/convolution.cpp +++ b/al/effects/convolution.cpp @@ -83,6 +83,8 @@ void Convolution_getParamfv(const EffectProps *props, ALenum param, float *vals) EffectProps genDefaultProps() noexcept { EffectProps props{}; + props.Convolution.OrientAt = {0.0f, 0.0f, -1.0f}; + props.Convolution.OrientUp = {0.0f, 1.0f, 0.0f}; return props; } diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index f3a7dbe3..fe681745 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -431,7 +431,7 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot, - const EffectProps* /*props*/, const EffectTarget target) + const EffectProps *props, const EffectTarget target) { /* NOTE: Stereo and Rear are slightly different from normal mixing (as * defined in alu.cpp). These are 45 degrees from center, rather than the @@ -516,6 +516,23 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot } mOutTarget = target.Main->Buffer; + alu::Vector N{props->Convolution.OrientAt[0], props->Convolution.OrientAt[1], + props->Convolution.OrientAt[2], 0.0f}; + N.normalize(); + alu::Vector V{props->Convolution.OrientUp[0], props->Convolution.OrientUp[1], + props->Convolution.OrientUp[2], 0.0f}; + V.normalize(); + /* Build and normalize right-vector */ + alu::Vector U{N.cross_product(V)}; + U.normalize(); + + const float mixmatrix[4][4]{ + {1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, U[0], -U[1], U[2]}, + {0.0f, -V[0], V[1], -V[2]}, + {0.0f, -N[0], N[1], -N[2]}, + }; + const auto scales = GetAmbiScales(mAmbiScaling); const uint8_t *index_map{Is2DAmbisonic(mChannels) ? GetAmbi2DLayout(mAmbiLayout).data() : @@ -525,9 +542,12 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot for(size_t c{0u};c < mChans->size();++c) { const size_t acn{index_map[c]}; - coeffs[acn] = scales[acn]; + const float scale{scales[acn]}; + + for(size_t x{0};x < 4;++x) + coeffs[x] = mixmatrix[acn][x] * scale; + ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[c].Target); - coeffs[acn] = 0.0f; } } else diff --git a/core/effects/base.h b/core/effects/base.h index b02d33b7..83df7cf0 100644 --- a/core/effects/base.h +++ b/core/effects/base.h @@ -1,6 +1,7 @@ #ifndef CORE_EFFECTS_BASE_H #define CORE_EFFECTS_BASE_H +#include #include #include "almalloc.h" @@ -165,6 +166,11 @@ union EffectProps { struct { float Gain; } Dedicated; + + struct { + std::array OrientAt; + std::array OrientUp; + } Convolution; }; -- cgit v1.2.3 From d1acb001a5c4779d382838fb02660ba9aa10e4cc Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Oct 2023 06:28:12 -0700 Subject: Add an orientation property for convolution reverb Only affects ambisonic (B-Format and UHJ) formats --- al/effects/convolution.cpp | 30 ++++++++++++++++++++++++++---- alc/inprogext.h | 3 ++- 2 files changed, 28 insertions(+), 5 deletions(-) (limited to 'alc') diff --git a/al/effects/convolution.cpp b/al/effects/convolution.cpp index a9426ce4..494950b7 100644 --- a/al/effects/convolution.cpp +++ b/al/effects/convolution.cpp @@ -36,12 +36,25 @@ void Convolution_setParamf(EffectProps* /*props*/, ALenum param, float /*val*/) param}; } } -void Convolution_setParamfv(EffectProps *props, ALenum param, const float *vals) +void Convolution_setParamfv(EffectProps *props, ALenum param, const float *values) { switch(param) { + case AL_CONVOLUTION_REVERB_ORIENTATION_SOFT: + if(!(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]) + && std::isfinite(values[3]) && std::isfinite(values[4]) && std::isfinite(values[5]))) + throw effect_exception{AL_INVALID_VALUE, "Property 0x%04x value out of range", param}; + + props->Convolution.OrientAt[0] = values[0]; + props->Convolution.OrientAt[1] = values[1]; + props->Convolution.OrientAt[2] = values[2]; + props->Convolution.OrientUp[0] = values[3]; + props->Convolution.OrientUp[1] = values[4]; + props->Convolution.OrientUp[2] = values[5]; + break; + default: - Convolution_setParamf(props, param, vals[0]); + Convolution_setParamf(props, param, values[0]); } } @@ -71,12 +84,21 @@ void Convolution_getParamf(const EffectProps* /*props*/, ALenum param, float* /* param}; } } -void Convolution_getParamfv(const EffectProps *props, ALenum param, float *vals) +void Convolution_getParamfv(const EffectProps *props, ALenum param, float *values) { switch(param) { + case AL_CONVOLUTION_REVERB_ORIENTATION_SOFT: + values[0] = props->Convolution.OrientAt[0]; + values[1] = props->Convolution.OrientAt[1]; + values[2] = props->Convolution.OrientAt[2]; + values[3] = props->Convolution.OrientUp[0]; + values[4] = props->Convolution.OrientUp[1]; + values[5] = props->Convolution.OrientUp[2]; + break; + default: - Convolution_getParamf(props, param, vals); + Convolution_getParamf(props, param, values); } } diff --git a/alc/inprogext.h b/alc/inprogext.h index 2fa425bb..a595721d 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -44,7 +44,8 @@ void AL_APIENTRY alFlushMappedBufferDirectSOFT(ALCcontext *context, ALuint buffe #ifndef AL_SOFT_convolution_reverb #define AL_SOFT_convolution_reverb #define AL_EFFECT_CONVOLUTION_REVERB_SOFT 0xA000 -#define AL_EFFECTSLOT_STATE_SOFT 0x199D +#define AL_CONVOLUTION_REVERB_ORIENTATION_SOFT 0x100F /* same as AL_ORIENTATION */ +#define AL_EFFECTSLOT_STATE_SOFT 0x199E typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYSOFT)(ALuint slotid) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYVSOFT)(ALsizei n, const ALuint *slotids) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTSTOPSOFT)(ALuint slotid) AL_API_NOEXCEPT17; -- cgit v1.2.3 From 5b86b80591ce85869716885ca393e080f6f72685 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 12 Oct 2023 06:42:32 -0700 Subject: Rename the convolution reverb effect to just convolution While the common use case, convolution can do more than just reverb, and it nicely shortens the name. --- al/auxeffectslot.cpp | 2 +- al/effect.cpp | 4 ++-- al/effects/convolution.cpp | 4 ++-- alc/context.cpp | 2 +- alc/export_list.h | 2 +- alc/inprogext.h | 8 ++++---- examples/alconvolve.c | 32 ++++++++++++++++---------------- 7 files changed, 27 insertions(+), 27 deletions(-) (limited to 'alc') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 33252410..fb646389 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -230,7 +230,7 @@ EffectSlotType EffectSlotTypeFromEnum(ALenum type) case AL_EFFECT_EAXREVERB: return EffectSlotType::EAXReverb; case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT: return EffectSlotType::DedicatedLFE; case AL_EFFECT_DEDICATED_DIALOGUE: return EffectSlotType::DedicatedDialog; - case AL_EFFECT_CONVOLUTION_REVERB_SOFT: return EffectSlotType::Convolution; + case AL_EFFECT_CONVOLUTION_SOFT: return EffectSlotType::Convolution; } ERR("Unhandled effect enum: 0x%04x\n", type); return EffectSlotType::None; diff --git a/al/effect.cpp b/al/effect.cpp index c4b06407..3e48e91b 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -74,7 +74,7 @@ const EffectList gEffectList[16]{ { "vmorpher", VMORPHER_EFFECT, AL_EFFECT_VOCAL_MORPHER }, { "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT }, { "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_DIALOGUE }, - { "convolution", CONVOLUTION_EFFECT, AL_EFFECT_CONVOLUTION_REVERB_SOFT }, + { "convolution", CONVOLUTION_EFFECT, AL_EFFECT_CONVOLUTION_SOFT }, }; bool DisabledEffects[MAX_EFFECTS]; @@ -113,7 +113,7 @@ constexpr EffectPropsItem EffectPropsList[] = { { AL_EFFECT_VOCAL_MORPHER, VmorpherEffectProps, VmorpherEffectVtable }, { AL_EFFECT_DEDICATED_DIALOGUE, DedicatedEffectProps, DedicatedEffectVtable }, { AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, DedicatedEffectProps, DedicatedEffectVtable }, - { AL_EFFECT_CONVOLUTION_REVERB_SOFT, ConvolutionEffectProps, ConvolutionEffectVtable }, + { AL_EFFECT_CONVOLUTION_SOFT, ConvolutionEffectProps, ConvolutionEffectVtable }, }; diff --git a/al/effects/convolution.cpp b/al/effects/convolution.cpp index 494950b7..3e7885f8 100644 --- a/al/effects/convolution.cpp +++ b/al/effects/convolution.cpp @@ -40,7 +40,7 @@ void Convolution_setParamfv(EffectProps *props, ALenum param, const float *value { switch(param) { - case AL_CONVOLUTION_REVERB_ORIENTATION_SOFT: + case AL_CONVOLUTION_ORIENTATION_SOFT: if(!(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]) && std::isfinite(values[3]) && std::isfinite(values[4]) && std::isfinite(values[5]))) throw effect_exception{AL_INVALID_VALUE, "Property 0x%04x value out of range", param}; @@ -88,7 +88,7 @@ void Convolution_getParamfv(const EffectProps *props, ALenum param, float *value { switch(param) { - case AL_CONVOLUTION_REVERB_ORIENTATION_SOFT: + case AL_CONVOLUTION_ORIENTATION_SOFT: values[0] = props->Convolution.OrientAt[0]; values[1] = props->Convolution.OrientAt[1]; values[2] = props->Convolution.OrientAt[2]; diff --git a/alc/context.cpp b/alc/context.cpp index 8c930056..ffc2743e 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -75,7 +75,7 @@ std::vector getContextExtensions() noexcept "AL_SOFT_block_alignment", "AL_SOFT_buffer_length_query", "AL_SOFT_callback_buffer", - "AL_SOFTX_convolution_reverb", + "AL_SOFTX_convolution_effect", "AL_SOFT_deferred_updates", "AL_SOFT_direct_channels", "AL_SOFT_direct_channels_remix", diff --git a/alc/export_list.h b/alc/export_list.h index cefe7a09..2ef0d777 100644 --- a/alc/export_list.h +++ b/alc/export_list.h @@ -820,7 +820,7 @@ inline const EnumExport alcEnumerations[]{ DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT), - DECL(AL_EFFECT_CONVOLUTION_REVERB_SOFT), + DECL(AL_EFFECT_CONVOLUTION_SOFT), DECL(AL_EFFECTSLOT_STATE_SOFT), DECL(AL_FORMAT_UHJ2CHN8_SOFT), diff --git a/alc/inprogext.h b/alc/inprogext.h index a595721d..a145b8e4 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -41,10 +41,10 @@ void AL_APIENTRY alFlushMappedBufferDirectSOFT(ALCcontext *context, ALuint buffe #define AL_UNPACK_AMBISONIC_ORDER_SOFT 0x199D #endif -#ifndef AL_SOFT_convolution_reverb -#define AL_SOFT_convolution_reverb -#define AL_EFFECT_CONVOLUTION_REVERB_SOFT 0xA000 -#define AL_CONVOLUTION_REVERB_ORIENTATION_SOFT 0x100F /* same as AL_ORIENTATION */ +#ifndef AL_SOFT_convolution_effect +#define AL_SOFT_convolution_effect +#define AL_EFFECT_CONVOLUTION_SOFT 0xA000 +#define AL_CONVOLUTION_ORIENTATION_SOFT 0x100F /* same as AL_ORIENTATION */ #define AL_EFFECTSLOT_STATE_SOFT 0x199E typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYSOFT)(ALuint slotid) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYVSOFT)(ALsizei n, const ALuint *slotids) AL_API_NOEXCEPT17; diff --git a/examples/alconvolve.c b/examples/alconvolve.c index 94b978b5..8580d443 100644 --- a/examples/alconvolve.c +++ b/examples/alconvolve.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -/* This file contains an example for applying convolution reverb to a source. */ +/* This file contains an example for applying convolution to a source. */ #include #include @@ -39,9 +39,9 @@ #include "common/alhelpers.h" -#ifndef AL_SOFT_convolution_reverb -#define AL_SOFT_convolution_reverb -#define AL_EFFECT_CONVOLUTION_REVERB_SOFT 0xA000 +#ifndef AL_SOFT_convolution_effect +#define AL_SOFT_convolution_effect +#define AL_EFFECT_CONVOLUTION_SOFT 0xA000 #endif @@ -278,19 +278,19 @@ static int UpdatePlayer(StreamPlayer *player) } -/* CreateEffect creates a new OpenAL effect object with a convolution reverb - * type, and returns the new effect ID. +/* CreateEffect creates a new OpenAL effect object with a convolution type, and + * returns the new effect ID. */ static ALuint CreateEffect(void) { ALuint effect = 0; ALenum err; - printf("Using Convolution Reverb\n"); + printf("Using Convolution\n"); - /* Create the effect object and set the convolution reverb effect type. */ + /* Create the effect object and set the convolution effect type. */ alGenEffects(1, &effect); - alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_CONVOLUTION_REVERB_SOFT); + alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_CONVOLUTION_SOFT); /* Check if an error occurred, and clean up if so. */ err = alGetError(); @@ -423,10 +423,10 @@ int main(int argc, char **argv) if(InitAL(&argv, &argc) != 0) return 1; - if(!alIsExtensionPresent("AL_SOFTX_convolution_reverb")) + if(!alIsExtensionPresent("AL_SOFTX_convolution_effect")) { CloseAL(); - fprintf(stderr, "Error: Convolution revern not supported\n"); + fprintf(stderr, "Error: Convolution effect not supported\n"); return 1; } @@ -500,11 +500,11 @@ int main(int argc, char **argv) alGenAuxiliaryEffectSlots(1, &slot); /* Set the impulse response sound buffer on the effect slot. This allows - * effects to access it as needed. In this case, convolution reverb uses it - * as the filter source. NOTE: Unlike the effect object, the buffer *is* - * kept referenced and may not be changed or deleted as long as it's set, - * just like with a source. When another buffer is set, or the effect slot - * is deleted, the buffer reference is released. + * effects to access it as needed. In this case, convolution uses it as the + * filter source. NOTE: Unlike the effect object, the buffer *is* kept + * referenced and may not be changed or deleted as long as it's set, just + * like with a source. When another buffer is set, or the effect slot is + * deleted, the buffer reference is released. * * The effect slot's gain is reduced because the impulse responses I've * tested with result in excessively loud reverb. Is that normal? Even with -- cgit v1.2.3 From d3d23579add16fbe3c21f2b436457f398f0f5254 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 14 Oct 2023 10:56:37 -0700 Subject: Read the correct half-frequency bin --- alc/effects/convolution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index fe681745..ca356508 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -418,7 +418,7 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag { ffttmp[i*2 ] = static_cast(fftbuffer[i].real()) * fftscale; ffttmp[i*2 + 1] = static_cast((i == 0) ? - fftbuffer[ConvolveUpdateSamples+1].real() : fftbuffer[i].imag()) * fftscale; + fftbuffer[ConvolveUpdateSamples].real() : fftbuffer[i].imag()) * fftscale; } /* Reorder backward to make it suitable for pffft_zconvolve and the * subsequent pffft_transform(..., PFFFT_BACKWARD). -- cgit v1.2.3 From 5a72f300dcfa63c9b32f23ad3cf256b245ee0cd3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 14 Oct 2023 23:22:16 -0700 Subject: Avoid an extra copy to calculate the convolution FFT --- alc/effects/convolution.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'alc') diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index ca356508..271a4348 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -224,7 +224,7 @@ struct ConvolutionState final : public EffectState { uint mAmbiOrder{}; size_t mFifoPos{0}; - std::array mInput{}; + alignas(16) std::array mInput{}; al::vector,16> mFilter; al::vector,16> mOutput; @@ -665,14 +665,13 @@ void ConvolutionState::process(const size_t samplesToDo, /* Move the newest input to the front for the next iteration's history. */ std::copy(mInput.cbegin()+ConvolveUpdateSamples, mInput.cend(), mInput.begin()); + std::fill(mInput.begin()+ConvolveUpdateSamples, mInput.end(), 0.0f); - /* Calculate the frequency domain response and add the relevant + /* Calculate the frequency-domain response and add the relevant * frequency bins to the FFT history. */ - auto fftiter = std::copy_n(mInput.cbegin(), ConvolveUpdateSamples, mFftBuffer.begin()); - std::fill(fftiter, mFftBuffer.end(), 0.0f); - pffft_transform(mFft.get(), mFftBuffer.data(), - mComplexData.get() + curseg*ConvolveUpdateSize, mFftWorkBuffer.data(), PFFFT_FORWARD); + pffft_transform(mFft.get(), mInput.data(), mComplexData.get() + curseg*ConvolveUpdateSize, + mFftWorkBuffer.data(), PFFFT_FORWARD); const float *RESTRICT filter{mComplexData.get() + mNumConvolveSegs*ConvolveUpdateSize}; for(size_t c{0};c < chans.size();++c) -- cgit v1.2.3 From 5619de5ca05684656f32eafd8cfc987fb6161d97 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Oct 2023 00:22:24 -0700 Subject: Ensure some variables are the same And clean up some comments --- alc/effects/convolution.cpp | 42 +++++++++++++++++++++--------------------- core/uhjfilter.cpp | 45 +++++++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 41 deletions(-) (limited to 'alc') diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index 271a4348..06c34a37 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -41,21 +41,21 @@ namespace { -/* Convolution reverb is implemented using a segmented overlap-add method. The - * impulse response is broken up into multiple segments of 128 samples, and - * each segment has an FFT applied with a 256-sample buffer (the latter half - * left silent) to get its frequency-domain response. The resulting response - * has its positive/non-mirrored frequencies saved (129 bins) in each segment. - * Note that since the 0th and 129th bins are real for a real signal, their - * imaginary components are always 0 and can be dropped, allowing their real - * components to be combined so only 128 complex values are stored for the 129 - * bins. +/* Convolution is implemented using a segmented overlap-add method. The impulse + * response is split into multiple segments of 128 samples, and each segment + * has an FFT applied with a 256-sample buffer (the latter half left silent) to + * get its frequency-domain response. The resulting response has its positive/ + * non-mirrored frequencies saved (129 bins) in each segment. Note that since + * the 0- and half-frequency bins are real for a real signal, their imaginary + * components are always 0 and can be dropped, allowing their real components + * to be combined so only 128 complex values are stored for the 129 bins. * - * Input samples are similarly broken up into 128-sample segments, with an FFT - * applied to each new incoming segment to get its 129 bins. A history of FFT'd - * input segments is maintained, equal to the length of the impulse response. + * Input samples are similarly broken up into 128-sample segments, with a 256- + * sample FFT applied to each new incoming segment to get its 129 bins. A + * history of FFT'd input segments is maintained, equal to the number of + * impulse response segments. * - * To apply the reverberation, each impulse response segment is convolved with + * To apply the convolution, each impulse response segment is convolved with * its paired input segment (using complex multiplies, far cheaper than FIRs), * accumulating into a 129-bin FFT buffer. The input history is then shifted to * align with later impulse response segments for the next input segment. @@ -64,15 +64,15 @@ namespace { * sample time-domain response for output, which is split in two halves. The * first half is the 128-sample output, and the second half is a 128-sample * (really, 127) delayed extension, which gets added to the output next time. - * Convolving two time-domain responses of lengths N and M results in a time- - * domain signal of length N+M-1, and this holds true regardless of the - * convolution being applied in the frequency domain, so these "overflow" - * samples need to be accounted for. + * Convolving two time-domain responses of length N results in a time-domain + * signal of length N*2 - 1, and this holds true regardless of the convolution + * being applied in the frequency domain, so these "overflow" samples need to + * be accounted for. * - * To avoid a delay with gathering enough input samples to apply an FFT with, - * the first segment is applied directly in the time-domain as the samples come - * in. Once enough have been retrieved, the FFT is applied on the input and - * it's paired with the remaining (FFT'd) filter segments for processing. + * To avoid a delay with gathering enough input samples for the FFT, the first + * segment is applied directly in the time-domain as the samples come in. Once + * enough have been retrieved, the FFT is applied on the input and it's paired + * with the remaining (FFT'd) filter segments for processing. */ diff --git a/core/uhjfilter.cpp b/core/uhjfilter.cpp index 744054a7..d33e5079 100644 --- a/core/uhjfilter.cpp +++ b/core/uhjfilter.cpp @@ -29,10 +29,10 @@ using PFFFTSetupPtr = std::unique_ptr; * segment has an FFT applied with a 256-sample buffer (the latter half left * silent) to get its frequency-domain response. * - * Input samples are similarly broken up into 128-sample segments, with an FFT - * applied with a 256-sample buffer to each new incoming segment to get its - * frequency-domain response. A history of FFT'd input segments is maintained, - * equal to the number of filter response segments. + * Input samples are similarly broken up into 128-sample segments, with a 256- + * sample FFT applied to each new incoming segment to get its frequency-domain + * response. A history of FFT'd input segments is maintained, equal to the + * number of filter response segments. * * To apply the convolution, each filter response segment is convolved with its * paired input segment (using complex multiplies, far cheaper than time-domain @@ -82,6 +82,10 @@ struct SplitFilter { /* Convert to the frequency domain, shift the phase of each bin by +90 * degrees, then convert back to the time domain. + * + * NOTE: The 0- and half-frequency are always real for a real signal. + * To maintain that and their phase (0 or pi), they're heavily + * attenuated instead of shifted like the others. */ forward_fft(al::span{fftBuffer.get(), fft_size}); fftBuffer[0] *= std::numeric_limits::epsilon(); @@ -204,6 +208,7 @@ void UhjEncoder::encode(float *LeftOut, float *RightOut, { static constexpr auto &Filter = gSplitFilter; static_assert(sFftLength == Filter.sFftLength); + static_assert(sSegmentSize == Filter.sSampleLength); static_assert(sNumSegments == Filter.sNumSegments); ASSUME(SamplesToDo > 0); @@ -223,13 +228,13 @@ void UhjEncoder::encode(float *LeftOut, float *RightOut, /* Precompute j(-0.3420201*W + 0.5098604*X) and store in mD. */ for(size_t base{0};base < SamplesToDo;) { - const size_t todo{minz(Filter.sSampleLength-mFifoPos, SamplesToDo-base)}; + const size_t todo{minz(sSegmentSize-mFifoPos, SamplesToDo-base)}; /* Transform the non-delayed input and store in the later half of the * filter input. */ std::transform(winput+base, winput+base+todo, xinput+base, - mWXIn.begin()+Filter.sSampleLength + mFifoPos, + mWXIn.begin()+sSegmentSize + mFifoPos, [](const float w, const float x) noexcept -> float { return -0.3420201f*w + 0.5098604f*x; }); @@ -247,36 +252,36 @@ void UhjEncoder::encode(float *LeftOut, float *RightOut, base += todo; /* Check whether the input buffer is filled with new samples. */ - if(mFifoPos < Filter.sSampleLength) break; + if(mFifoPos < sSegmentSize) break; mFifoPos = 0; /* Move the newest input to the front for the next iteration's history. */ - std::copy(mWXIn.cbegin()+Filter.sSampleLength, mWXIn.cend(), mWXIn.begin()); - std::fill(mWXIn.begin()+Filter.sSampleLength, mWXIn.end(), 0.0f); + std::copy(mWXIn.cbegin()+sSegmentSize, mWXIn.cend(), mWXIn.begin()); + std::fill(mWXIn.begin()+sSegmentSize, mWXIn.end(), 0.0f); /* Overwrite the stale/oldest FFT'd segment with the newest input. */ const size_t curseg{mCurrentSegment}; - pffft_transform(Filter.mFft.get(), mWXIn.data(), - mWXHistory.data() + curseg*Filter.sFftLength, mWorkData.data(), PFFFT_FORWARD); + pffft_transform(Filter.mFft.get(), mWXIn.data(), mWXHistory.data() + curseg*sFftLength, + mWorkData.data(), PFFFT_FORWARD); /* Convolve each input segment with its IR filter counterpart (aligned * in time). */ mFftBuffer.fill(0.0f); const float *filter{Filter.mFilterData.data()}; - const float *input{mWXHistory.data() + curseg*Filter.sFftLength}; + const float *input{mWXHistory.data() + curseg*sFftLength}; for(size_t s{curseg};s < sNumSegments;++s) { pffft_zconvolve_accumulate(Filter.mFft.get(), input, filter, mFftBuffer.data()); - input += Filter.sFftLength; - filter += Filter.sFftLength; + input += sFftLength; + filter += sFftLength; } input = mWXHistory.data(); for(size_t s{0};s < curseg;++s) { pffft_zconvolve_accumulate(Filter.mFft.get(), input, filter, mFftBuffer.data()); - input += Filter.sFftLength; - filter += Filter.sFftLength; + input += sFftLength; + filter += sFftLength; } /* Convert back to samples, writing to the output and storing the extra @@ -285,10 +290,10 @@ void UhjEncoder::encode(float *LeftOut, float *RightOut, pffft_transform(Filter.mFft.get(), mFftBuffer.data(), mFftBuffer.data(), mWorkData.data(), PFFFT_BACKWARD); - for(size_t i{0};i < Filter.sSampleLength;++i) - mWXOut[i] = mFftBuffer[i] + mWXOut[Filter.sSampleLength+i]; - for(size_t i{0};i < Filter.sSampleLength;++i) - mWXOut[Filter.sSampleLength+i] = mFftBuffer[Filter.sSampleLength+i]; + for(size_t i{0};i < sSegmentSize;++i) + mWXOut[i] = mFftBuffer[i] + mWXOut[sSegmentSize+i]; + for(size_t i{0};i < sSegmentSize;++i) + mWXOut[sSegmentSize+i] = mFftBuffer[sSegmentSize+i]; /* Shift the input history. */ mCurrentSegment = curseg ? (curseg-1) : (sNumSegments-1); -- cgit v1.2.3 From bfee94dfec64dd22ad8d985e71803fbe411f7a1a Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Oct 2023 02:38:20 -0700 Subject: Use a span for a known array length instead of a raw pointer --- alc/alu.cpp | 28 ++++++++++++++-------------- alc/effects/chorus.cpp | 4 ++-- alc/effects/convolution.cpp | 6 +++--- alc/effects/dedicated.cpp | 2 +- alc/effects/distortion.cpp | 2 +- alc/effects/echo.cpp | 4 ++-- alc/effects/fshifter.cpp | 4 ++-- alc/effects/pshifter.cpp | 2 +- alc/effects/reverb.cpp | 8 ++++---- core/mixer.cpp | 7 +++---- core/mixer.h | 4 ++-- 11 files changed, 35 insertions(+), 36 deletions(-) (limited to 'alc') diff --git a/alc/alu.cpp b/alc/alu.cpp index 1585b8f2..7aefcfb5 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -929,12 +929,12 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con if(!(coverage > 0.0f)) { - ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base*scales[0], + ComputePanGains(&Device->Dry, coeffs, DryGain.Base*scales[0], voice->mChans[0].mDryParams.Gains.Target); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base*scales[0], + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base*scales[0], voice->mChans[0].mWetParams[i].Gains.Target); } } @@ -1038,13 +1038,13 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con for(size_t x{0};x < MaxAmbiChannels;++x) coeffs[x] += mixmatrix[acn][x] * scale; - ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, + ComputePanGains(&Device->Dry, coeffs, DryGain.Base, voice->mChans[c].mDryParams.Gains.Target); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } @@ -1097,7 +1097,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } } @@ -1125,7 +1125,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base, voice->mChans[0].mWetParams[i].Gains.Target); } } @@ -1166,7 +1166,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } } @@ -1206,7 +1206,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } } @@ -1247,12 +1247,12 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con }; const auto coeffs = calc_coeffs(Device->mRenderMode); - ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, + ComputePanGains(&Device->Dry, coeffs, DryGain.Base, voice->mChans[0].mDryParams.Gains.Target); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base, voice->mChans[0].mWetParams[i].Gains.Target); } } @@ -1296,12 +1296,12 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con pos = ScaleAzimuthFront3(pos); const auto coeffs = CalcDirectionCoeffs(pos, 0.0f); - ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, + ComputePanGains(&Device->Dry, coeffs, DryGain.Base, voice->mChans[c].mDryParams.Gains.Target); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } } @@ -1343,12 +1343,12 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con const auto coeffs = CalcDirectionCoeffs((Device->mRenderMode==RenderMode::Pairwise) ? ScaleAzimuthFront3(chans[c].pos) : chans[c].pos, spread); - ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, + ComputePanGains(&Device->Dry, coeffs, DryGain.Base, voice->mChans[c].mDryParams.Gains.Target); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } } diff --git a/alc/effects/chorus.cpp b/alc/effects/chorus.cpp index c84531d4..9cbc922f 100644 --- a/alc/effects/chorus.cpp +++ b/alc/effects/chorus.cpp @@ -133,8 +133,8 @@ void ChorusState::update(const ContextBase *Context, const EffectSlot *Slot, auto &rcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? rcoeffs_nrml : rcoeffs_pw; mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, lcoeffs.data(), Slot->Gain, mGains[0].Target); - ComputePanGains(target.Main, rcoeffs.data(), Slot->Gain, mGains[1].Target); + ComputePanGains(target.Main, lcoeffs, Slot->Gain, mGains[0].Target); + ComputePanGains(target.Main, rcoeffs, Slot->Gain, mGains[1].Target); float rate{props->Chorus.Rate}; if(!(rate > 0.0f)) diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index 06c34a37..5d1a6500 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -547,7 +547,7 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot for(size_t x{0};x < 4;++x) coeffs[x] = mixmatrix[acn][x] * scale; - ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[c].Target); + ComputePanGains(target.Main, coeffs, gain, (*mChans)[c].Target); } } else @@ -616,14 +616,14 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot { if(chanmap[i].channel == LFE) continue; const auto coeffs = CalcDirectionCoeffs(ScaleAzimuthFront(chanmap[i].pos), 0.0f); - ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[i].Target); + ComputePanGains(target.Main, coeffs, gain, (*mChans)[i].Target); } } else for(size_t i{0};i < chanmap.size();++i) { if(chanmap[i].channel == LFE) continue; const auto coeffs = CalcDirectionCoeffs(chanmap[i].pos, 0.0f); - ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[i].Target); + ComputePanGains(target.Main, coeffs, gain, (*mChans)[i].Target); } } } diff --git a/alc/effects/dedicated.cpp b/alc/effects/dedicated.cpp index e82b13d9..9ac68bec 100644 --- a/alc/effects/dedicated.cpp +++ b/alc/effects/dedicated.cpp @@ -97,7 +97,7 @@ void DedicatedState::update(const ContextBase*, const EffectSlot *slot, static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f}); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, coeffs.data(), Gain, mTargetGains); + ComputePanGains(target.Main, coeffs, Gain, mTargetGains); } } } diff --git a/alc/effects/distortion.cpp b/alc/effects/distortion.cpp index 392d81c8..3d77ff35 100644 --- a/alc/effects/distortion.cpp +++ b/alc/effects/distortion.cpp @@ -98,7 +98,7 @@ void DistortionState::update(const ContextBase *context, const EffectSlot *slot, static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f}); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, coeffs.data(), slot->Gain*props->Distortion.Gain, mGain); + ComputePanGains(target.Main, coeffs, slot->Gain*props->Distortion.Gain, mGain); } void DistortionState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) diff --git a/alc/effects/echo.cpp b/alc/effects/echo.cpp index 7824c246..714649c9 100644 --- a/alc/effects/echo.cpp +++ b/alc/effects/echo.cpp @@ -118,8 +118,8 @@ void EchoState::update(const ContextBase *context, const EffectSlot *slot, const auto coeffs1 = CalcAngleCoeffs( angle, 0.0f, 0.0f); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, coeffs0.data(), slot->Gain, mGains[0].Target); - ComputePanGains(target.Main, coeffs1.data(), slot->Gain, mGains[1].Target); + ComputePanGains(target.Main, coeffs0, slot->Gain, mGains[0].Target); + ComputePanGains(target.Main, coeffs1, slot->Gain, mGains[1].Target); } void EchoState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) diff --git a/alc/effects/fshifter.cpp b/alc/effects/fshifter.cpp index ec0cc29f..d3989e84 100644 --- a/alc/effects/fshifter.cpp +++ b/alc/effects/fshifter.cpp @@ -172,8 +172,8 @@ void FshifterState::update(const ContextBase *context, const EffectSlot *slot, auto &rcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? rcoeffs_nrml : rcoeffs_pw; mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, lcoeffs.data(), slot->Gain, mGains[0].Target); - ComputePanGains(target.Main, rcoeffs.data(), slot->Gain, mGains[1].Target); + ComputePanGains(target.Main, lcoeffs, slot->Gain, mGains[0].Target); + ComputePanGains(target.Main, rcoeffs, slot->Gain, mGains[1].Target); } void FshifterState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) diff --git a/alc/effects/pshifter.cpp b/alc/effects/pshifter.cpp index 2460cf78..95269009 100644 --- a/alc/effects/pshifter.cpp +++ b/alc/effects/pshifter.cpp @@ -145,7 +145,7 @@ void PshifterState::update(const ContextBase*, const EffectSlot *slot, static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f}); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, coeffs.data(), slot->Gain, mTargetGains); + ComputePanGains(target.Main, coeffs, slot->Gain, mTargetGains); } void PshifterState::process(const size_t samplesToDo, diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index b00f638b..9727f400 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -1108,9 +1108,9 @@ void ReverbPipeline::update3DPanning(const al::span ReflectionsPa auto latecoeffs = mult_matrix(latemat); for(size_t i{0u};i < NUM_LINES;i++) - ComputePanGains(mainMix, earlycoeffs[i].data(), earlyGain, mEarly.TargetGains[i]); + ComputePanGains(mainMix, earlycoeffs[i], earlyGain, mEarly.TargetGains[i]); for(size_t i{0u};i < NUM_LINES;i++) - ComputePanGains(mainMix, latecoeffs[i].data(), lateGain, mLate.TargetGains[i]); + ComputePanGains(mainMix, latecoeffs[i], lateGain, mLate.TargetGains[i]); } else { @@ -1140,9 +1140,9 @@ void ReverbPipeline::update3DPanning(const al::span ReflectionsPa auto latecoeffs = mult_matrix(LateA2B, latemat); for(size_t i{0u};i < NUM_LINES;i++) - ComputePanGains(mainMix, earlycoeffs[i].data(), earlyGain, mEarly.TargetGains[i]); + ComputePanGains(mainMix, earlycoeffs[i], earlyGain, mEarly.TargetGains[i]); for(size_t i{0u};i < NUM_LINES;i++) - ComputePanGains(mainMix, latecoeffs[i].data(), lateGain, mLate.TargetGains[i]); + ComputePanGains(mainMix, latecoeffs[i], lateGain, mLate.TargetGains[i]); } } diff --git a/core/mixer.cpp b/core/mixer.cpp index 066c57bd..806ac8b8 100644 --- a/core/mixer.cpp +++ b/core/mixer.cpp @@ -82,14 +82,13 @@ std::array CalcAmbiCoeffs(const float y, const float z, c return coeffs; } -void ComputePanGains(const MixParams *mix, const float*RESTRICT coeffs, const float ingain, - const al::span gains) +void ComputePanGains(const MixParams *mix, const al::span coeffs, + const float ingain, const al::span gains) { auto ambimap = mix->AmbiMap.cbegin(); auto iter = std::transform(ambimap, ambimap+mix->Buffer.size(), gains.begin(), [coeffs,ingain](const BFChannelConfig &chanmap) noexcept -> float - { return chanmap.Scale * coeffs[chanmap.Index] * ingain; } - ); + { return chanmap.Scale * coeffs[chanmap.Index] * ingain; }); std::fill(iter, gains.end(), 0.0f); } diff --git a/core/mixer.h b/core/mixer.h index a9c1f931..9062ebac 100644 --- a/core/mixer.h +++ b/core/mixer.h @@ -103,7 +103,7 @@ inline std::array CalcAngleCoeffs(const float azimuth, * coeffs are a 'slice' of a transform matrix for the input channel, used to * scale and orient the sound samples. */ -void ComputePanGains(const MixParams *mix, const float*RESTRICT coeffs, const float ingain, - const al::span gains); +void ComputePanGains(const MixParams *mix, const al::span coeffs, + const float ingain, const al::span gains); #endif /* CORE_MIXER_H */ -- cgit v1.2.3 From 4c356cb2b10f5fb05e1917ef4c5cba756c6c35c9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Oct 2023 03:25:32 -0700 Subject: Use the same stereo angles in convolution as normal mixing --- alc/effects/convolution.cpp | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) (limited to 'alc') diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index 5d1a6500..ca5337b4 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -433,22 +433,18 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot, const EffectProps *props, const EffectTarget target) { - /* NOTE: Stereo and Rear are slightly different from normal mixing (as - * defined in alu.cpp). These are 45 degrees from center, rather than the - * 30 degrees used there. - * - * TODO: LFE is not mixed to output. This will require each buffer channel + /* TODO: LFE is not mixed to output. This will require each buffer channel * to have its own output target since the main mixing buffer won't have an * LFE channel (due to being B-Format). */ static constexpr ChanPosMap MonoMap[1]{ { FrontCenter, std::array{0.0f, 0.0f, -1.0f} } }, StereoMap[2]{ - { FrontLeft, std::array{-sin45, 0.0f, -cos45} }, - { FrontRight, std::array{ sin45, 0.0f, -cos45} }, + { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, + { FrontRight, std::array{ sin30, 0.0f, -cos30} }, }, RearMap[2]{ - { BackLeft, std::array{-sin45, 0.0f, cos45} }, - { BackRight, std::array{ sin45, 0.0f, cos45} }, + { BackLeft, std::array{-sin30, 0.0f, cos30} }, + { BackRight, std::array{ sin30, 0.0f, cos30} }, }, QuadMap[4]{ { FrontLeft, std::array{-sin45, 0.0f, -cos45} }, { FrontRight, std::array{ sin45, 0.0f, -cos45} }, @@ -575,8 +571,8 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot mOutTarget = target.Main->Buffer; if(device->mRenderMode == RenderMode::Pairwise) { - /* Scales the azimuth of the given vector by 2 if it's in front. - * Effectively scales +/-45 degrees to +/-90 degrees, leaving > +90 + /* Scales the azimuth of the given vector by 3 if it's in front. + * Effectively scales +/-30 degrees to +/-90 degrees, leaving > +90 * and < -90 alone. */ auto ScaleAzimuthFront = [](std::array pos) -> std::array @@ -591,20 +587,20 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot float x{pos[0] / len2d}; float z{-pos[2] / len2d}; - /* Z > cos(pi/4) = -45 < azimuth < 45 degrees. */ - if(z > cos45) + /* Z > cos(pi/6) = -30 < azimuth < 30 degrees. */ + if(z > cos30) { - /* Double the angle represented by x,z. */ - const float resx{2.0f*x * z}; - const float resz{z*z - x*x}; + /* Triple the angle represented by x,z. */ + x = x*3.0f - x*x*x*4.0f; + z = z*z*z*4.0f - z*3.0f; /* Scale the vector back to fit in 3D. */ - pos[0] = resx * len2d; - pos[2] = -resz * len2d; + pos[0] = x * len2d; + pos[2] = -z * len2d; } else { - /* If azimuth >= 45 degrees, clamp to 90 degrees. */ + /* If azimuth >= 30 degrees, clamp to 90 degrees. */ pos[0] = std::copysign(len2d, pos[0]); pos[2] = 0.0f; } -- cgit v1.2.3 From af4f92c3a235c6f99ee9a46399dee976e70e9d4f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Oct 2023 12:18:06 -0700 Subject: Avoid some unique and wrapper types --- alc/effects/convolution.cpp | 91 ++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 58 deletions(-) (limited to 'alc') diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index ca5337b4..5c0b2677 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -189,28 +189,6 @@ void apply_fir(al::span dst, const float *RESTRICT src, const float *REST } -template -struct AlignedDeleter { }; - -template -struct AlignedDeleter { - static_assert(std::is_trivially_destructible_v); - using type = T; - - void operator()(T *ptr) { al_free(ptr); } -}; -template -using AlignedUPtr = std::unique_ptr>; - -template -auto MakeAlignedPtr(size_t count) -> AlignedUPtr -{ - using Type = typename AlignedDeleter::type; - void *ptr{al_calloc(A, sizeof(Type)*count)}; - return AlignedUPtr{::new(ptr) Type[count]}; -} - - struct PFFFTSetupDeleter { void operator()(PFFFT_Setup *ptr) { pffft_destroy_setup(ptr); } }; @@ -242,9 +220,8 @@ struct ConvolutionState final : public EffectState { float Current[MAX_OUTPUT_CHANNELS]{}; float Target[MAX_OUTPUT_CHANNELS]{}; }; - using ChannelDataArray = al::FlexArray; - std::unique_ptr mChans; - AlignedUPtr mComplexData; + std::vector mChans; + al::vector mComplexData; ConvolutionState() = default; @@ -267,7 +244,7 @@ struct ConvolutionState final : public EffectState { void ConvolutionState::NormalMix(const al::span samplesOut, const size_t samplesToDo) { - for(auto &chan : *mChans) + for(auto &chan : mChans) MixSamples({chan.mBuffer.data(), samplesToDo}, samplesOut, chan.Current, chan.Target, samplesToDo, 0); } @@ -275,7 +252,7 @@ void ConvolutionState::NormalMix(const al::span samplesOut, void ConvolutionState::UpsampleMix(const al::span samplesOut, const size_t samplesToDo) { - for(auto &chan : *mChans) + for(auto &chan : mChans) { const al::span src{chan.mBuffer.data(), samplesToDo}; chan.mFilter.processScale(src, chan.mHfScale, chan.mLfScale); @@ -304,8 +281,8 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag mCurrentSegment = 0; mNumConvolveSegs = 0; - mChans = nullptr; - mComplexData = nullptr; + decltype(mChans){}.swap(mChans); + decltype(mComplexData){}.swap(mComplexData); /* An empty buffer doesn't need a convolution filter. */ if(!buffer || buffer->mSampleLen < 1) return; @@ -319,7 +296,7 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag const auto realChannels = buffer->channelsFromFmt(); const auto numChannels = (mChannels == FmtUHJ2) ? 3u : ChannelsFromFmt(mChannels, mAmbiOrder); - mChans = ChannelDataArray::Create(numChannels); + mChans.resize(numChannels); /* The impulse response needs to have the same sample rate as the input and * output. The bsinc24 resampler is decent, but there is high-frequency @@ -334,7 +311,7 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag buffer->mSampleRate); const BandSplitter splitter{device->mXOverFreq / static_cast(device->Frequency)}; - for(auto &e : *mChans) + for(auto &e : mChans) e.mFilter = splitter; mFilter.resize(numChannels, {}); @@ -349,8 +326,7 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag mNumConvolveSegs = maxz(mNumConvolveSegs, 2) - 1; const size_t complex_length{mNumConvolveSegs * ConvolveUpdateSize * (numChannels+1)}; - mComplexData = MakeAlignedPtr(complex_length); - std::fill_n(mComplexData.get(), complex_length, 0.0f); + mComplexData.resize(complex_length, 0.0f); /* Load the samples from the buffer. */ const size_t srclinelength{RoundUp(buffer->mSampleLen+DecoderPadding, 16)}; @@ -374,7 +350,7 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag auto ffttmp = al::vector(ConvolveUpdateSize); auto fftbuffer = std::vector>(ConvolveUpdateSize); - float *filteriter = mComplexData.get() + mNumConvolveSegs*ConvolveUpdateSize; + float *filteriter = mComplexData.data() + mNumConvolveSegs*ConvolveUpdateSize; for(size_t c{0};c < numChannels;++c) { /* Resample to match the device. */ @@ -481,7 +457,7 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot mMix = &ConvolutionState::NormalMix; - for(auto &chan : *mChans) + for(auto &chan : mChans) std::fill(std::begin(chan.Target), std::end(chan.Target), 0.0f); const float gain{slot->Gain}; if(IsAmbisonic(mChannels)) @@ -490,24 +466,24 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot if(mChannels == FmtUHJ2 && !device->mUhjEncoder) { mMix = &ConvolutionState::UpsampleMix; - (*mChans)[0].mHfScale = 1.0f; - (*mChans)[0].mLfScale = DecoderBase::sWLFScale; - (*mChans)[1].mHfScale = 1.0f; - (*mChans)[1].mLfScale = DecoderBase::sXYLFScale; - (*mChans)[2].mHfScale = 1.0f; - (*mChans)[2].mLfScale = DecoderBase::sXYLFScale; + mChans[0].mHfScale = 1.0f; + mChans[0].mLfScale = DecoderBase::sWLFScale; + mChans[1].mHfScale = 1.0f; + mChans[1].mLfScale = DecoderBase::sXYLFScale; + mChans[2].mHfScale = 1.0f; + mChans[2].mLfScale = DecoderBase::sXYLFScale; } else if(device->mAmbiOrder > mAmbiOrder) { mMix = &ConvolutionState::UpsampleMix; const auto scales = AmbiScale::GetHFOrderScales(mAmbiOrder, device->mAmbiOrder, device->m2DMixing); - (*mChans)[0].mHfScale = scales[0]; - (*mChans)[0].mLfScale = 1.0f; - for(size_t i{1};i < mChans->size();++i) + mChans[0].mHfScale = scales[0]; + mChans[0].mLfScale = 1.0f; + for(size_t i{1};i < mChans.size();++i) { - (*mChans)[i].mHfScale = scales[1]; - (*mChans)[i].mLfScale = 1.0f; + mChans[i].mHfScale = scales[1]; + mChans[i].mLfScale = 1.0f; } } mOutTarget = target.Main->Buffer; @@ -535,7 +511,7 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot GetAmbiLayout(mAmbiLayout).data()}; std::array coeffs{}; - for(size_t c{0u};c < mChans->size();++c) + for(size_t c{0u};c < mChans.size();++c) { const size_t acn{index_map[c]}; const float scale{scales[acn]}; @@ -543,7 +519,7 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot for(size_t x{0};x < 4;++x) coeffs[x] = mixmatrix[acn][x] * scale; - ComputePanGains(target.Main, coeffs, gain, (*mChans)[c].Target); + ComputePanGains(target.Main, coeffs, gain, mChans[c].Target); } } else @@ -612,14 +588,14 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot { if(chanmap[i].channel == LFE) continue; const auto coeffs = CalcDirectionCoeffs(ScaleAzimuthFront(chanmap[i].pos), 0.0f); - ComputePanGains(target.Main, coeffs, gain, (*mChans)[i].Target); + ComputePanGains(target.Main, coeffs, gain, mChans[i].Target); } } else for(size_t i{0};i < chanmap.size();++i) { if(chanmap[i].channel == LFE) continue; const auto coeffs = CalcDirectionCoeffs(chanmap[i].pos, 0.0f); - ComputePanGains(target.Main, coeffs, gain, (*mChans)[i].Target); + ComputePanGains(target.Main, coeffs, gain, mChans[i].Target); } } } @@ -631,7 +607,6 @@ void ConvolutionState::process(const size_t samplesToDo, return; size_t curseg{mCurrentSegment}; - auto &chans = *mChans; for(size_t base{0u};base < samplesToDo;) { @@ -643,9 +618,9 @@ void ConvolutionState::process(const size_t samplesToDo, /* Apply the FIR for the newly retrieved input samples, and combine it * with the inverse FFT'd output samples. */ - for(size_t c{0};c < chans.size();++c) + for(size_t c{0};c < mChans.size();++c) { - auto buf_iter = chans[c].mBuffer.begin() + base; + auto buf_iter = mChans[c].mBuffer.begin() + base; apply_fir({buf_iter, todo}, mInput.data()+1 + mFifoPos, mFilter[c].data()); auto fifo_iter = mOutput[c].begin() + mFifoPos; @@ -666,24 +641,24 @@ void ConvolutionState::process(const size_t samplesToDo, /* Calculate the frequency-domain response and add the relevant * frequency bins to the FFT history. */ - pffft_transform(mFft.get(), mInput.data(), mComplexData.get() + curseg*ConvolveUpdateSize, + pffft_transform(mFft.get(), mInput.data(), mComplexData.data() + curseg*ConvolveUpdateSize, mFftWorkBuffer.data(), PFFFT_FORWARD); - const float *RESTRICT filter{mComplexData.get() + mNumConvolveSegs*ConvolveUpdateSize}; - for(size_t c{0};c < chans.size();++c) + const float *filter{mComplexData.data() + mNumConvolveSegs*ConvolveUpdateSize}; + for(size_t c{0};c < mChans.size();++c) { /* Convolve each input segment with its IR filter counterpart * (aligned in time). */ mFftBuffer.fill(0.0f); - const float *RESTRICT input{&mComplexData[curseg*ConvolveUpdateSize]}; + const float *input{&mComplexData[curseg*ConvolveUpdateSize]}; for(size_t s{curseg};s < mNumConvolveSegs;++s) { pffft_zconvolve_accumulate(mFft.get(), input, filter, mFftBuffer.data()); input += ConvolveUpdateSize; filter += ConvolveUpdateSize; } - input = mComplexData.get(); + input = mComplexData.data(); for(size_t s{0};s < curseg;++s) { pffft_zconvolve_accumulate(mFft.get(), input, filter, mFftBuffer.data()); -- cgit v1.2.3 From f15749e7dadbb2d6050c037da9ccd97e8f4dc31c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 19 Oct 2023 19:29:14 -0700 Subject: Don't log failed config option lookups --- alc/alconfig.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'alc') diff --git a/alc/alconfig.cpp b/alc/alconfig.cpp index 097ba3a0..cfa178fb 100644 --- a/alc/alconfig.cpp +++ b/alc/alconfig.cpp @@ -265,7 +265,7 @@ void LoadConfigFromFile(std::istream &f) } } - TRACE(" found '%s' = '%s'\n", fullKey.c_str(), value.c_str()); + TRACE(" setting '%s' = '%s'\n", fullKey.c_str(), value.c_str()); /* Check if we already have this option set */ auto find_key = [&fullKey](const ConfigEntry &entry) -> bool @@ -316,17 +316,14 @@ const char *GetConfigValue(const char *devName, const char *blockName, const cha { return entry.key == key; }); if(iter != ConfOpts.cend()) { - TRACE("Found %s = \"%s\"\n", key.c_str(), iter->value.c_str()); + TRACE("Found option %s = \"%s\"\n", key.c_str(), iter->value.c_str()); if(!iter->value.empty()) return iter->value.c_str(); return nullptr; } if(!devName) - { - TRACE("Key %s not found\n", key.c_str()); return nullptr; - } return GetConfigValue(nullptr, blockName, keyName); } -- cgit v1.2.3 From 72836ed69b6eed93a802ef86a97b628bb464fa56 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 20 Oct 2023 09:35:56 -0700 Subject: Remove an outdated comment --- alc/effects/reverb.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'alc') diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index 9727f400..0e63c7bc 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -1360,9 +1360,6 @@ void VectorScatterRevDelayIn(const DelayLineI delay, size_t offset, const float * It works by vectorizing a regular all-pass filter and replacing the delay * element with a scattering matrix (like the one above) and a diagonal * matrix of delay elements. - * - * Two static specializations are used for transitional (cross-faded) delay - * line processing and non-transitional processing. */ void VecAllpass::process(const al::span samples, size_t offset, const float xCoeff, const float yCoeff, const size_t todo) -- cgit v1.2.3 From b8645438006de7e0a19ec4abe1c3314fec97c209 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Oct 2023 21:03:44 -0700 Subject: Use a dynamically resizing spa_pod_builder Rather than relying on a fixed-size buffer --- alc/backends/pipewire.cpp | 61 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 14 deletions(-) (limited to 'alc') diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 1c4e2cc4..6cfb31a4 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -109,12 +109,12 @@ template constexpr auto get_pod_body(const spa_pod *pod) noexcept { return al::span{static_cast(SPA_POD_BODY(pod)), N}; } -constexpr auto make_pod_builder(void *data, uint32_t size) noexcept -{ return SPA_POD_BUILDER_INIT(data, size); } - constexpr auto get_array_value_type(const spa_pod *pod) noexcept { return SPA_POD_ARRAY_VALUE_TYPE(pod); } +constexpr auto make_pod_builder(void *data, uint32_t size) noexcept +{ return SPA_POD_BUILDER_INIT(data, size); } + constexpr auto PwIdAny = PW_ID_ANY; } // namespace @@ -122,6 +122,44 @@ _Pragma("GCC diagnostic pop") namespace { +struct PodDynamicBuilder { +private: + std::vector mStorage; + spa_pod_builder mPod{}; + + int overflow(uint32_t size) noexcept + { + try { + mStorage.resize(size); + } + catch(...) { + ERR("Failed to resize POD storage\n"); + return -ENOMEM; + } + mPod.data = mStorage.data(); + mPod.size = size; + return 0; + } + +public: + PodDynamicBuilder(uint32_t initSize=0) : mStorage(initSize) + , mPod{make_pod_builder(mStorage.data(), initSize)} + { + static constexpr auto callbacks{[] + { + spa_pod_builder_callbacks cb{}; + cb.version = SPA_VERSION_POD_BUILDER_CALLBACKS; + cb.overflow = [](void *data, uint32_t size) noexcept + { return static_cast(data)->overflow(size); }; + return cb; + }()}; + + spa_pod_builder_set_callbacks(&mPod, &callbacks, this); + } + + spa_pod_builder *get() noexcept { return &mPod; } +}; + /* Added in 0.3.33, but we currently only require 0.3.23. */ #ifndef PW_KEY_NODE_RATE #define PW_KEY_NODE_RATE "node.rate" @@ -1592,14 +1630,10 @@ bool PipeWirePlayback::reset() */ spa_audio_info_raw info{make_spa_info(mDevice, is51rear, ForceF32Planar)}; - /* TODO: How to tell what an appropriate size is? Examples just use this - * magic value. - */ - constexpr uint32_t pod_buffer_size{1024}; - auto pod_buffer = std::make_unique(pod_buffer_size); - spa_pod_builder b{make_pod_builder(pod_buffer.get(), pod_buffer_size)}; + static constexpr uint32_t pod_buffer_size{1024}; + PodDynamicBuilder b(pod_buffer_size); - const spa_pod *params{spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &info)}; + const spa_pod *params{spa_format_audio_raw_build(b.get(), SPA_PARAM_EnumFormat, &info)}; if(!params) throw al::backend_exception{al::backend_error::DeviceError, "Failed to set PipeWire audio format parameters"}; @@ -2021,11 +2055,10 @@ void PipeWireCapture::open(std::string_view name) } spa_audio_info_raw info{make_spa_info(mDevice, is51rear, UseDevType)}; - constexpr uint32_t pod_buffer_size{1024}; - auto pod_buffer = std::make_unique(pod_buffer_size); - spa_pod_builder b{make_pod_builder(pod_buffer.get(), pod_buffer_size)}; + static constexpr uint32_t pod_buffer_size{1024}; + PodDynamicBuilder b(pod_buffer_size); - const spa_pod *params[]{spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &info)}; + const spa_pod *params[]{spa_format_audio_raw_build(b.get(), SPA_PARAM_EnumFormat, &info)}; if(!params[0]) throw al::backend_exception{al::backend_error::DeviceError, "Failed to set PipeWire audio format parameters"}; -- cgit v1.2.3 From 09b0d6091d9ef125fa7aac7514018f54793430b3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 21 Oct 2023 23:19:16 -0700 Subject: Update the downmix tables --- alc/alc.cpp | 119 +++++++++++++++++++++++++++--------------------------------- 1 file changed, 53 insertions(+), 66 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index baa4788f..96b641f7 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -880,73 +880,60 @@ ALCenum EnumFromDevAmbi(DevAmbiScaling scaling) } -/* Downmixing channel arrays, to map the given format's missing channels to - * existing ones. Based on Wine's DSound downmix values, which are based on - * PulseAudio's. +/* Downmixing channel arrays, to map a device format's missing channels to + * existing ones. Based on what PipeWire does, though simplified. */ -constexpr std::array FrontStereoSplit{{ - {FrontLeft, 0.5f}, {FrontRight, 0.5f} -}}; -constexpr std::array FrontLeft9{{ - {FrontLeft, 1.0f/9.0f} -}}; -constexpr std::array FrontRight9{{ - {FrontRight, 1.0f/9.0f} -}}; -constexpr std::array BackMonoToFrontSplit{{ - {FrontLeft, 0.5f/9.0f}, {FrontRight, 0.5f/9.0f} -}}; -constexpr std::array LeftStereoSplit{{ - {FrontLeft, 0.5f}, {BackLeft, 0.5f} -}}; -constexpr std::array RightStereoSplit{{ - {FrontRight, 0.5f}, {BackRight, 0.5f} -}}; -constexpr std::array BackStereoSplit{{ - {BackLeft, 0.5f}, {BackRight, 0.5f} -}}; -constexpr std::array SideStereoSplit{{ - {SideLeft, 0.5f}, {SideRight, 0.5f} -}}; -constexpr std::array ToSideLeft{{ - {SideLeft, 1.0f} -}}; -constexpr std::array ToSideRight{{ - {SideRight, 1.0f} -}}; -constexpr std::array BackLeftSplit{{ - {SideLeft, 0.5f}, {BackCenter, 0.5f} -}}; -constexpr std::array BackRightSplit{{ - {SideRight, 0.5f}, {BackCenter, 0.5f} -}}; - -const std::array StereoDownmix{{ - { FrontCenter, FrontStereoSplit }, - { SideLeft, FrontLeft9 }, - { SideRight, FrontRight9 }, - { BackLeft, FrontLeft9 }, - { BackRight, FrontRight9 }, - { BackCenter, BackMonoToFrontSplit }, -}}; -const std::array QuadDownmix{{ - { FrontCenter, FrontStereoSplit }, - { SideLeft, LeftStereoSplit }, - { SideRight, RightStereoSplit }, - { BackCenter, BackStereoSplit }, -}}; -const std::array X51Downmix{{ - { BackLeft, ToSideLeft }, - { BackRight, ToSideRight }, - { BackCenter, SideStereoSplit }, -}}; -const std::array X61Downmix{{ - { BackLeft, BackLeftSplit }, - { BackRight, BackRightSplit }, -}}; -const std::array X71Downmix{{ - { BackCenter, BackStereoSplit }, -}}; +constexpr float inv_sqrt2f{static_cast(1.0 / al::numbers::sqrt2)}; +constexpr std::array FrontStereo3dB{ + InputRemixMap::TargetMix{FrontLeft, inv_sqrt2f}, + InputRemixMap::TargetMix{FrontRight, inv_sqrt2f} +}; +constexpr std::array FrontStereo6dB{ + InputRemixMap::TargetMix{FrontLeft, 0.5f}, + InputRemixMap::TargetMix{FrontRight, 0.5f} +}; +constexpr std::array SideStereo3dB{ + InputRemixMap::TargetMix{SideLeft, inv_sqrt2f}, + InputRemixMap::TargetMix{SideRight, inv_sqrt2f} +}; +constexpr std::array BackStereo3dB{ + InputRemixMap::TargetMix{BackLeft, inv_sqrt2f}, + InputRemixMap::TargetMix{BackRight, inv_sqrt2f} +}; +constexpr std::array FrontLeft3dB{InputRemixMap::TargetMix{FrontLeft, inv_sqrt2f}}; +constexpr std::array FrontRight3dB{InputRemixMap::TargetMix{FrontRight, inv_sqrt2f}}; +constexpr std::array SideLeft0dB{InputRemixMap::TargetMix{SideLeft, 1.0f}}; +constexpr std::array SideRight0dB{InputRemixMap::TargetMix{SideRight, 1.0f}}; +constexpr std::array BackLeft0dB{InputRemixMap::TargetMix{BackLeft, 1.0f}}; +constexpr std::array BackRight0dB{InputRemixMap::TargetMix{BackRight, 1.0f}}; +constexpr std::array BackCenter3dB{InputRemixMap::TargetMix{BackCenter, inv_sqrt2f}}; + +constexpr std::array StereoDownmix{ + InputRemixMap{FrontCenter, FrontStereo3dB}, + InputRemixMap{SideLeft, FrontLeft3dB}, + InputRemixMap{SideRight, FrontRight3dB}, + InputRemixMap{BackLeft, FrontLeft3dB}, + InputRemixMap{BackRight, FrontRight3dB}, + InputRemixMap{BackCenter, FrontStereo6dB}, +}; +constexpr std::array QuadDownmix{ + InputRemixMap{FrontCenter, FrontStereo3dB}, + InputRemixMap{SideLeft, BackLeft0dB}, + InputRemixMap{SideRight, BackRight0dB}, + InputRemixMap{BackCenter, BackStereo3dB}, +}; +constexpr std::array X51Downmix{ + InputRemixMap{BackLeft, SideLeft0dB}, + InputRemixMap{BackRight, SideRight0dB}, + InputRemixMap{BackCenter, SideStereo3dB}, +}; +constexpr std::array X61Downmix{ + InputRemixMap{BackLeft, BackCenter3dB}, + InputRemixMap{BackRight, BackCenter3dB}, +}; +constexpr std::array X71Downmix{ + InputRemixMap{BackCenter, BackStereo3dB}, +}; std::unique_ptr CreateDeviceLimiter(const ALCdevice *device, const float threshold) -- cgit v1.2.3 From 197691365d112e170a8478fbbdcb38fd3826e418 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 22 Oct 2023 13:56:05 -0700 Subject: Use a byte for the channel index --- alc/alu.cpp | 18 +++++++++--------- alc/effects/dedicated.cpp | 4 ++-- alc/panning.cpp | 2 +- core/device.h | 18 +++++++++--------- 4 files changed, 21 insertions(+), 21 deletions(-) (limited to 'alc') diff --git a/alc/alu.cpp b/alc/alu.cpp index 7aefcfb5..203bd7cf 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -279,8 +279,8 @@ ResamplerFunc PrepareResampler(Resampler resampler, uint increment, InterpState void DeviceBase::ProcessHrtf(const size_t SamplesToDo) { /* HRTF is stereo output only. */ - const uint lidx{RealOut.ChannelIndex[FrontLeft]}; - const uint ridx{RealOut.ChannelIndex[FrontRight]}; + const size_t lidx{RealOut.ChannelIndex[FrontLeft]}; + const size_t ridx{RealOut.ChannelIndex[FrontRight]}; MixDirectHrtf(RealOut.Buffer[lidx], RealOut.Buffer[ridx], Dry.Buffer, HrtfAccumData, mHrtfState->mTemp.data(), mHrtfState->mChannels.data(), mHrtfState->mIrSize, SamplesToDo); @@ -294,9 +294,9 @@ void DeviceBase::ProcessAmbiDec(const size_t SamplesToDo) void DeviceBase::ProcessAmbiDecStablized(const size_t SamplesToDo) { /* Decode with front image stablization. */ - const uint lidx{RealOut.ChannelIndex[FrontLeft]}; - const uint ridx{RealOut.ChannelIndex[FrontRight]}; - const uint cidx{RealOut.ChannelIndex[FrontCenter]}; + const size_t lidx{RealOut.ChannelIndex[FrontLeft]}; + const size_t ridx{RealOut.ChannelIndex[FrontRight]}; + const size_t cidx{RealOut.ChannelIndex[FrontCenter]}; AmbiDecoder->processStablize(RealOut.Buffer, Dry.Buffer.data(), lidx, ridx, cidx, SamplesToDo); @@ -305,8 +305,8 @@ void DeviceBase::ProcessAmbiDecStablized(const size_t SamplesToDo) void DeviceBase::ProcessUhj(const size_t SamplesToDo) { /* UHJ is stereo output only. */ - const uint lidx{RealOut.ChannelIndex[FrontLeft]}; - const uint ridx{RealOut.ChannelIndex[FrontRight]}; + const size_t lidx{RealOut.ChannelIndex[FrontLeft]}; + const size_t ridx{RealOut.ChannelIndex[FrontRight]}; /* Encode to stereo-compatible 2-channel UHJ output. */ mUhjEncoder->encode(RealOut.Buffer[lidx].data(), RealOut.Buffer[ridx].data(), @@ -319,8 +319,8 @@ void DeviceBase::ProcessBs2b(const size_t SamplesToDo) AmbiDecoder->process(RealOut.Buffer, Dry.Buffer.data(), SamplesToDo); /* BS2B is stereo output only. */ - const uint lidx{RealOut.ChannelIndex[FrontLeft]}; - const uint ridx{RealOut.ChannelIndex[FrontRight]}; + const size_t lidx{RealOut.ChannelIndex[FrontLeft]}; + const size_t ridx{RealOut.ChannelIndex[FrontRight]}; /* Now apply the BS2B binaural/crossfeed filter. */ bs2b_cross_feed(Bs2b.get(), RealOut.Buffer[lidx].data(), RealOut.Buffer[ridx].data(), diff --git a/alc/effects/dedicated.cpp b/alc/effects/dedicated.cpp index 9ac68bec..a9131bfa 100644 --- a/alc/effects/dedicated.cpp +++ b/alc/effects/dedicated.cpp @@ -74,7 +74,7 @@ void DedicatedState::update(const ContextBase*, const EffectSlot *slot, if(slot->EffectType == EffectSlotType::DedicatedLFE) { - const uint idx{target.RealOut ? target.RealOut->ChannelIndex[LFE] : InvalidChannelIndex}; + const size_t idx{target.RealOut ? target.RealOut->ChannelIndex[LFE] : InvalidChannelIndex}; if(idx != InvalidChannelIndex) { mOutTarget = target.RealOut->Buffer; @@ -85,7 +85,7 @@ void DedicatedState::update(const ContextBase*, const EffectSlot *slot, { /* Dialog goes to the front-center speaker if it exists, otherwise it * plays from the front-center location. */ - const uint idx{target.RealOut ? target.RealOut->ChannelIndex[FrontCenter] + const size_t idx{target.RealOut ? target.RealOut->ChannelIndex[FrontCenter] : InvalidChannelIndex}; if(idx != InvalidChannelIndex) { diff --git a/alc/panning.cpp b/alc/panning.cpp index 871fef65..b512a42a 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -677,7 +677,7 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= /* Only enable the stablizer if the decoder does not output to the * front-center channel. */ - const auto cidx = device->RealOut.ChannelIndex[FrontCenter]; + const size_t cidx{device->RealOut.ChannelIndex[FrontCenter]}; bool hasfc{false}; if(cidx < chancoeffs.size()) { diff --git a/core/device.h b/core/device.h index b088e130..b1ffc9ce 100644 --- a/core/device.h +++ b/core/device.h @@ -94,7 +94,7 @@ struct DistanceComp { }; -constexpr uint InvalidChannelIndex{~0u}; +constexpr uint8_t InvalidChannelIndex{static_cast(~0u)}; struct BFChannelConfig { float Scale; @@ -112,8 +112,8 @@ struct MixParams { * source is expected to be a 3D ACN/N3D ambisonic buffer, and for each * channel [0...count), the given functor is called with the source channel * index, destination channel index, and the gain for that channel. If the - * destination channel is INVALID_CHANNEL_INDEX, the given source channel - * is not used for output. + * destination channel is InvalidChannelIndex, the given source channel is + * not used for output. */ template void setAmbiMixParams(const MixParams &inmix, const float gainbase, F func) const @@ -122,14 +122,14 @@ struct MixParams { const size_t numOut{Buffer.size()}; for(size_t i{0};i < numIn;++i) { - auto idx = InvalidChannelIndex; - auto gain = 0.0f; + uint8_t idx{InvalidChannelIndex}; + float gain{0.0f}; for(size_t j{0};j < numOut;++j) { if(AmbiMap[j].Index == inmix.AmbiMap[i].Index) { - idx = static_cast(j); + idx = static_cast(j); gain = AmbiMap[j].Scale * gainbase; break; } @@ -141,7 +141,7 @@ struct MixParams { struct RealMixParams { al::span RemixMap; - std::array ChannelIndex{}; + std::array ChannelIndex{}; al::span Buffer; }; @@ -329,9 +329,9 @@ struct DeviceBase { /** * Returns the index for the given channel name (e.g. FrontCenter), or - * INVALID_CHANNEL_INDEX if it doesn't exist. + * InvalidChannelIndex if it doesn't exist. */ - uint channelIdxByName(Channel chan) const noexcept + uint8_t channelIdxByName(Channel chan) const noexcept { return RealOut.ChannelIndex[chan]; } DISABLE_ALLOC() -- cgit v1.2.3 From 62e0d9125f98b8dd174c9fabce81ab633b66b2df Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 25 Oct 2023 16:29:01 -0700 Subject: Use PFFFT for the pitch shifter --- alc/effects/pshifter.cpp | 49 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 13 deletions(-) (limited to 'alc') diff --git a/alc/effects/pshifter.cpp b/alc/effects/pshifter.cpp index 95269009..0c27be30 100644 --- a/alc/effects/pshifter.cpp +++ b/alc/effects/pshifter.cpp @@ -28,7 +28,6 @@ #include #include "alc/effects/base.h" -#include "alcomplex.h" #include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" @@ -40,6 +39,7 @@ #include "core/mixer.h" #include "core/mixer/defs.h" #include "intrusive_ptr.h" +#include "pffft.h" struct ContextBase; @@ -74,6 +74,12 @@ struct Windower { const Windower gWindow{}; +struct PFFFTSetupDeleter { + void operator()(PFFFT_Setup *ptr) { pffft_destroy_setup(ptr); } +}; +using PFFFTSetupPtr = std::unique_ptr; + + struct FrequencyBin { float Magnitude; float FreqBin; @@ -93,7 +99,9 @@ struct PshifterState final : public EffectState { std::array mSumPhase; std::array mOutputAccum; - std::array mFftBuffer; + PFFFTSetupPtr mFft; + alignas(16) std::array mFftBuffer; + alignas(16) std::array mFftWorkBuffer; std::array mAnalysisBuffer; std::array mSynthesisBuffer; @@ -126,12 +134,15 @@ void PshifterState::deviceUpdate(const DeviceBase*, const BufferStorage*) mLastPhase.fill(0.0f); mSumPhase.fill(0.0f); mOutputAccum.fill(0.0f); - mFftBuffer.fill(complex_f{}); + mFftBuffer.fill(0.0f); mAnalysisBuffer.fill(FrequencyBin{}); mSynthesisBuffer.fill(FrequencyBin{}); std::fill(std::begin(mCurrentGains), std::end(mCurrentGains), 0.0f); std::fill(std::begin(mTargetGains), std::end(mTargetGains), 0.0f); + + if(!mFft) + mFft = PFFFTSetupPtr{pffft_new_setup(StftSize, PFFFT_REAL)}; } void PshifterState::update(const ContextBase*, const EffectSlot *slot, @@ -186,15 +197,19 @@ void PshifterState::process(const size_t samplesToDo, mFftBuffer[k] = mFIFO[src] * gWindow.mData[k]; for(size_t src{0u}, k{StftSize-mPos};src < mPos;++src,++k) mFftBuffer[k] = mFIFO[src] * gWindow.mData[k]; - forward_fft(al::span{mFftBuffer}); + pffft_transform_ordered(mFft.get(), mFftBuffer.data(), mFftBuffer.data(), + mFftWorkBuffer.data(), PFFFT_FORWARD); /* Analyze the obtained data. Since the real FFT is symmetric, only * StftHalfSize+1 samples are needed. */ - for(size_t k{0u};k < StftHalfSize+1;k++) + for(size_t k{0u};k < StftHalfSize+1;++k) { - const float magnitude{std::abs(mFftBuffer[k])}; - const float phase{std::arg(mFftBuffer[k])}; + const auto cplx = (k == 0) ? complex_f{mFftBuffer[0]} : + (k == StftHalfSize) ? complex_f{mFftBuffer[1]} : + complex_f{mFftBuffer[k*2], mFftBuffer[k*2 + 1]}; + const float magnitude{std::abs(cplx)}; + const float phase{std::arg(cplx)}; /* Compute the phase difference from the last update and subtract * the expected phase difference for this bin. @@ -266,21 +281,29 @@ void PshifterState::process(const size_t samplesToDo, tmp -= static_cast(qpd + (qpd%2)); mSumPhase[k] = tmp * al::numbers::pi_v; - mFftBuffer[k] = std::polar(mSynthesisBuffer[k].Magnitude, mSumPhase[k]); + const complex_f cplx{std::polar(mSynthesisBuffer[k].Magnitude, mSumPhase[k])}; + if(k == 0) + mFftBuffer[0] = cplx.real(); + else if(k == StftHalfSize) + mFftBuffer[1] = cplx.real(); + else + { + mFftBuffer[k*2 + 0] = cplx.real(); + mFftBuffer[k*2 + 1] = cplx.imag(); + } } - for(size_t k{StftHalfSize+1};k < StftSize;++k) - mFftBuffer[k] = std::conj(mFftBuffer[StftSize-k]); /* Apply an inverse FFT to get the time-domain signal, and accumulate * for the output with windowing. */ - inverse_fft(al::span{mFftBuffer}); + pffft_transform_ordered(mFft.get(), mFftBuffer.data(), mFftBuffer.data(), + mFftWorkBuffer.data(), PFFFT_BACKWARD); static constexpr float scale{3.0f / OversampleFactor / StftSize}; for(size_t dst{mPos}, k{0u};dst < StftSize;++dst,++k) - mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k].real() * scale; + mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k] * scale; for(size_t dst{0u}, k{StftSize-mPos};dst < mPos;++dst,++k) - mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k].real() * scale; + mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k] * scale; /* Copy out the accumulated result, then clear for the next iteration. */ std::copy_n(mOutputAccum.begin() + mPos, StftStep, mFIFO.begin() + mPos); -- cgit v1.2.3 From 62995788b1fbdf2c64ef23158c60e8e5ddd290b5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 10 Nov 2023 20:48:21 -0800 Subject: Remove some explicit template parameters --- alc/alu.cpp | 15 ++-- core/ambidefs.cpp | 234 +++++++++++++++++++++++++++--------------------------- 2 files changed, 124 insertions(+), 125 deletions(-) (limited to 'alc') diff --git a/alc/alu.cpp b/alc/alu.cpp index 203bd7cf..e0858b18 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -603,19 +603,18 @@ inline std::array ScaleAzimuthFront3_2(std::array pos) * precomputed since they're constant. The second-order coefficients are * followed by the third-order coefficients, etc. */ -template -constexpr size_t CalcRotatorSize() -{ return (L*2 + 1)*(L*2 + 1) + CalcRotatorSize(); } - -template<> constexpr size_t CalcRotatorSize<0>() = delete; -template<> constexpr size_t CalcRotatorSize<1>() = delete; -template<> constexpr size_t CalcRotatorSize<2>() { return 5*5; } +constexpr size_t CalcRotatorSize(size_t l) noexcept +{ + if(l >= 2) + return (l*2 + 1)*(l*2 + 1) + CalcRotatorSize(l-1); + return 0; +} struct RotatorCoeffs { struct CoeffValues { float u, v, w; }; - std::array()> mCoeffs{}; + std::array mCoeffs{}; RotatorCoeffs() { diff --git a/core/ambidefs.cpp b/core/ambidefs.cpp index c1bb5c81..ffb45e09 100644 --- a/core/ambidefs.cpp +++ b/core/ambidefs.cpp @@ -21,25 +21,25 @@ constexpr auto inv_sqrt3f = static_cast(1.0/al::numbers::sqrt3); * will result in that channel being subsequently decoded for second-order as * if it was a first-order decoder for that same speaker array. */ -constexpr std::array,MaxAmbiOrder+1> HFScales{{ - {{ 4.000000000e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f }}, - {{ 4.000000000e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f }}, - {{ 2.981423970e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f }}, - {{ 2.359168820e+00f, 2.031565936e+00f, 1.444598386e+00f, 7.189495850e-01f }}, - /* 1.947005434e+00f, 1.764337084e+00f, 1.424707344e+00f, 9.755104127e-01f, 4.784482742e-01f */ -}}; +constexpr std::array HFScales{ + std::array{4.000000000e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f}, + std::array{4.000000000e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f}, + std::array{2.981423970e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f}, + std::array{2.359168820e+00f, 2.031565936e+00f, 1.444598386e+00f, 7.189495850e-01f}, + /*std::array{1.947005434e+00f, 1.764337084e+00f, 1.424707344e+00f, 9.755104127e-01f, 4.784482742e-01f}, */ +}; /* Same as above, but using a 10-point horizontal-only speaker array. Should * only be used when the device is mixing in 2D B-Format for horizontal-only * output. */ -constexpr std::array,MaxAmbiOrder+1> HFScales2D{{ - {{ 2.236067977e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f }}, - {{ 2.236067977e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f }}, - {{ 1.825741858e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f }}, - {{ 1.581138830e+00f, 1.460781803e+00f, 1.118033989e+00f, 6.050756345e-01f }}, - /* 1.414213562e+00f, 1.344997024e+00f, 1.144122806e+00f, 8.312538756e-01f, 4.370160244e-01f */ -}}; +constexpr std::array HFScales2D{ + std::array{2.236067977e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f}, + std::array{2.236067977e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f}, + std::array{1.825741858e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f}, + std::array{1.581138830e+00f, 1.460781803e+00f, 1.118033989e+00f, 6.050756345e-01f}, + /*std::array{1.414213562e+00f, 1.344997024e+00f, 1.144122806e+00f, 8.312538756e-01f, 4.370160244e-01f}, */ +}; /* This calculates a first-order "upsampler" matrix. It combines a first-order @@ -49,17 +49,17 @@ constexpr std::array,MaxAmbiOrder+1> HFScales2D * signal. While not perfect, this should accurately encode a lower-order * signal into a higher-order signal. */ -constexpr std::array,8> FirstOrderDecoder{{ - {{ 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, }}, - {{ 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, }}, - {{ 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, }}, - {{ 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, }}, - {{ 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, }}, - {{ 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, }}, - {{ 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, }}, - {{ 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, }}, -}}; -constexpr std::array FirstOrderEncoder{{ +constexpr std::array FirstOrderDecoder{ + std::array{1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f}, + std::array{1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f}, + std::array{1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f}, + std::array{1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f}, + std::array{1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f}, + std::array{1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f}, + std::array{1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f}, + std::array{1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f}, +}; +constexpr std::array FirstOrderEncoder{ CalcAmbiCoeffs( inv_sqrt3f, inv_sqrt3f, inv_sqrt3f), CalcAmbiCoeffs( inv_sqrt3f, inv_sqrt3f, -inv_sqrt3f), CalcAmbiCoeffs(-inv_sqrt3f, inv_sqrt3f, inv_sqrt3f), @@ -68,25 +68,25 @@ constexpr std::array FirstOrderEncoder{{ CalcAmbiCoeffs( inv_sqrt3f, -inv_sqrt3f, -inv_sqrt3f), CalcAmbiCoeffs(-inv_sqrt3f, -inv_sqrt3f, inv_sqrt3f), CalcAmbiCoeffs(-inv_sqrt3f, -inv_sqrt3f, -inv_sqrt3f), -}}; +}; static_assert(FirstOrderDecoder.size() == FirstOrderEncoder.size(), "First-order mismatch"); /* This calculates a 2D first-order "upsampler" matrix. Same as the first-order * matrix, just using a more optimized speaker array for horizontal-only * content. */ -constexpr std::array,4> FirstOrder2DDecoder{{ - {{ 2.500000000e-01f, 2.041241452e-01f, 0.0f, 2.041241452e-01f, }}, - {{ 2.500000000e-01f, 2.041241452e-01f, 0.0f, -2.041241452e-01f, }}, - {{ 2.500000000e-01f, -2.041241452e-01f, 0.0f, 2.041241452e-01f, }}, - {{ 2.500000000e-01f, -2.041241452e-01f, 0.0f, -2.041241452e-01f, }}, -}}; -constexpr std::array FirstOrder2DEncoder{{ +constexpr std::array FirstOrder2DDecoder{ + std::array{2.500000000e-01f, 2.041241452e-01f, 0.0f, 2.041241452e-01f}, + std::array{2.500000000e-01f, 2.041241452e-01f, 0.0f, -2.041241452e-01f}, + std::array{2.500000000e-01f, -2.041241452e-01f, 0.0f, 2.041241452e-01f}, + std::array{2.500000000e-01f, -2.041241452e-01f, 0.0f, -2.041241452e-01f}, +}; +constexpr std::array FirstOrder2DEncoder{ CalcAmbiCoeffs( inv_sqrt2f, 0.0f, inv_sqrt2f), CalcAmbiCoeffs( inv_sqrt2f, 0.0f, -inv_sqrt2f), CalcAmbiCoeffs(-inv_sqrt2f, 0.0f, inv_sqrt2f), CalcAmbiCoeffs(-inv_sqrt2f, 0.0f, -inv_sqrt2f), -}}; +}; static_assert(FirstOrder2DDecoder.size() == FirstOrder2DEncoder.size(), "First-order 2D mismatch"); @@ -94,21 +94,21 @@ static_assert(FirstOrder2DDecoder.size() == FirstOrder2DEncoder.size(), "First-o * matrix, just using a slightly more dense speaker array suitable for second- * order content. */ -constexpr std::array,12> SecondOrderDecoder{{ - {{ 8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f, }}, - {{ 8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }}, - {{ 8.333333333e-02f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }}, - {{ 8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f, }}, - {{ 8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }}, - {{ 8.333333333e-02f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }}, - {{ 8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f, }}, - {{ 8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }}, - {{ 8.333333333e-02f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }}, - {{ 8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f, }}, - {{ 8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }}, - {{ 8.333333333e-02f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }}, -}}; -constexpr std::array SecondOrderEncoder{{ +constexpr std::array SecondOrderDecoder{ + std::array{8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f}, + std::array{8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + std::array{8.333333333e-02f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, + std::array{8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f}, + std::array{8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + std::array{8.333333333e-02f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, + std::array{8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f}, + std::array{8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + std::array{8.333333333e-02f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, + std::array{8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f}, + std::array{8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + std::array{8.333333333e-02f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, +}; +constexpr std::array SecondOrderEncoder{ CalcAmbiCoeffs( 0.000000000e+00f, -5.257311121e-01f, 8.506508084e-01f), CalcAmbiCoeffs(-8.506508084e-01f, 0.000000000e+00f, 5.257311121e-01f), CalcAmbiCoeffs(-5.257311121e-01f, 8.506508084e-01f, 0.000000000e+00f), @@ -121,29 +121,29 @@ constexpr std::array SecondOrderEncoder{{ CalcAmbiCoeffs( 0.000000000e+00f, 5.257311121e-01f, -8.506508084e-01f), CalcAmbiCoeffs( 8.506508084e-01f, 0.000000000e+00f, 5.257311121e-01f), CalcAmbiCoeffs(-5.257311121e-01f, -8.506508084e-01f, 0.000000000e+00f), -}}; +}; static_assert(SecondOrderDecoder.size() == SecondOrderEncoder.size(), "Second-order mismatch"); /* This calculates a 2D second-order "upsampler" matrix. Same as the second- * order matrix, just using a more optimized speaker array for horizontal-only * content. */ -constexpr std::array,6> SecondOrder2DDecoder{{ - {{ 1.666666667e-01f, -9.622504486e-02f, 0.0f, 1.666666667e-01f, -1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f, }}, - {{ 1.666666667e-01f, -1.924500897e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.721325932e-01f, }}, - {{ 1.666666667e-01f, -9.622504486e-02f, 0.0f, -1.666666667e-01f, 1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f, }}, - {{ 1.666666667e-01f, 9.622504486e-02f, 0.0f, -1.666666667e-01f, -1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f, }}, - {{ 1.666666667e-01f, 1.924500897e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.721325932e-01f, }}, - {{ 1.666666667e-01f, 9.622504486e-02f, 0.0f, 1.666666667e-01f, 1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f, }}, -}}; -constexpr std::array SecondOrder2DEncoder{{ +constexpr std::array SecondOrder2DDecoder{ + std::array{1.666666667e-01f, -9.622504486e-02f, 0.0f, 1.666666667e-01f, -1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f}, + std::array{1.666666667e-01f, -1.924500897e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.721325932e-01f}, + std::array{1.666666667e-01f, -9.622504486e-02f, 0.0f, -1.666666667e-01f, 1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f}, + std::array{1.666666667e-01f, 9.622504486e-02f, 0.0f, -1.666666667e-01f, -1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f}, + std::array{1.666666667e-01f, 1.924500897e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.721325932e-01f}, + std::array{1.666666667e-01f, 9.622504486e-02f, 0.0f, 1.666666667e-01f, 1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f}, +}; +constexpr std::array SecondOrder2DEncoder{ CalcAmbiCoeffs(-0.50000000000f, 0.0f, 0.86602540379f), CalcAmbiCoeffs(-1.00000000000f, 0.0f, 0.00000000000f), CalcAmbiCoeffs(-0.50000000000f, 0.0f, -0.86602540379f), CalcAmbiCoeffs( 0.50000000000f, 0.0f, -0.86602540379f), CalcAmbiCoeffs( 1.00000000000f, 0.0f, 0.00000000000f), CalcAmbiCoeffs( 0.50000000000f, 0.0f, 0.86602540379f), -}}; +}; static_assert(SecondOrder2DDecoder.size() == SecondOrder2DEncoder.size(), "Second-order 2D mismatch"); @@ -152,29 +152,29 @@ static_assert(SecondOrder2DDecoder.size() == SecondOrder2DEncoder.size(), * matrix, just using a more dense speaker array suitable for third-order * content. */ -constexpr std::array,20> ThirdOrderDecoder{{ - {{ 5.000000000e-02f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f, }}, - {{ 5.000000000e-02f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f, }}, - {{ 5.000000000e-02f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f, }}, - {{ 5.000000000e-02f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f, }}, - {{ 5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f, }}, - {{ 5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f, }}, - {{ 5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f, }}, - {{ 5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f, }}, - {{ 5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, -6.779013272e-02f, 1.659481923e-01f, 4.797944664e-02f, }}, - {{ 5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, 6.779013272e-02f, 1.659481923e-01f, -4.797944664e-02f, }}, - {{ 5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, -6.779013272e-02f, -1.659481923e-01f, 4.797944664e-02f, }}, - {{ 5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, 6.779013272e-02f, -1.659481923e-01f, -4.797944664e-02f, }}, - {{ 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f, }}, - {{ 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f, }}, - {{ 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f, }}, - {{ 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f, }}, - {{ 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f, }}, - {{ 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f, }}, - {{ 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f, }}, - {{ 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f, }}, -}}; -constexpr std::array ThirdOrderEncoder{{ +constexpr std::array ThirdOrderDecoder{ + std::array{5.000000000e-02f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f}, + std::array{5.000000000e-02f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f}, + std::array{5.000000000e-02f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f}, + std::array{5.000000000e-02f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f}, + std::array{5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f}, + std::array{5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f}, + std::array{5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f}, + std::array{5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f}, + std::array{5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, -6.779013272e-02f, 1.659481923e-01f, 4.797944664e-02f}, + std::array{5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, 6.779013272e-02f, 1.659481923e-01f, -4.797944664e-02f}, + std::array{5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, -6.779013272e-02f, -1.659481923e-01f, 4.797944664e-02f}, + std::array{5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, 6.779013272e-02f, -1.659481923e-01f, -4.797944664e-02f}, + std::array{5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f}, + std::array{5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f}, + std::array{5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f}, + std::array{5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f}, + std::array{5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f}, + std::array{5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f}, + std::array{5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f}, + std::array{5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f}, +}; +constexpr std::array ThirdOrderEncoder{ CalcAmbiCoeffs( 0.35682208976f, 0.93417235897f, 0.00000000000f), CalcAmbiCoeffs(-0.35682208976f, 0.93417235897f, 0.00000000000f), CalcAmbiCoeffs( 0.35682208976f, -0.93417235897f, 0.00000000000f), @@ -195,24 +195,24 @@ constexpr std::array ThirdOrderEncoder{{ CalcAmbiCoeffs( inv_sqrt3f, -inv_sqrt3f, -inv_sqrt3f), CalcAmbiCoeffs( -inv_sqrt3f, -inv_sqrt3f, inv_sqrt3f), CalcAmbiCoeffs( -inv_sqrt3f, -inv_sqrt3f, -inv_sqrt3f), -}}; +}; static_assert(ThirdOrderDecoder.size() == ThirdOrderEncoder.size(), "Third-order mismatch"); /* This calculates a 2D third-order "upsampler" matrix. Same as the third-order * matrix, just using a more optimized speaker array for horizontal-only * content. */ -constexpr std::array,8> ThirdOrder2DDecoder{{ - {{ 1.250000000e-01f, -5.523559567e-02f, 0.0f, 1.333505242e-01f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, -1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.573941867e-02f, }}, - {{ 1.250000000e-01f, -1.333505242e-01f, 0.0f, 5.523559567e-02f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, 4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.104247249e-01f, }}, - {{ 1.250000000e-01f, -1.333505242e-01f, 0.0f, -5.523559567e-02f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, 4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.104247249e-01f, }}, - {{ 1.250000000e-01f, -5.523559567e-02f, 0.0f, -1.333505242e-01f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, -1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -4.573941867e-02f, }}, - {{ 1.250000000e-01f, 5.523559567e-02f, 0.0f, -1.333505242e-01f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, 1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -4.573941867e-02f, }}, - {{ 1.250000000e-01f, 1.333505242e-01f, 0.0f, -5.523559567e-02f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, -4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.104247249e-01f, }}, - {{ 1.250000000e-01f, 1.333505242e-01f, 0.0f, 5.523559567e-02f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, -4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.104247249e-01f, }}, - {{ 1.250000000e-01f, 5.523559567e-02f, 0.0f, 1.333505242e-01f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, 1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.573941867e-02f, }}, -}}; -constexpr std::array ThirdOrder2DEncoder{{ +constexpr std::array ThirdOrder2DDecoder{ + std::array{1.250000000e-01f, -5.523559567e-02f, 0.0f, 1.333505242e-01f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, -1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.573941867e-02f}, + std::array{1.250000000e-01f, -1.333505242e-01f, 0.0f, 5.523559567e-02f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, 4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.104247249e-01f}, + std::array{1.250000000e-01f, -1.333505242e-01f, 0.0f, -5.523559567e-02f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, 4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.104247249e-01f}, + std::array{1.250000000e-01f, -5.523559567e-02f, 0.0f, -1.333505242e-01f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, -1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -4.573941867e-02f}, + std::array{1.250000000e-01f, 5.523559567e-02f, 0.0f, -1.333505242e-01f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, 1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -4.573941867e-02f}, + std::array{1.250000000e-01f, 1.333505242e-01f, 0.0f, -5.523559567e-02f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, -4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.104247249e-01f}, + std::array{1.250000000e-01f, 1.333505242e-01f, 0.0f, 5.523559567e-02f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, -4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.104247249e-01f}, + std::array{1.250000000e-01f, 5.523559567e-02f, 0.0f, 1.333505242e-01f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, 1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.573941867e-02f}, +}; +constexpr std::array ThirdOrder2DEncoder{ CalcAmbiCoeffs(-0.38268343237f, 0.0f, 0.92387953251f), CalcAmbiCoeffs(-0.92387953251f, 0.0f, 0.38268343237f), CalcAmbiCoeffs(-0.92387953251f, 0.0f, -0.38268343237f), @@ -221,7 +221,7 @@ constexpr std::array ThirdOrder2DEncoder{{ CalcAmbiCoeffs( 0.92387953251f, 0.0f, -0.38268343237f), CalcAmbiCoeffs( 0.92387953251f, 0.0f, 0.38268343237f), CalcAmbiCoeffs( 0.38268343237f, 0.0f, 0.92387953251f), -}}; +}; static_assert(ThirdOrder2DDecoder.size() == ThirdOrder2DEncoder.size(), "Third-order 2D mismatch"); @@ -230,19 +230,19 @@ static_assert(ThirdOrder2DDecoder.size() == ThirdOrder2DEncoder.size(), "Third-o * the foreseeable future. This is only necessary for mixing horizontal-only * fourth-order content to 3D. */ -constexpr std::array,10> FourthOrder2DDecoder{{ - {{ 1.000000000e-01f, 3.568220898e-02f, 0.0f, 1.098185471e-01f, 6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, 7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 5.620301997e-02f, 8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f, }}, - {{ 1.000000000e-01f, 9.341723590e-02f, 0.0f, 6.787159473e-02f, 9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, 2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -9.093839659e-02f, -5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f, }}, - {{ 1.000000000e-01f, 1.154700538e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.032795559e-01f, -9.561828875e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.014978717e-02f, }}, - {{ 1.000000000e-01f, 9.341723590e-02f, 0.0f, -6.787159473e-02f, -9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, 2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.093839659e-02f, 5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f, }}, - {{ 1.000000000e-01f, 3.568220898e-02f, 0.0f, -1.098185471e-01f, -6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, 7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -5.620301997e-02f, -8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f, }}, - {{ 1.000000000e-01f, -3.568220898e-02f, 0.0f, -1.098185471e-01f, 6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, -7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -5.620301997e-02f, 8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f, }}, - {{ 1.000000000e-01f, -9.341723590e-02f, 0.0f, -6.787159473e-02f, 9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, -2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.093839659e-02f, -5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f, }}, - {{ 1.000000000e-01f, -1.154700538e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.032795559e-01f, 9.561828875e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.014978717e-02f, }}, - {{ 1.000000000e-01f, -9.341723590e-02f, 0.0f, 6.787159473e-02f, -9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, -2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -9.093839659e-02f, 5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f, }}, - {{ 1.000000000e-01f, -3.568220898e-02f, 0.0f, 1.098185471e-01f, -6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, -7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 5.620301997e-02f, -8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f, }}, -}}; -constexpr std::array FourthOrder2DEncoder{{ +constexpr std::array FourthOrder2DDecoder{ + std::array{1.000000000e-01f, 3.568220898e-02f, 0.0f, 1.098185471e-01f, 6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, 7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 5.620301997e-02f, 8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f}, + std::array{1.000000000e-01f, 9.341723590e-02f, 0.0f, 6.787159473e-02f, 9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, 2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -9.093839659e-02f, -5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f}, + std::array{1.000000000e-01f, 1.154700538e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.032795559e-01f, -9.561828875e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.014978717e-02f}, + std::array{1.000000000e-01f, 9.341723590e-02f, 0.0f, -6.787159473e-02f, -9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, 2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.093839659e-02f, 5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f}, + std::array{1.000000000e-01f, 3.568220898e-02f, 0.0f, -1.098185471e-01f, -6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, 7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -5.620301997e-02f, -8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f}, + std::array{1.000000000e-01f, -3.568220898e-02f, 0.0f, -1.098185471e-01f, 6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, -7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -5.620301997e-02f, 8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f}, + std::array{1.000000000e-01f, -9.341723590e-02f, 0.0f, -6.787159473e-02f, 9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, -2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.093839659e-02f, -5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f}, + std::array{1.000000000e-01f, -1.154700538e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.032795559e-01f, 9.561828875e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.014978717e-02f}, + std::array{1.000000000e-01f, -9.341723590e-02f, 0.0f, 6.787159473e-02f, -9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, -2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -9.093839659e-02f, 5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f}, + std::array{1.000000000e-01f, -3.568220898e-02f, 0.0f, 1.098185471e-01f, -6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, -7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 5.620301997e-02f, -8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f}, +}; +constexpr std::array FourthOrder2DEncoder{ CalcAmbiCoeffs( 3.090169944e-01f, 0.000000000e+00f, 9.510565163e-01f), CalcAmbiCoeffs( 8.090169944e-01f, 0.000000000e+00f, 5.877852523e-01f), CalcAmbiCoeffs( 1.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f), @@ -253,7 +253,7 @@ constexpr std::array FourthOrder2DEncoder{{ CalcAmbiCoeffs(-1.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f), CalcAmbiCoeffs(-8.090169944e-01f, 0.000000000e+00f, 5.877852523e-01f), CalcAmbiCoeffs(-3.090169944e-01f, 0.000000000e+00f, 9.510565163e-01f), -}}; +}; static_assert(FourthOrder2DDecoder.size() == FourthOrder2DEncoder.size(), "Fourth-order 2D mismatch"); @@ -279,13 +279,13 @@ constexpr auto CalcAmbiUpsampler(const std::array,M> &decode } // namespace -const std::array AmbiScale::FirstOrderUp{CalcAmbiUpsampler(FirstOrderDecoder, FirstOrderEncoder)}; -const std::array AmbiScale::FirstOrder2DUp{CalcAmbiUpsampler(FirstOrder2DDecoder, FirstOrder2DEncoder)}; -const std::array AmbiScale::SecondOrderUp{CalcAmbiUpsampler(SecondOrderDecoder, SecondOrderEncoder)}; -const std::array AmbiScale::SecondOrder2DUp{CalcAmbiUpsampler(SecondOrder2DDecoder, SecondOrder2DEncoder)}; -const std::array AmbiScale::ThirdOrderUp{CalcAmbiUpsampler(ThirdOrderDecoder, ThirdOrderEncoder)}; -const std::array AmbiScale::ThirdOrder2DUp{CalcAmbiUpsampler(ThirdOrder2DDecoder, ThirdOrder2DEncoder)}; -const std::array AmbiScale::FourthOrder2DUp{CalcAmbiUpsampler(FourthOrder2DDecoder, FourthOrder2DEncoder)}; +const std::array AmbiScale::FirstOrderUp = CalcAmbiUpsampler(FirstOrderDecoder, FirstOrderEncoder); +const std::array AmbiScale::FirstOrder2DUp = CalcAmbiUpsampler(FirstOrder2DDecoder, FirstOrder2DEncoder); +const std::array AmbiScale::SecondOrderUp = CalcAmbiUpsampler(SecondOrderDecoder, SecondOrderEncoder); +const std::array AmbiScale::SecondOrder2DUp = CalcAmbiUpsampler(SecondOrder2DDecoder, SecondOrder2DEncoder); +const std::array AmbiScale::ThirdOrderUp = CalcAmbiUpsampler(ThirdOrderDecoder, ThirdOrderEncoder); +const std::array AmbiScale::ThirdOrder2DUp = CalcAmbiUpsampler(ThirdOrder2DDecoder, ThirdOrder2DEncoder); +const std::array AmbiScale::FourthOrder2DUp = CalcAmbiUpsampler(FourthOrder2DDecoder, FourthOrder2DEncoder); std::array AmbiScale::GetHFOrderScales(const uint src_order, -- cgit v1.2.3 From fe5b3f4fed727b6cf0e98a3454070a53ffcb2ee6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 15 Nov 2023 00:52:57 -0800 Subject: Support 32-bit int sample storage --- al/buffer.cpp | 1 + alc/effects/convolution.cpp | 1 + core/buffer_storage.cpp | 2 ++ core/buffer_storage.h | 1 + core/fmt_traits.h | 8 ++++++++ core/voice.cpp | 1 + 6 files changed, 14 insertions(+) (limited to 'alc') diff --git a/al/buffer.cpp b/al/buffer.cpp index 8ba874e4..82068b62 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -464,6 +464,7 @@ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, { case FmtUByte: return alignof(ALubyte); case FmtShort: return alignof(ALshort); + case FmtInt: return alignof(ALint); case FmtFloat: return alignof(ALfloat); case FmtDouble: return alignof(ALdouble); case FmtMulaw: return alignof(ALubyte); diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index 5c0b2677..517e6b08 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -84,6 +84,7 @@ void LoadSamples(float *RESTRICT dst, const std::byte *src, const size_t srcstep { HANDLE_FMT(FmtUByte); HANDLE_FMT(FmtShort); + HANDLE_FMT(FmtInt); HANDLE_FMT(FmtFloat); HANDLE_FMT(FmtDouble); HANDLE_FMT(FmtMulaw); diff --git a/core/buffer_storage.cpp b/core/buffer_storage.cpp index 98ca2c1b..6ffab124 100644 --- a/core/buffer_storage.cpp +++ b/core/buffer_storage.cpp @@ -12,6 +12,7 @@ const char *NameFromFormat(FmtType type) noexcept { case FmtUByte: return "UInt8"; case FmtShort: return "Int16"; + case FmtInt: return "Int32"; case FmtFloat: return "Float"; case FmtDouble: return "Double"; case FmtMulaw: return "muLaw"; @@ -49,6 +50,7 @@ uint BytesFromFmt(FmtType type) noexcept { case FmtUByte: return sizeof(uint8_t); case FmtShort: return sizeof(int16_t); + case FmtInt: return sizeof(int32_t); case FmtFloat: return sizeof(float); case FmtDouble: return sizeof(double); case FmtMulaw: return sizeof(uint8_t); diff --git a/core/buffer_storage.h b/core/buffer_storage.h index d8ab0b67..3b581b5e 100644 --- a/core/buffer_storage.h +++ b/core/buffer_storage.h @@ -15,6 +15,7 @@ using uint = unsigned int; enum FmtType : unsigned char { FmtUByte, FmtShort, + FmtInt, FmtFloat, FmtDouble, FmtMulaw, diff --git a/core/fmt_traits.h b/core/fmt_traits.h index 1879c81b..02473014 100644 --- a/core/fmt_traits.h +++ b/core/fmt_traits.h @@ -31,6 +31,14 @@ struct FmtTypeTraits { static constexpr OutT to(const Type val) noexcept { return val*OutT{1.0/32768.0}; } }; template<> +struct FmtTypeTraits { + using Type = int32_t; + + template + static constexpr OutT to(const Type val) noexcept + { return static_cast(val)*OutT{1.0/2147483648.0}; } +}; +template<> struct FmtTypeTraits { using Type = float; diff --git a/core/voice.cpp b/core/voice.cpp index b8acc7a6..3889c42d 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -474,6 +474,7 @@ void LoadSamples(float *dstSamples, const std::byte *src, const size_t srcChan, { HANDLE_FMT(FmtUByte); HANDLE_FMT(FmtShort); + HANDLE_FMT(FmtInt); HANDLE_FMT(FmtFloat); HANDLE_FMT(FmtDouble); HANDLE_FMT(FmtMulaw); -- cgit v1.2.3 From 6e224443096a85f5eefa8d815d6905824f230604 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 18 Nov 2023 05:33:30 -0800 Subject: Start a 32-bit sample format extension This ultimately is to properly distinguish and clarify formats being 32-bit integer and 32-bit float. --- al/buffer.cpp | 169 +++++++++++++++++++++++++++++------------------------- alc/alc.cpp | 48 ++++++++++------ alc/export_list.h | 63 ++++++++++++-------- alc/inprogext.h | 20 +++++++ 4 files changed, 181 insertions(+), 119 deletions(-) (limited to 'alc') diff --git a/al/buffer.cpp b/al/buffer.cpp index 82068b62..7d043036 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -550,83 +550,98 @@ std::optional DecomposeUserFormat(ALenum format) FmtChannels channels; FmtType type; }; - static const std::array UserFmtList{{ - { AL_FORMAT_MONO8, FmtMono, FmtUByte }, - { AL_FORMAT_MONO16, FmtMono, FmtShort }, - { AL_FORMAT_MONO_FLOAT32, FmtMono, FmtFloat }, - { AL_FORMAT_MONO_DOUBLE_EXT, FmtMono, FmtDouble }, - { AL_FORMAT_MONO_IMA4, FmtMono, FmtIMA4 }, - { AL_FORMAT_MONO_MSADPCM_SOFT, FmtMono, FmtMSADPCM }, - { AL_FORMAT_MONO_MULAW, FmtMono, FmtMulaw }, - { AL_FORMAT_MONO_ALAW_EXT, FmtMono, FmtAlaw }, - - { AL_FORMAT_STEREO8, FmtStereo, FmtUByte }, - { AL_FORMAT_STEREO16, FmtStereo, FmtShort }, - { AL_FORMAT_STEREO_FLOAT32, FmtStereo, FmtFloat }, - { AL_FORMAT_STEREO_DOUBLE_EXT, FmtStereo, FmtDouble }, - { AL_FORMAT_STEREO_IMA4, FmtStereo, FmtIMA4 }, - { AL_FORMAT_STEREO_MSADPCM_SOFT, FmtStereo, FmtMSADPCM }, - { AL_FORMAT_STEREO_MULAW, FmtStereo, FmtMulaw }, - { AL_FORMAT_STEREO_ALAW_EXT, FmtStereo, FmtAlaw }, - - { AL_FORMAT_REAR8, FmtRear, FmtUByte }, - { AL_FORMAT_REAR16, FmtRear, FmtShort }, - { AL_FORMAT_REAR32, FmtRear, FmtFloat }, - { AL_FORMAT_REAR_MULAW, FmtRear, FmtMulaw }, - - { AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtUByte }, - { AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort }, - - { AL_FORMAT_QUAD8, FmtQuad, FmtUByte }, - { AL_FORMAT_QUAD16, FmtQuad, FmtShort }, - { AL_FORMAT_QUAD32, FmtQuad, FmtFloat }, - { AL_FORMAT_QUAD_MULAW, FmtQuad, FmtMulaw }, - - { AL_FORMAT_51CHN8, FmtX51, FmtUByte }, - { AL_FORMAT_51CHN16, FmtX51, FmtShort }, - { AL_FORMAT_51CHN32, FmtX51, FmtFloat }, - { AL_FORMAT_51CHN_MULAW, FmtX51, FmtMulaw }, - - { AL_FORMAT_61CHN8, FmtX61, FmtUByte }, - { AL_FORMAT_61CHN16, FmtX61, FmtShort }, - { AL_FORMAT_61CHN32, FmtX61, FmtFloat }, - { AL_FORMAT_61CHN_MULAW, FmtX61, FmtMulaw }, - - { AL_FORMAT_71CHN8, FmtX71, FmtUByte }, - { AL_FORMAT_71CHN16, FmtX71, FmtShort }, - { AL_FORMAT_71CHN32, FmtX71, FmtFloat }, - { AL_FORMAT_71CHN_MULAW, FmtX71, FmtMulaw }, - - { AL_FORMAT_BFORMAT2D_8, FmtBFormat2D, FmtUByte }, - { AL_FORMAT_BFORMAT2D_16, FmtBFormat2D, FmtShort }, - { AL_FORMAT_BFORMAT2D_FLOAT32, FmtBFormat2D, FmtFloat }, - { AL_FORMAT_BFORMAT2D_MULAW, FmtBFormat2D, FmtMulaw }, - - { AL_FORMAT_BFORMAT3D_8, FmtBFormat3D, FmtUByte }, - { AL_FORMAT_BFORMAT3D_16, FmtBFormat3D, FmtShort }, - { AL_FORMAT_BFORMAT3D_FLOAT32, FmtBFormat3D, FmtFloat }, - { AL_FORMAT_BFORMAT3D_MULAW, FmtBFormat3D, FmtMulaw }, - - { AL_FORMAT_UHJ2CHN8_SOFT, FmtUHJ2, FmtUByte }, - { AL_FORMAT_UHJ2CHN16_SOFT, FmtUHJ2, FmtShort }, - { AL_FORMAT_UHJ2CHN_FLOAT32_SOFT, FmtUHJ2, FmtFloat }, - { AL_FORMAT_UHJ2CHN_MULAW_SOFT, FmtUHJ2, FmtMulaw }, - { AL_FORMAT_UHJ2CHN_ALAW_SOFT, FmtUHJ2, FmtAlaw }, - { AL_FORMAT_UHJ2CHN_IMA4_SOFT, FmtUHJ2, FmtIMA4 }, - { AL_FORMAT_UHJ2CHN_MSADPCM_SOFT, FmtUHJ2, FmtMSADPCM }, - - { AL_FORMAT_UHJ3CHN8_SOFT, FmtUHJ3, FmtUByte }, - { AL_FORMAT_UHJ3CHN16_SOFT, FmtUHJ3, FmtShort }, - { AL_FORMAT_UHJ3CHN_FLOAT32_SOFT, FmtUHJ3, FmtFloat }, - { AL_FORMAT_UHJ3CHN_MULAW_SOFT, FmtUHJ3, FmtMulaw }, - { AL_FORMAT_UHJ3CHN_ALAW_SOFT, FmtUHJ3, FmtAlaw }, - - { AL_FORMAT_UHJ4CHN8_SOFT, FmtUHJ4, FmtUByte }, - { AL_FORMAT_UHJ4CHN16_SOFT, FmtUHJ4, FmtShort }, - { AL_FORMAT_UHJ4CHN_FLOAT32_SOFT, FmtUHJ4, FmtFloat }, - { AL_FORMAT_UHJ4CHN_MULAW_SOFT, FmtUHJ4, FmtMulaw }, - { AL_FORMAT_UHJ4CHN_ALAW_SOFT, FmtUHJ4, FmtAlaw }, - }}; + static constexpr std::array UserFmtList{ + FormatMap{AL_FORMAT_MONO8, FmtMono, FmtUByte }, + FormatMap{AL_FORMAT_MONO16, FmtMono, FmtShort }, + FormatMap{AL_FORMAT_MONO_I32, FmtMono, FmtInt }, + FormatMap{AL_FORMAT_MONO_FLOAT32, FmtMono, FmtFloat }, + FormatMap{AL_FORMAT_MONO_DOUBLE_EXT, FmtMono, FmtDouble }, + FormatMap{AL_FORMAT_MONO_IMA4, FmtMono, FmtIMA4 }, + FormatMap{AL_FORMAT_MONO_MSADPCM_SOFT, FmtMono, FmtMSADPCM}, + FormatMap{AL_FORMAT_MONO_MULAW, FmtMono, FmtMulaw }, + FormatMap{AL_FORMAT_MONO_ALAW_EXT, FmtMono, FmtAlaw }, + + FormatMap{AL_FORMAT_STEREO8, FmtStereo, FmtUByte }, + FormatMap{AL_FORMAT_STEREO16, FmtStereo, FmtShort }, + FormatMap{AL_FORMAT_STEREO_I32, FmtStereo, FmtInt }, + FormatMap{AL_FORMAT_STEREO_FLOAT32, FmtStereo, FmtFloat }, + FormatMap{AL_FORMAT_STEREO_DOUBLE_EXT, FmtStereo, FmtDouble }, + FormatMap{AL_FORMAT_STEREO_IMA4, FmtStereo, FmtIMA4 }, + FormatMap{AL_FORMAT_STEREO_MSADPCM_SOFT, FmtStereo, FmtMSADPCM}, + FormatMap{AL_FORMAT_STEREO_MULAW, FmtStereo, FmtMulaw }, + FormatMap{AL_FORMAT_STEREO_ALAW_EXT, FmtStereo, FmtAlaw }, + + FormatMap{AL_FORMAT_REAR8, FmtRear, FmtUByte}, + FormatMap{AL_FORMAT_REAR16, FmtRear, FmtShort}, + FormatMap{AL_FORMAT_REAR32, FmtRear, FmtFloat}, + FormatMap{AL_FORMAT_REAR_I32, FmtRear, FmtInt }, + FormatMap{AL_FORMAT_REAR_FLOAT32, FmtRear, FmtFloat}, + FormatMap{AL_FORMAT_REAR_MULAW, FmtRear, FmtMulaw}, + + FormatMap{AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtUByte}, + FormatMap{AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort}, + + FormatMap{AL_FORMAT_QUAD8, FmtQuad, FmtUByte}, + FormatMap{AL_FORMAT_QUAD16, FmtQuad, FmtShort}, + FormatMap{AL_FORMAT_QUAD32, FmtQuad, FmtFloat}, + FormatMap{AL_FORMAT_QUAD_I32, FmtQuad, FmtInt }, + FormatMap{AL_FORMAT_QUAD_FLOAT32, FmtQuad, FmtFloat}, + FormatMap{AL_FORMAT_QUAD_MULAW, FmtQuad, FmtMulaw}, + + FormatMap{AL_FORMAT_51CHN8, FmtX51, FmtUByte}, + FormatMap{AL_FORMAT_51CHN16, FmtX51, FmtShort}, + FormatMap{AL_FORMAT_51CHN32, FmtX51, FmtFloat}, + FormatMap{AL_FORMAT_51CHN_I32, FmtX51, FmtInt }, + FormatMap{AL_FORMAT_51CHN_FLOAT32, FmtX51, FmtFloat}, + FormatMap{AL_FORMAT_51CHN_MULAW, FmtX51, FmtMulaw}, + + FormatMap{AL_FORMAT_61CHN8, FmtX61, FmtUByte}, + FormatMap{AL_FORMAT_61CHN16, FmtX61, FmtShort}, + FormatMap{AL_FORMAT_61CHN32, FmtX61, FmtFloat}, + FormatMap{AL_FORMAT_61CHN_I32, FmtX61, FmtInt }, + FormatMap{AL_FORMAT_61CHN_FLOAT32, FmtX61, FmtFloat}, + FormatMap{AL_FORMAT_61CHN_MULAW, FmtX61, FmtMulaw}, + + FormatMap{AL_FORMAT_71CHN8, FmtX71, FmtUByte}, + FormatMap{AL_FORMAT_71CHN16, FmtX71, FmtShort}, + FormatMap{AL_FORMAT_71CHN32, FmtX71, FmtFloat}, + FormatMap{AL_FORMAT_71CHN_I32, FmtX71, FmtInt }, + FormatMap{AL_FORMAT_71CHN_FLOAT32, FmtX71, FmtFloat}, + FormatMap{AL_FORMAT_71CHN_MULAW, FmtX71, FmtMulaw}, + + FormatMap{AL_FORMAT_BFORMAT2D_8, FmtBFormat2D, FmtUByte}, + FormatMap{AL_FORMAT_BFORMAT2D_16, FmtBFormat2D, FmtShort}, + FormatMap{AL_FORMAT_BFORMAT2D_FLOAT32, FmtBFormat2D, FmtFloat}, + FormatMap{AL_FORMAT_BFORMAT2D_MULAW, FmtBFormat2D, FmtMulaw}, + + FormatMap{AL_FORMAT_BFORMAT3D_8, FmtBFormat3D, FmtUByte}, + FormatMap{AL_FORMAT_BFORMAT3D_16, FmtBFormat3D, FmtShort}, + FormatMap{AL_FORMAT_BFORMAT3D_FLOAT32, FmtBFormat3D, FmtFloat}, + FormatMap{AL_FORMAT_BFORMAT3D_MULAW, FmtBFormat3D, FmtMulaw}, + + FormatMap{AL_FORMAT_UHJ2CHN8_SOFT, FmtUHJ2, FmtUByte }, + FormatMap{AL_FORMAT_UHJ2CHN16_SOFT, FmtUHJ2, FmtShort }, + FormatMap{AL_FORMAT_UHJ2CHN_I32, FmtUHJ2, FmtInt }, + FormatMap{AL_FORMAT_UHJ2CHN_FLOAT32_SOFT, FmtUHJ2, FmtFloat }, + FormatMap{AL_FORMAT_UHJ2CHN_MULAW_SOFT, FmtUHJ2, FmtMulaw }, + FormatMap{AL_FORMAT_UHJ2CHN_ALAW_SOFT, FmtUHJ2, FmtAlaw }, + FormatMap{AL_FORMAT_UHJ2CHN_IMA4_SOFT, FmtUHJ2, FmtIMA4 }, + FormatMap{AL_FORMAT_UHJ2CHN_MSADPCM_SOFT, FmtUHJ2, FmtMSADPCM}, + + FormatMap{AL_FORMAT_UHJ3CHN8_SOFT, FmtUHJ3, FmtUByte}, + FormatMap{AL_FORMAT_UHJ3CHN16_SOFT, FmtUHJ3, FmtShort}, + FormatMap{AL_FORMAT_UHJ3CHN_I32, FmtUHJ3, FmtInt }, + FormatMap{AL_FORMAT_UHJ3CHN_FLOAT32_SOFT, FmtUHJ3, FmtFloat}, + FormatMap{AL_FORMAT_UHJ3CHN_MULAW_SOFT, FmtUHJ3, FmtMulaw}, + FormatMap{AL_FORMAT_UHJ3CHN_ALAW_SOFT, FmtUHJ3, FmtAlaw }, + + FormatMap{AL_FORMAT_UHJ4CHN8_SOFT, FmtUHJ4, FmtUByte}, + FormatMap{AL_FORMAT_UHJ4CHN16_SOFT, FmtUHJ4, FmtShort}, + FormatMap{AL_FORMAT_UHJ4CHN_I32, FmtUHJ4, FmtInt }, + FormatMap{AL_FORMAT_UHJ4CHN_FLOAT32_SOFT, FmtUHJ4, FmtFloat}, + FormatMap{AL_FORMAT_UHJ4CHN_MULAW_SOFT, FmtUHJ4, FmtMulaw}, + FormatMap{AL_FORMAT_UHJ4CHN_ALAW_SOFT, FmtUHJ4, FmtAlaw }, + }; for(const auto &fmt : UserFmtList) { diff --git a/alc/alc.cpp b/alc/alc.cpp index 96b641f7..08ef0063 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -740,29 +740,39 @@ std::optional DecomposeDevFormat(ALenum format) DevFmtChannels channels; DevFmtType type; } list[] = { - { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte }, - { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort }, + { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte }, + { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort }, + { AL_FORMAT_MONO_I32, DevFmtMono, DevFmtInt }, { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat }, - { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte }, - { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort }, + { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte }, + { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort }, + { AL_FORMAT_STEREO_I32, DevFmtStereo, DevFmtInt }, { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat }, - { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte }, - { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort }, - { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat }, - - { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte }, - { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort }, - { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat }, - - { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte }, - { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort }, - { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat }, - - { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte }, - { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort }, - { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat }, + { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte }, + { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort }, + { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat }, + { AL_FORMAT_QUAD_I32, DevFmtQuad, DevFmtInt }, + { AL_FORMAT_QUAD_FLOAT32, DevFmtQuad, DevFmtFloat }, + + { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte }, + { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort }, + { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat }, + { AL_FORMAT_51CHN_I32, DevFmtX51, DevFmtInt }, + { AL_FORMAT_51CHN_FLOAT32, DevFmtX51, DevFmtFloat }, + + { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte }, + { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort }, + { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat }, + { AL_FORMAT_61CHN_I32, DevFmtX61, DevFmtInt }, + { AL_FORMAT_61CHN_FLOAT32, DevFmtX61, DevFmtFloat }, + + { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte }, + { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort }, + { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat }, + { AL_FORMAT_71CHN_I32, DevFmtX71, DevFmtInt }, + { AL_FORMAT_71CHN_FLOAT32, DevFmtX71, DevFmtFloat }, }; for(const auto &item : list) diff --git a/alc/export_list.h b/alc/export_list.h index 2ef0d777..47b04a08 100644 --- a/alc/export_list.h +++ b/alc/export_list.h @@ -598,6 +598,46 @@ inline const EnumExport alcEnumerations[]{ DECL(AL_FORMAT_BFORMAT3D_FLOAT32), DECL(AL_FORMAT_BFORMAT3D_MULAW), + DECL(AL_FORMAT_UHJ2CHN8_SOFT), + DECL(AL_FORMAT_UHJ2CHN16_SOFT), + DECL(AL_FORMAT_UHJ2CHN_FLOAT32_SOFT), + DECL(AL_FORMAT_UHJ3CHN8_SOFT), + DECL(AL_FORMAT_UHJ3CHN16_SOFT), + DECL(AL_FORMAT_UHJ3CHN_FLOAT32_SOFT), + DECL(AL_FORMAT_UHJ4CHN8_SOFT), + DECL(AL_FORMAT_UHJ4CHN16_SOFT), + DECL(AL_FORMAT_UHJ4CHN_FLOAT32_SOFT), + DECL(AL_STEREO_MODE_SOFT), + DECL(AL_NORMAL_SOFT), + DECL(AL_SUPER_STEREO_SOFT), + DECL(AL_SUPER_STEREO_WIDTH_SOFT), + + DECL(AL_FORMAT_UHJ2CHN_MULAW_SOFT), + DECL(AL_FORMAT_UHJ2CHN_ALAW_SOFT), + DECL(AL_FORMAT_UHJ2CHN_IMA4_SOFT), + DECL(AL_FORMAT_UHJ2CHN_MSADPCM_SOFT), + DECL(AL_FORMAT_UHJ3CHN_MULAW_SOFT), + DECL(AL_FORMAT_UHJ3CHN_ALAW_SOFT), + DECL(AL_FORMAT_UHJ4CHN_MULAW_SOFT), + DECL(AL_FORMAT_UHJ4CHN_ALAW_SOFT), + + DECL(AL_FORMAT_MONO_I32), + DECL(AL_FORMAT_STEREO_I32), + DECL(AL_FORMAT_REAR_I32), + DECL(AL_FORMAT_QUAD_I32), + DECL(AL_FORMAT_51CHN_I32), + DECL(AL_FORMAT_61CHN_I32), + DECL(AL_FORMAT_71CHN_I32), + DECL(AL_FORMAT_UHJ2CHN_I32), + DECL(AL_FORMAT_UHJ3CHN_I32), + DECL(AL_FORMAT_UHJ4CHN_I32), + + DECL(AL_FORMAT_REAR_FLOAT32), + DECL(AL_FORMAT_QUAD_FLOAT32), + DECL(AL_FORMAT_51CHN_FLOAT32), + DECL(AL_FORMAT_61CHN_FLOAT32), + DECL(AL_FORMAT_71CHN_FLOAT32), + DECL(AL_FREQUENCY), DECL(AL_BITS), DECL(AL_CHANNELS), @@ -823,29 +863,6 @@ inline const EnumExport alcEnumerations[]{ DECL(AL_EFFECT_CONVOLUTION_SOFT), DECL(AL_EFFECTSLOT_STATE_SOFT), - DECL(AL_FORMAT_UHJ2CHN8_SOFT), - DECL(AL_FORMAT_UHJ2CHN16_SOFT), - DECL(AL_FORMAT_UHJ2CHN_FLOAT32_SOFT), - DECL(AL_FORMAT_UHJ3CHN8_SOFT), - DECL(AL_FORMAT_UHJ3CHN16_SOFT), - DECL(AL_FORMAT_UHJ3CHN_FLOAT32_SOFT), - DECL(AL_FORMAT_UHJ4CHN8_SOFT), - DECL(AL_FORMAT_UHJ4CHN16_SOFT), - DECL(AL_FORMAT_UHJ4CHN_FLOAT32_SOFT), - DECL(AL_STEREO_MODE_SOFT), - DECL(AL_NORMAL_SOFT), - DECL(AL_SUPER_STEREO_SOFT), - DECL(AL_SUPER_STEREO_WIDTH_SOFT), - - DECL(AL_FORMAT_UHJ2CHN_MULAW_SOFT), - DECL(AL_FORMAT_UHJ2CHN_ALAW_SOFT), - DECL(AL_FORMAT_UHJ2CHN_IMA4_SOFT), - DECL(AL_FORMAT_UHJ2CHN_MSADPCM_SOFT), - DECL(AL_FORMAT_UHJ3CHN_MULAW_SOFT), - DECL(AL_FORMAT_UHJ3CHN_ALAW_SOFT), - DECL(AL_FORMAT_UHJ4CHN_MULAW_SOFT), - DECL(AL_FORMAT_UHJ4CHN_ALAW_SOFT), - DECL(AL_DONT_CARE_EXT), DECL(AL_DEBUG_OUTPUT_EXT), DECL(AL_DEBUG_CALLBACK_FUNCTION_EXT), diff --git a/alc/inprogext.h b/alc/inprogext.h index a145b8e4..8764c85b 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -398,6 +398,26 @@ ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, AL #endif #endif +#ifndef AL_EXT_int32 +#define AL_EXT_int32 +#define AL_FORMAT_MONO_I32 0x9999 /* TBD, same as AL_FORMAT_MONO32 */ +#define AL_FORMAT_STEREO_I32 0x1203 /* Same as AL_FORMAT_STEREO32 */ +#define AL_FORMAT_REAR_I32 0x19D9 +#define AL_FORMAT_QUAD_I32 0x19DA +#define AL_FORMAT_51CHN_I32 0x19DB +#define AL_FORMAT_61CHN_I32 0x19DC +#define AL_FORMAT_71CHN_I32 0x19DD +#define AL_FORMAT_UHJ2CHN_I32 0x19DE +#define AL_FORMAT_UHJ3CHN_I32 0x19DF +#define AL_FORMAT_UHJ4CHN_I32 0x19E0 + +#define AL_FORMAT_REAR_FLOAT32 0x19E1 +#define AL_FORMAT_QUAD_FLOAT32 0x19E2 +#define AL_FORMAT_51CHN_FLOAT32 0x19E3 +#define AL_FORMAT_61CHN_FLOAT32 0x19E4 +#define AL_FORMAT_71CHN_FLOAT32 0x19E5 +#endif + /* Non-standard exports. Not part of any extension. */ AL_API const ALchar* AL_APIENTRY alsoft_get_version(void) noexcept; -- cgit v1.2.3 From 62c5b38c811ac1552a1cadb00604477ebb39c646 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 21 Nov 2023 14:40:15 -0800 Subject: Don't combine both early reflection taps for the late reverb It doesn't make much sense to include both early reflections to feed the late reverb, since it increases the total energy in the reverb decay. This better fits with the design described in papers for this type of reverb, and seems to better match volume levels of hardware EAX/EFX reverb (though there are still some apparent differences). Note that this adds a bit more delay to the late reverb, specifically EARLY_LINE_LENGTHS[0] * density_mult. This can be compensated for somewhat by reducing the late reverb delay by that amount (clamping to a minimum of 0). Alternatively, adjust the delay lines for the second early tap to have a zero- delay pass-through line with 3 delay lines (as opposed to the current 4 delay lines), as suggested by the paper "ADAPTING ARTIFICIAL REVERBERATION ARCHITECTURES FOR B-FORMAT SIGNAL PROCESSING". Although doing so may require additional adjustments to the delay lengths and gains to avoid the 0-length lines accumulating unattenuated copies of the signal for the early reflection output. --- alc/effects/reverb.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'alc') diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index 0e63c7bc..5068c8d7 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -1482,8 +1482,9 @@ void ReverbPipeline::processEarly(size_t offset, const size_t samplesToDo, feedb_tap &= early_delay.Mask; size_t td{minz(early_delay.Mask+1 - feedb_tap, todo - i)}; do { - tempSamples[j][i] += early_delay.Line[feedb_tap++][j]*feedb_coeff; - out[i] = tempSamples[j][i]; + float sample{early_delay.Line[feedb_tap++][j]}; + out[i] = tempSamples[j][i] + sample*feedb_coeff; + tempSamples[j][i] = sample; ++i; } while(--td); } -- cgit v1.2.3 From 403aaa4fdd0ddca725cb06560dda99f8766e0750 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 22 Nov 2023 07:28:50 -0800 Subject: Compensate the late delay tap by the early delay buffer --- alc/effects/reverb.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'alc') diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index 5068c8d7..1af50559 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -1018,8 +1018,12 @@ void ReverbPipeline::updateDelayLine(const float earlyDelay, const float lateDel mEarlyDelayTap[i][1] = float2uint((earlyDelay+length) * frequency); mEarlyDelayCoeff[i] = CalcDecayCoeff(length, decayTime); + /* Reduce the late delay tap by the shortest early delay line length to + * compensate for the late line input being fed by the delayed early + * output. + */ length = (LATE_LINE_LENGTHS[i] - LATE_LINE_LENGTHS.front())/float{NUM_LINES}*density_mult + - lateDelay; + std::max(lateDelay - EARLY_LINE_LENGTHS[0]*density_mult, 0.0f); mLateDelayTap[i][1] = float2uint(length * frequency); } } -- cgit v1.2.3 From 1f6d19fd4a4fec15da4181a40ed443174bb95384 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 22 Nov 2023 13:55:51 -0800 Subject: Do proper spatial reflection in reverb Instead of "bouncing" the lines by indexing backwards for a not-quite-spatial- opposite, do a proper mix that moves each line response to its true spatial opposite position. --- alc/effects/reverb.cpp | 71 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 16 deletions(-) (limited to 'alc') diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index 1af50559..e0d59f36 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -98,8 +98,6 @@ struct CubicFilter { constexpr CubicFilter gCubicTable; -using namespace std::placeholders; - /* Max samples per process iteration. Used to limit the size needed for * temporary buffers. Must be a multiple of 4 for SIMD alignment. */ @@ -122,12 +120,9 @@ constexpr size_t NUM_LINES{4u}; constexpr float MODULATION_DEPTH_COEFF{0.05f}; -/* The B-Format to A-Format conversion matrix. The arrangement of rows is - * deliberately chosen to align the resulting lines to their spatial opposites - * (0:above front left <-> 3:above back right, 1:below front right <-> 2:below - * back left). It's not quite opposite, since the A-Format results in a - * tetrahedron, but it's close enough. Should the model be extended to 8-lines - * in the future, true opposites can be used. +/* The B-Format to (W-normalized) A-Format conversion matrix. This produces a + * tetrahedral array of discrete signals (boosted by a factor of sqrt(3), to + * reduce the error introduced in the conversion). */ alignas(16) constexpr float B2A[NUM_LINES][NUM_LINES]{ { 0.5f, 0.5f, 0.5f, 0.5f }, @@ -136,7 +131,9 @@ alignas(16) constexpr float B2A[NUM_LINES][NUM_LINES]{ { 0.5f, -0.5f, 0.5f, -0.5f } }; -/* Converts A-Format to B-Format for early reflections. */ +/* Converts (W-normalized) A-Format to B-Format for early reflections (scaled + * by 1/sqrt(3) to compensate for the boost in the B2A matrix). + */ alignas(16) constexpr std::array,NUM_LINES> EarlyA2B{{ {{ 0.5f, 0.5f, 0.5f, 0.5f }}, {{ 0.5f, -0.5f, 0.5f, -0.5f }}, @@ -144,7 +141,11 @@ alignas(16) constexpr std::array,NUM_LINES> EarlyA2B {{ 0.5f, 0.5f, -0.5f, -0.5f }} }}; -/* Converts A-Format to B-Format for late reverb. */ +/* Converts (W-normalized) A-Format to B-Format for late reverb (scaled + * by 1/sqrt(3) to compensate for the boost in the B2A matrix). The response + * is rotated around Z (ambisonic X) so that the front lines are placed + * horizontally in front, and the rear lines are placed vertically in back. + */ constexpr auto InvSqrt2 = static_cast(1.0/al::numbers::sqrt2); alignas(16) constexpr std::array,NUM_LINES> LateA2B{{ {{ 0.5f, 0.5f, 0.5f, 0.5f }}, @@ -330,6 +331,39 @@ struct DelayLineI { } while(--td); } } + + /* Writes the given input lines to the delay buffer, applying a geometric + * reflection. This effectively applies the matrix + * + * [ -1/2 +1/2 +1/2 +1/2 ] + * [ +1/2 -1/2 +1/2 +1/2 ] + * [ +1/2 +1/2 -1/2 +1/2 ] + * [ +1/2 +1/2 +1/2 -1/2 ] + * + * to the four input lines when writing to the delay buffer. The effect on + * the B-Format signal is negating X,Y,Z, moving each response to its + * spatially opposite location. + */ + void writeReflected(size_t offset, const al::span in, + const size_t count) const noexcept + { + ASSUME(count > 0); + for(size_t i{0u};i < count;) + { + offset &= Mask; + size_t td{minz(Mask+1 - offset, count - i)}; + do { + const std::array src{in[0][i], in[1][i], in[2][i], in[3][i]}; + ++i; + + Line[offset][0] = ( src[1] + src[2] + src[3] - src[0]) * 0.5f; + Line[offset][1] = (src[0] + src[2] + src[3] - src[1]) * 0.5f; + Line[offset][2] = (src[0] + src[1] + src[3] - src[2]) * 0.5f; + Line[offset][3] = (src[0] + src[1] + src[2] - src[3]) * 0.5f; + ++offset; + } while(--td); + } + } }; struct VecAllpass { @@ -1337,7 +1371,9 @@ inline auto VectorPartialScatter(const std::array &RESTRICT in, }}; } -/* Utilizes the above, but reverses the input channels. */ +/* Utilizes the above, but also applies a geometric reflection on the input + * channels. + */ void VectorScatterRevDelayIn(const DelayLineI delay, size_t offset, const float xCoeff, const float yCoeff, const al::span in, const size_t count) { @@ -1348,9 +1384,13 @@ void VectorScatterRevDelayIn(const DelayLineI delay, size_t offset, const float offset &= delay.Mask; size_t td{minz(delay.Mask+1 - offset, count-i)}; do { - std::array f; - for(size_t j{0u};j < NUM_LINES;j++) - f[NUM_LINES-1-j] = in[j][i]; + std::array src{in[0][i], in[1][i], in[2][i], in[3][i]}; + std::array f{ + ( src[1] + src[2] + src[3] - src[0]) * 0.5f, + (src[0] + src[2] + src[3] - src[1]) * 0.5f, + (src[0] + src[1] + src[3] - src[2]) * 0.5f, + (src[0] + src[1] + src[2] - src[3]) * 0.5f + }; ++i; delay.Line[offset++] = VectorPartialScatter(f, xCoeff, yCoeff); @@ -1473,8 +1513,7 @@ void ReverbPipeline::processEarly(size_t offset, const size_t samplesToDo, /* Apply a delay and bounce to generate secondary reflections, combine * with the primary reflections and write out the result for mixing. */ - for(size_t j{0u};j < NUM_LINES;j++) - early_delay.write(offset, NUM_LINES-1-j, tempSamples[j].data(), todo); + early_delay.writeReflected(offset, tempSamples, todo); for(size_t j{0u};j < NUM_LINES;j++) { size_t feedb_tap{offset - mEarly.Offset[j]}; -- cgit v1.2.3 From c03603b58d4cf6a25d36bca00305970bc9f163b4 Mon Sep 17 00:00:00 2001 From: MathiusD Date: Sun, 26 Nov 2023 03:33:00 +0100 Subject: Add query fonction in ALC_SOFT_system_events unreleased extension (#938) * feat(ALC_SOFT_system_events): Add alcEventIsSupportedSOFT method in ALC_SOFT_system_events unreleased extension The purpose of this addition (to my collection) are allow to retrieve which events are supported and if events are fully supported or if some case isn't managed for some reason For exemple only some backends provide system events: * pipewire -> Full support of extension * wasapi -> Full support of extension * pulseaudio -> Support of add and remove devices events only * coreaudio -> Support of default device change only * feat(ALC_SOFT_system_events): Fix typo in alext.h Cf following review : https://github.com/kcat/openal-soft/pull/938#discussion_r1404509828 * feat(ALC_SOFT_system_events): Remove ALC_EVENT_NOT_SUPPORTED_SOFT token Cf following discussions between this comment : https://github.com/kcat/openal-soft/pull/938#issuecomment-1825876452 to this comment : https://github.com/kcat/openal-soft/pull/938#issuecomment-1826419406 --- alc/alc.cpp | 40 +++++++++++++++++++++++++++++++++++ alc/backends/base.h | 5 +++++ alc/backends/coreaudio.cpp | 11 +++++++++- alc/backends/coreaudio.h | 2 ++ alc/backends/pipewire.cpp | 17 ++++++++++++++- alc/backends/pipewire.h | 2 ++ alc/backends/pulseaudio.cpp | 14 ++++++++++++- alc/backends/pulseaudio.h | 2 ++ alc/backends/wasapi.cpp | 17 ++++++++++++++- alc/backends/wasapi.h | 2 ++ alc/events.cpp | 26 +++++++++++------------ alc/events.h | 8 +++++++ alc/export_list.h | 1 + include/AL/alext.h | 4 ++++ utils/openal-info.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 184 insertions(+), 18 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index 08ef0063..be41f278 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -69,6 +69,7 @@ #include "al/filter.h" #include "al/listener.h" #include "al/source.h" +#include "alc/events.h" #include "albit.h" #include "alconfig.h" #include "almalloc.h" @@ -3469,3 +3470,42 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, ResetDeviceParams(dev.get(), attribs); return ALC_TRUE; } + +/************************************************ + * ALC event query functions + ************************************************/ + +FORCE_ALIGN ALCenum ALC_APIENTRY alcEventIsSupportedSOFT(ALCenum eventType, ALCenum deviceType) noexcept +{ + auto etype = alc::GetEventType(eventType); + if(!etype) + { + WARN("Invalid event type: 0x%04x\n", eventType); + alcSetError(nullptr, ALC_INVALID_ENUM); + return ALC_EVENT_NOT_SUPPORTED_SOFT; + } + switch(deviceType) + { + case al::to_underlying(alc::DeviceType::Playback): + { + if(!PlaybackFactory) + { + return ALC_EVENT_NOT_SUPPORTED_SOFT; + } + + auto supported = PlaybackFactory->queryEventSupport(*etype, BackendType::Playback); + return al::to_underlying(supported); + } + case al::to_underlying(alc::DeviceType::Capture): + { + if(!CaptureFactory) + { + return ALC_EVENT_NOT_SUPPORTED_SOFT; + } + + auto supported = CaptureFactory->queryEventSupport(*etype, BackendType::Capture); + return al::to_underlying(supported); + } + } + return ALC_EVENT_NOT_SUPPORTED_SOFT; +} \ No newline at end of file diff --git a/alc/backends/base.h b/alc/backends/base.h index a4079fe4..ea3b57a3 100644 --- a/alc/backends/base.h +++ b/alc/backends/base.h @@ -11,6 +11,7 @@ #include "core/device.h" #include "core/except.h" +#include "alc/events.h" using uint = unsigned int; @@ -79,6 +80,10 @@ struct BackendFactory { virtual bool querySupport(BackendType type) = 0; + virtual alc::EventSupport queryEventSupport(alc::EventType eventType, BackendType type) { + return alc::EventSupport::NoSupport; + } + virtual std::string probe(BackendType type) = 0; virtual BackendPtr createBackend(DeviceBase *device, BackendType type) = 0; diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index 1684545b..eb4e5880 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -39,7 +39,6 @@ #include "core/device.h" #include "core/logging.h" #include "ringbuffer.h" -#include "alc/events.h" #include #include @@ -1013,3 +1012,13 @@ BackendPtr CoreAudioBackendFactory::createBackend(DeviceBase *device, BackendTyp return BackendPtr{new CoreAudioCapture{device}}; return nullptr; } + +alc::EventSupport CoreAudioBackendFactory::queryEventSupport(alc::EventType eventType, BackendType type) +{ + switch(eventType) { + case alc::EventType::DefaultDeviceChanged: { + return alc::EventSupport::FullSupport; + } + } + return alc::EventSupport::NoSupport; +} diff --git a/alc/backends/coreaudio.h b/alc/backends/coreaudio.h index 1252edde..6ea4307c 100644 --- a/alc/backends/coreaudio.h +++ b/alc/backends/coreaudio.h @@ -9,6 +9,8 @@ public: bool querySupport(BackendType type) override; + alc::EventSupport queryEventSupport(alc::EventType eventType, BackendType type) override; + std::string probe(BackendType type) override; BackendPtr createBackend(DeviceBase *device, BackendType type) override; diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 6cfb31a4..d1a9d095 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -40,7 +40,6 @@ #include "albit.h" #include "alc/alconfig.h" -#include "alc/events.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -2266,3 +2265,19 @@ BackendFactory &PipeWireBackendFactory::getFactory() static PipeWireBackendFactory factory{}; return factory; } + +alc::EventSupport PipeWireBackendFactory::queryEventSupport(alc::EventType eventType, BackendType type) +{ + switch(eventType) { + case alc::EventType::DefaultDeviceChanged: { + return alc::EventSupport::FullSupport; + } + case alc::EventType::DeviceAdded: { + return alc::EventSupport::FullSupport; + } + case alc::EventType::DeviceRemoved: { + return alc::EventSupport::FullSupport; + } + } + return alc::EventSupport::NoSupport; +} \ No newline at end of file diff --git a/alc/backends/pipewire.h b/alc/backends/pipewire.h index 5f930239..5493684f 100644 --- a/alc/backends/pipewire.h +++ b/alc/backends/pipewire.h @@ -13,6 +13,8 @@ public: bool querySupport(BackendType type) override; + alc::EventSupport queryEventSupport(alc::EventType eventType, BackendType type) override; + std::string probe(BackendType type) override; BackendPtr createBackend(DeviceBase *device, BackendType type) override; diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index e2cea8a8..23ed1415 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -41,7 +41,6 @@ #include "albit.h" #include "alc/alconfig.h" -#include "alc/events.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -1491,3 +1490,16 @@ BackendFactory &PulseBackendFactory::getFactory() static PulseBackendFactory factory{}; return factory; } + +alc::EventSupport PulseBackendFactory::queryEventSupport(alc::EventType eventType, BackendType type) +{ + switch(eventType) { + case alc::EventType::DeviceAdded: { + return alc::EventSupport::FullSupport; + } + case alc::EventType::DeviceRemoved: { + return alc::EventSupport::FullSupport; + } + } + return alc::EventSupport::NoSupport; +} diff --git a/alc/backends/pulseaudio.h b/alc/backends/pulseaudio.h index 6690fe8a..4752a891 100644 --- a/alc/backends/pulseaudio.h +++ b/alc/backends/pulseaudio.h @@ -9,6 +9,8 @@ public: bool querySupport(BackendType type) override; + alc::EventSupport queryEventSupport(alc::EventType eventType, BackendType type) override; + std::string probe(BackendType type) override; BackendPtr createBackend(DeviceBase *device, BackendType type) override; diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 37151ef9..a4d6ea2f 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -60,7 +60,6 @@ #include "albit.h" #include "alc/alconfig.h" -#include "alc/events.h" #include "alnumeric.h" #include "alspan.h" #include "althrd_setname.h" @@ -2741,3 +2740,19 @@ BackendFactory &WasapiBackendFactory::getFactory() static WasapiBackendFactory factory{}; return factory; } + +alc::EventSupport WasapiBackendFactory::queryEventSupport(alc::EventType eventType, BackendType type) +{ + switch(eventType) { + case alc::EventType::DefaultDeviceChanged: { + return alc::EventSupport::FullSupport; + } + case alc::EventType::DeviceAdded: { + return alc::EventSupport::FullSupport; + } + case alc::EventType::DeviceRemoved: { + return alc::EventSupport::FullSupport; + } + } + return alc::EventSupport::NoSupport; +} diff --git a/alc/backends/wasapi.h b/alc/backends/wasapi.h index bb2671ee..12fd95ef 100644 --- a/alc/backends/wasapi.h +++ b/alc/backends/wasapi.h @@ -9,6 +9,8 @@ public: bool querySupport(BackendType type) override; + alc::EventSupport queryEventSupport(alc::EventType eventType, BackendType type) override; + std::string probe(BackendType type) override; BackendPtr createBackend(DeviceBase *device, BackendType type) override; diff --git a/alc/events.cpp b/alc/events.cpp index a80faf8a..1010a338 100644 --- a/alc/events.cpp +++ b/alc/events.cpp @@ -3,8 +3,6 @@ #include "events.h" -#include - #include "alspan.h" #include "core/logging.h" #include "device.h" @@ -12,17 +10,6 @@ namespace { -std::optional GetEventType(ALCenum type) -{ - switch(type) - { - case ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT: return alc::EventType::DefaultDeviceChanged; - case ALC_EVENT_TYPE_DEVICE_ADDED_SOFT: return alc::EventType::DeviceAdded; - case ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT: return alc::EventType::DeviceRemoved; - } - return std::nullopt; -} - ALCenum EnumFromEventType(const alc::EventType type) { switch(type) @@ -39,6 +26,17 @@ ALCenum EnumFromEventType(const alc::EventType type) namespace alc { +std::optional GetEventType(ALCenum type) +{ + switch(type) + { + case ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT: return alc::EventType::DefaultDeviceChanged; + case ALC_EVENT_TYPE_DEVICE_ADDED_SOFT: return alc::EventType::DeviceAdded; + case ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT: return alc::EventType::DeviceRemoved; + } + return std::nullopt; +} + void Event(EventType eventType, DeviceType deviceType, ALCdevice *device, std::string_view message) noexcept { auto eventlock = std::unique_lock{EventMutex}; @@ -73,7 +71,7 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const AL alc::EventBitSet eventSet{0}; for(ALCenum type : al::span{events, static_cast(count)}) { - auto etype = GetEventType(type); + auto etype = alc::GetEventType(type); if(!etype) { WARN("Invalid event type: 0x%04x\n", type); diff --git a/alc/events.h b/alc/events.h index 4acc505d..3f53ec76 100644 --- a/alc/events.h +++ b/alc/events.h @@ -6,6 +6,7 @@ #include #include +#include #include @@ -19,6 +20,13 @@ enum class EventType : uint8_t { Count }; +std::optional GetEventType(ALCenum type); + +enum class EventSupport : ALCenum { + FullSupport = ALC_EVENT_SUPPORTED_SOFT, + NoSupport = ALC_EVENT_NOT_SUPPORTED_SOFT, +}; + enum class DeviceType : ALCenum { Playback = ALC_PLAYBACK_DEVICE_SOFT, Capture = ALC_CAPTURE_DEVICE_SOFT, diff --git a/alc/export_list.h b/alc/export_list.h index 47b04a08..c5af1ab0 100644 --- a/alc/export_list.h +++ b/alc/export_list.h @@ -56,6 +56,7 @@ inline const FuncExport alcFunctions[]{ DECL(alcReopenDeviceSOFT), + DECL(alcEventIsSupportedSOFT), DECL(alcEventControlSOFT), DECL(alcEventCallbackSOFT), diff --git a/include/AL/alext.h b/include/AL/alext.h index b99d6aac..c75e0770 100644 --- a/include/AL/alext.h +++ b/include/AL/alext.h @@ -720,11 +720,15 @@ void AL_APIENTRY alGetObjectLabelEXT(ALenum identifier, ALuint name, ALsizei buf #define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D6 #define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D7 #define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D8 +#define ALC_EVENT_SUPPORTED_SOFT 0x19D9 +#define ALC_EVENT_NOT_SUPPORTED_SOFT 0x19DA typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCenum deviceType, ALCdevice *device, ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17; +typedef ALCenum (ALC_APIENTRY*LPALCEVENTISSUPPORTEDSOFT)(ALCenum eventType, ALCenum deviceType) ALC_API_NOEXCEPT17; typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT17; typedef void (ALC_APIENTRY*LPALCEVENTCALLBACKSOFT)(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES +ALCenum ALC_APIENTRY alcEventIsSupportedSOFT(ALCenum eventType, ALCenum deviceType) ALC_API_NOEXCEPT; ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT; void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT; #endif diff --git a/utils/openal-info.c b/utils/openal-info.c index 0af27422..11c49245 100644 --- a/utils/openal-info.c +++ b/utils/openal-info.c @@ -230,6 +230,56 @@ static void printModeInfo(ALCdevice *device) } } +static void printALCSOFTSystemEventIsSupportedResult(LPALCEVENTISSUPPORTEDSOFT alcEventIsSupportedSOFT, ALCenum eventType, ALCenum deviceType) +{ + if (alcEventIsSupportedSOFT == NULL) + { + printf("ERROR (alcEventIsSupportedSOFT missing)\n"); + return; + } + ALCenum supported = alcEventIsSupportedSOFT(eventType, deviceType); + if (supported == ALC_EVENT_SUPPORTED_SOFT) + { + printf("SUPPORTED\n"); + } + else if (supported == ALC_EVENT_NOT_SUPPORTED_SOFT) + { + printf("NOT SUPPORTED\n"); + } + else + { + printf("UNEXPECTED VALUE : %d\n", supported); + } +} + +static void printALC_SOFT_system_event(void) +{ + printf("ALC_SOFT_system_events:"); + if (alcIsExtensionPresent(NULL, "ALC_SOFT_system_events")) + { + static LPALCEVENTISSUPPORTEDSOFT alcEventIsSupportedSOFT; + alcEventIsSupportedSOFT = FUNCTION_CAST(LPALCEVENTISSUPPORTEDSOFT, alGetProcAddress("alcEventIsSupportedSOFT")); + printf(" Supported.\n"); + printf(" Events:\n"); + printf(" ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT for ALC_PLAYBACK_DEVICE_SOFT - "); + printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT, ALC_PLAYBACK_DEVICE_SOFT); + printf(" ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT for ALC_CAPTURE_DEVICE_SOFT - "); + printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT, ALC_CAPTURE_DEVICE_SOFT); + printf(" ALC_EVENT_TYPE_DEVICE_ADDED_SOFT for ALC_PLAYBACK_DEVICE_SOFT - "); + printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEVICE_ADDED_SOFT, ALC_PLAYBACK_DEVICE_SOFT); + printf(" ALC_EVENT_TYPE_DEVICE_ADDED_SOFT for ALC_CAPTURE_DEVICE_SOFT - "); + printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEVICE_ADDED_SOFT, ALC_CAPTURE_DEVICE_SOFT); + printf(" ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT for ALC_PLAYBACK_DEVICE_SOFT - "); + printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT, ALC_PLAYBACK_DEVICE_SOFT); + printf(" ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT for ALC_CAPTURE_DEVICE_SOFT - "); + printALCSOFTSystemEventIsSupportedResult(alcEventIsSupportedSOFT, ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT, ALC_CAPTURE_DEVICE_SOFT); + } + else + { + printf(" Not supported.\n"); + } +} + static void printALInfo(void) { printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR)); @@ -435,6 +485,7 @@ int main(int argc, char *argv[]) } printALCInfo(device); printHRTFInfo(device); + printALC_SOFT_system_event(); context = alcCreateContext(device, NULL); if(!context || alcMakeContextCurrent(context) == ALC_FALSE) -- cgit v1.2.3 From 889f2daf1f0453fbbebc7ebba74c58584a335043 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 23 Nov 2023 21:08:56 -0800 Subject: Fix some comments --- alc/effects/reverb.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'alc') diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index e0d59f36..0f1fcca1 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -1450,14 +1450,13 @@ void VecAllpass::process(const al::span samples, siz * same direction as the source) from the main delay line. These are * attenuated and all-pass filtered (based on the diffusion parameter). * - * The early lines are then fed in reverse (according to the approximately - * opposite spatial location of the A-Format lines) to create the secondary + * The early lines are then reflected about the origin to create the secondary * reflections (those arriving from the opposite direction as the source). * * The early response is then completed by combining the primary reflections * with the delayed and attenuated output from the early lines. * - * Finally, the early response is reversed, scattered (based on diffusion), + * Finally, the early response is reflected, scattered (based on diffusion), * and fed into the late reverb section of the main delay line. */ void ReverbPipeline::processEarly(size_t offset, const size_t samplesToDo, -- cgit v1.2.3 From 2a27a2ca5ea0f6b6b8fff065212959ea60021647 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 25 Nov 2023 18:58:00 -0800 Subject: Fix some unused parameter and unhandled enum warnings --- alc/alc.cpp | 35 +++++++++++++++-------------------- alc/backends/base.h | 5 ++--- alc/backends/coreaudio.cpp | 15 ++++++++++----- alc/backends/pipewire.cpp | 23 +++++++++++------------ alc/backends/pulseaudio.cpp | 18 ++++++++++-------- alc/backends/wasapi.cpp | 25 ++++++++++++++----------- 6 files changed, 62 insertions(+), 59 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index be41f278..6017e743 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -3484,28 +3484,23 @@ FORCE_ALIGN ALCenum ALC_APIENTRY alcEventIsSupportedSOFT(ALCenum eventType, ALCe alcSetError(nullptr, ALC_INVALID_ENUM); return ALC_EVENT_NOT_SUPPORTED_SOFT; } + + auto supported = alc::EventSupport::NoSupport; switch(deviceType) { - case al::to_underlying(alc::DeviceType::Playback): - { - if(!PlaybackFactory) - { - return ALC_EVENT_NOT_SUPPORTED_SOFT; - } + case ALC_PLAYBACK_DEVICE_SOFT: + if(PlaybackFactory) + supported = PlaybackFactory->queryEventSupport(*etype, BackendType::Playback); + break; - auto supported = PlaybackFactory->queryEventSupport(*etype, BackendType::Playback); - return al::to_underlying(supported); - } - case al::to_underlying(alc::DeviceType::Capture): - { - if(!CaptureFactory) - { - return ALC_EVENT_NOT_SUPPORTED_SOFT; - } + case ALC_CAPTURE_DEVICE_SOFT: + if(CaptureFactory) + supported = CaptureFactory->queryEventSupport(*etype, BackendType::Capture); + break; - auto supported = CaptureFactory->queryEventSupport(*etype, BackendType::Capture); - return al::to_underlying(supported); - } + default: + WARN("Invalid device type: 0x%04x\n", deviceType); + alcSetError(nullptr, ALC_INVALID_ENUM); } - return ALC_EVENT_NOT_SUPPORTED_SOFT; -} \ No newline at end of file + return al::to_underlying(supported); +} diff --git a/alc/backends/base.h b/alc/backends/base.h index ea3b57a3..eea0d238 100644 --- a/alc/backends/base.h +++ b/alc/backends/base.h @@ -80,9 +80,8 @@ struct BackendFactory { virtual bool querySupport(BackendType type) = 0; - virtual alc::EventSupport queryEventSupport(alc::EventType eventType, BackendType type) { - return alc::EventSupport::NoSupport; - } + virtual alc::EventSupport queryEventSupport(alc::EventType, BackendType) + { return alc::EventSupport::NoSupport; } virtual std::string probe(BackendType type) = 0; diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index eb4e5880..16b0781e 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -1013,12 +1013,17 @@ BackendPtr CoreAudioBackendFactory::createBackend(DeviceBase *device, BackendTyp return nullptr; } -alc::EventSupport CoreAudioBackendFactory::queryEventSupport(alc::EventType eventType, BackendType type) +alc::EventSupport CoreAudioBackendFactory::queryEventSupport(alc::EventType eventType, BackendType) { - switch(eventType) { - case alc::EventType::DefaultDeviceChanged: { - return alc::EventSupport::FullSupport; - } + switch(eventType) + { + case alc::EventType::DefaultDeviceChanged: + return alc::EventSupport::FullSupport; + + case alc::EventType::DeviceAdded: + case alc::EventType::DeviceRemoved: + case alc::EventType::Count: + break; } return alc::EventSupport::NoSupport; } diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index d1a9d095..6a001d7a 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -2266,18 +2266,17 @@ BackendFactory &PipeWireBackendFactory::getFactory() return factory; } -alc::EventSupport PipeWireBackendFactory::queryEventSupport(alc::EventType eventType, BackendType type) +alc::EventSupport PipeWireBackendFactory::queryEventSupport(alc::EventType eventType, BackendType) { - switch(eventType) { - case alc::EventType::DefaultDeviceChanged: { - return alc::EventSupport::FullSupport; - } - case alc::EventType::DeviceAdded: { - return alc::EventSupport::FullSupport; - } - case alc::EventType::DeviceRemoved: { - return alc::EventSupport::FullSupport; - } + switch(eventType) + { + case alc::EventType::DefaultDeviceChanged: + case alc::EventType::DeviceAdded: + case alc::EventType::DeviceRemoved: + return alc::EventSupport::FullSupport; + + case alc::EventType::Count: + break; } return alc::EventSupport::NoSupport; -} \ No newline at end of file +} diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index 23ed1415..bebc182d 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -1491,15 +1491,17 @@ BackendFactory &PulseBackendFactory::getFactory() return factory; } -alc::EventSupport PulseBackendFactory::queryEventSupport(alc::EventType eventType, BackendType type) +alc::EventSupport PulseBackendFactory::queryEventSupport(alc::EventType eventType, BackendType) { - switch(eventType) { - case alc::EventType::DeviceAdded: { - return alc::EventSupport::FullSupport; - } - case alc::EventType::DeviceRemoved: { - return alc::EventSupport::FullSupport; - } + switch(eventType) + { + case alc::EventType::DeviceAdded: + case alc::EventType::DeviceRemoved: + return alc::EventSupport::FullSupport; + + case alc::EventType::DefaultDeviceChanged: + case alc::EventType::Count: + break; } return alc::EventSupport::NoSupport; } diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index a4d6ea2f..3ee98457 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -2741,18 +2741,21 @@ BackendFactory &WasapiBackendFactory::getFactory() return factory; } -alc::EventSupport WasapiBackendFactory::queryEventSupport(alc::EventType eventType, BackendType type) +alc::EventSupport WasapiBackendFactory::queryEventSupport(alc::EventType eventType, BackendType) { - switch(eventType) { - case alc::EventType::DefaultDeviceChanged: { - return alc::EventSupport::FullSupport; - } - case alc::EventType::DeviceAdded: { - return alc::EventSupport::FullSupport; - } - case alc::EventType::DeviceRemoved: { - return alc::EventSupport::FullSupport; - } + switch(eventType) + { + case alc::EventType::DefaultDeviceChanged: + return alc::EventSupport::FullSupport; + + case alc::EventType::DeviceAdded: + case alc::EventType::DeviceRemoved: +#if !defined(ALSOFT_UWP) + return alc::EventSupport::FullSupport; +#endif + + case alc::EventType::Count: + break; } return alc::EventSupport::NoSupport; } -- cgit v1.2.3 From 571b546f35eead77ce109f8d4dd6c3de3199d573 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 25 Nov 2023 22:09:28 -0800 Subject: Update some in-progress format enums --- alc/inprogext.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'alc') diff --git a/alc/inprogext.h b/alc/inprogext.h index 8764c85b..c5b09f13 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -400,22 +400,22 @@ ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, AL #ifndef AL_EXT_int32 #define AL_EXT_int32 -#define AL_FORMAT_MONO_I32 0x9999 /* TBD, same as AL_FORMAT_MONO32 */ +#define AL_FORMAT_MONO_I32 0x1202 /* Same as AL_FORMAT_MONO32 */ #define AL_FORMAT_STEREO_I32 0x1203 /* Same as AL_FORMAT_STEREO32 */ -#define AL_FORMAT_REAR_I32 0x19D9 -#define AL_FORMAT_QUAD_I32 0x19DA -#define AL_FORMAT_51CHN_I32 0x19DB -#define AL_FORMAT_61CHN_I32 0x19DC -#define AL_FORMAT_71CHN_I32 0x19DD -#define AL_FORMAT_UHJ2CHN_I32 0x19DE -#define AL_FORMAT_UHJ3CHN_I32 0x19DF -#define AL_FORMAT_UHJ4CHN_I32 0x19E0 - -#define AL_FORMAT_REAR_FLOAT32 0x19E1 -#define AL_FORMAT_QUAD_FLOAT32 0x19E2 -#define AL_FORMAT_51CHN_FLOAT32 0x19E3 -#define AL_FORMAT_61CHN_FLOAT32 0x19E4 -#define AL_FORMAT_71CHN_FLOAT32 0x19E5 +#define AL_FORMAT_REAR_I32 0x19DB +#define AL_FORMAT_QUAD_I32 0x19DC +#define AL_FORMAT_51CHN_I32 0x19DD +#define AL_FORMAT_61CHN_I32 0x19DE +#define AL_FORMAT_71CHN_I32 0x19DF +#define AL_FORMAT_UHJ2CHN_I32 0x19E0 +#define AL_FORMAT_UHJ3CHN_I32 0x19E1 +#define AL_FORMAT_UHJ4CHN_I32 0x19E2 + +#define AL_FORMAT_REAR_FLOAT32 0x19E3 +#define AL_FORMAT_QUAD_FLOAT32 0x19E4 +#define AL_FORMAT_51CHN_FLOAT32 0x19E5 +#define AL_FORMAT_61CHN_FLOAT32 0x19E6 +#define AL_FORMAT_71CHN_FLOAT32 0x19E7 #endif /* Non-standard exports. Not part of any extension. */ -- cgit v1.2.3