From bd0144065a343c936b6a12be6e546e114575217b Mon Sep 17 00:00:00 2001 From: Chris Robinson <chris.kcat@gmail.com> Date: Mon, 15 Jun 2020 18:50:59 -0700 Subject: Set channel labels from WFX channel masks --- alc/backends/base.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'alc/backends/base.cpp') diff --git a/alc/backends/base.cpp b/alc/backends/base.cpp index 45a1c25d..5c53e3b8 100644 --- a/alc/backends/base.cpp +++ b/alc/backends/base.cpp @@ -6,12 +6,20 @@ #include <atomic> #include <thread> +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <mmreg.h> +#endif + #include "AL/al.h" #include "alcmain.h" #include "alexcpt.h" #include "alnumeric.h" +#include "aloptional.h" #include "atomic.h" +#include "logging.h" bool BackendBase::reset() @@ -140,3 +148,50 @@ void BackendBase::setDefaultChannelOrder() break; } } + +#ifdef _WIN32 +void BackendBase::setChannelOrderFromWFXMask(ALuint chanmask) +{ + auto get_channel = [](const DWORD chanbit) noexcept -> al::optional<Channel> + { + switch(chanbit) + { + case SPEAKER_FRONT_LEFT: return al::make_optional(FrontLeft); + case SPEAKER_FRONT_RIGHT: return al::make_optional(FrontRight); + case SPEAKER_FRONT_CENTER: return al::make_optional(FrontCenter); + case SPEAKER_LOW_FREQUENCY: return al::make_optional(LFE); + case SPEAKER_BACK_LEFT: return al::make_optional(BackLeft); + case SPEAKER_BACK_RIGHT: return al::make_optional(BackRight); + case SPEAKER_FRONT_LEFT_OF_CENTER: break; + case SPEAKER_FRONT_RIGHT_OF_CENTER: break; + case SPEAKER_BACK_CENTER: return al::make_optional(BackCenter); + case SPEAKER_SIDE_LEFT: return al::make_optional(SideLeft); + case SPEAKER_SIDE_RIGHT: return al::make_optional(SideRight); + case SPEAKER_TOP_CENTER: return al::make_optional(TopCenter); + case SPEAKER_TOP_FRONT_LEFT: return al::make_optional(TopFrontLeft); + case SPEAKER_TOP_FRONT_CENTER: return al::make_optional(TopFrontCenter); + case SPEAKER_TOP_FRONT_RIGHT: return al::make_optional(TopFrontRight); + case SPEAKER_TOP_BACK_LEFT: return al::make_optional(TopBackLeft); + case SPEAKER_TOP_BACK_CENTER: return al::make_optional(TopBackCenter); + case SPEAKER_TOP_BACK_RIGHT: return al::make_optional(TopBackRight); + } + WARN("Unhandled WFX channel bit 0x%lx\n", chanbit); + return al::nullopt; + }; + + const ALuint numchans{mDevice->channelsFromFmt()}; + ALuint idx{0}; + while(chanmask) + { + const int bit{CTZ32(chanmask)}; + const ALuint mask{1u << bit}; + chanmask &= ~mask; + + if(auto label = get_channel(mask)) + { + mDevice->RealOut.ChannelIndex[*label] = idx; + if(++idx == numchans) break; + } + } +} +#endif -- cgit v1.2.3