diff options
Diffstat (limited to 'alc')
-rw-r--r-- | alc/backends/base.cpp | 55 | ||||
-rw-r--r-- | alc/backends/base.h | 5 | ||||
-rw-r--r-- | alc/backends/dsound.cpp | 151 | ||||
-rw-r--r-- | alc/backends/wasapi.cpp | 24 | ||||
-rw-r--r-- | alc/backends/winmm.cpp | 12 |
5 files changed, 129 insertions, 118 deletions
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 diff --git a/alc/backends/base.h b/alc/backends/base.h index 1824649b..2b89e893 100644 --- a/alc/backends/base.h +++ b/alc/backends/base.h @@ -40,6 +40,11 @@ protected: void setDefaultChannelOrder(); /** Sets the default channel order used by WaveFormatEx. */ void setDefaultWFXChannelOrder(); + +#ifdef _WIN32 + /** Sets the channel order given the WaveFormatEx mask. */ + void setChannelOrderFromWFXMask(ALuint chanmask); +#endif }; using BackendPtr = std::unique_ptr<BackendBase>; diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index da857beb..e86153aa 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -108,6 +108,14 @@ HRESULT (WINAPI *pDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallbac #endif +#define MONO SPEAKER_FRONT_CENTER +#define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT) +#define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT) +#define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) +#define X5DOT1REAR (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT) +#define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) +#define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) + #define MAX_UPDATES 128 struct DevMap { @@ -358,23 +366,23 @@ bool DSoundPlayback::reset() switch(mDevice->FmtType) { - case DevFmtByte: - mDevice->FmtType = DevFmtUByte; - break; - case DevFmtFloat: - if(mDevice->Flags.get<SampleTypeRequest>()) - break; - /* fall-through */ - case DevFmtUShort: - mDevice->FmtType = DevFmtShort; - break; - case DevFmtUInt: - mDevice->FmtType = DevFmtInt; - break; - case DevFmtUByte: - case DevFmtShort: - case DevFmtInt: + case DevFmtByte: + mDevice->FmtType = DevFmtUByte; + break; + case DevFmtFloat: + if(mDevice->Flags.get<SampleTypeRequest>()) break; + /* fall-through */ + case DevFmtUShort: + mDevice->FmtType = DevFmtShort; + break; + case DevFmtUInt: + mDevice->FmtType = DevFmtInt; + break; + case DevFmtUByte: + case DevFmtShort: + case DevFmtInt: + break; } WAVEFORMATEXTENSIBLE OutputType{}; @@ -400,62 +408,20 @@ bool DSoundPlayback::reset() else ERR("Unknown system speaker config: 0x%lx\n", speakers); } - mDevice->IsHeadphones = (mDevice->FmtChans == DevFmtStereo && - speakers == DSSPEAKER_HEADPHONE); + mDevice->IsHeadphones = mDevice->FmtChans == DevFmtStereo + && speakers == DSSPEAKER_HEADPHONE; switch(mDevice->FmtChans) { - case DevFmtMono: - OutputType.dwChannelMask = SPEAKER_FRONT_CENTER; - break; - case DevFmtAmbi3D: - mDevice->FmtChans = DevFmtStereo; - /*fall-through*/ - case DevFmtStereo: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT; - break; - case DevFmtQuad: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT; - break; - case DevFmtX51: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | - SPEAKER_SIDE_LEFT | - SPEAKER_SIDE_RIGHT; - break; - case DevFmtX51Rear: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | - SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT; - break; - case DevFmtX61: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | - SPEAKER_BACK_CENTER | - SPEAKER_SIDE_LEFT | - SPEAKER_SIDE_RIGHT; - break; - case DevFmtX71: - OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | - SPEAKER_FRONT_RIGHT | - SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | - SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT | - SPEAKER_SIDE_LEFT | - SPEAKER_SIDE_RIGHT; - break; + case DevFmtMono: OutputType.dwChannelMask = MONO; break; + case DevFmtAmbi3D: mDevice->FmtChans = DevFmtStereo; + /*fall-through*/ + case DevFmtStereo: OutputType.dwChannelMask = STEREO; break; + case DevFmtQuad: OutputType.dwChannelMask = QUAD; break; + case DevFmtX51: OutputType.dwChannelMask = X5DOT1; break; + case DevFmtX51Rear: OutputType.dwChannelMask = X5DOT1REAR; break; + case DevFmtX61: OutputType.dwChannelMask = X6DOT1; break; + case DevFmtX71: OutputType.dwChannelMask = X7DOT1; break; } retry_open: @@ -507,8 +473,8 @@ retry_open: DSBUFFERDESC DSBDescription{}; DSBDescription.dwSize = sizeof(DSBDescription); - DSBDescription.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | - DSBCAPS_GLOBALFOCUS; + DSBDescription.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 + | DSBCAPS_GLOBALFOCUS; DSBDescription.dwBufferBytes = mDevice->BufferSize * OutputType.Format.nBlockAlign; DSBDescription.lpwfxFormat = &OutputType.Format; @@ -526,8 +492,7 @@ retry_open: hr = mBuffer->QueryInterface(IID_IDirectSoundNotify, &ptr); if(SUCCEEDED(hr)) { - auto Notifies = static_cast<IDirectSoundNotify*>(ptr); - mNotifies = Notifies; + mNotifies = static_cast<IDirectSoundNotify*>(ptr); ALuint num_updates{mDevice->BufferSize / mDevice->UpdateSize}; assert(num_updates <= MAX_UPDATES); @@ -538,7 +503,7 @@ retry_open: nots[i].dwOffset = i * mDevice->UpdateSize * OutputType.Format.nBlockAlign; nots[i].hEventNotify = mNotifyEvent; } - if(Notifies->SetNotificationPositions(num_updates, nots.data()) != DS_OK) + if(mNotifies->SetNotificationPositions(num_updates, nots.data()) != DS_OK) hr = E_FAIL; } } @@ -558,7 +523,7 @@ retry_open: } ResetEvent(mNotifyEvent); - setDefaultWFXChannelOrder(); + setChannelOrderFromWFXMask(OutputType.dwChannelMask); return true; } @@ -670,33 +635,13 @@ void DSoundCapture::open(const ALCchar *name) WAVEFORMATEXTENSIBLE InputType{}; switch(mDevice->FmtChans) { - case DevFmtMono: - InputType.dwChannelMask = SPEAKER_FRONT_CENTER; - break; - case DevFmtStereo: - InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; - break; - case DevFmtQuad: - InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | - SPEAKER_BACK_RIGHT; - break; - case DevFmtX51: - InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; - break; - case DevFmtX51Rear: - InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; - break; - case DevFmtX61: - InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_CENTER | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; - break; - case DevFmtX71: - InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | - SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | - SPEAKER_SIDE_RIGHT; - break; + case DevFmtMono: InputType.dwChannelMask = MONO; break; + case DevFmtStereo: InputType.dwChannelMask = STEREO; break; + case DevFmtQuad: InputType.dwChannelMask = QUAD; break; + case DevFmtX51: InputType.dwChannelMask = X5DOT1; break; + case DevFmtX51Rear: InputType.dwChannelMask = X5DOT1REAR; break; + case DevFmtX61: InputType.dwChannelMask = X6DOT1; break; + case DevFmtX71: InputType.dwChannelMask = X7DOT1; break; case DevFmtAmbi3D: WARN("%s capture not supported\n", DevFmtChannelsString(mDevice->FmtChans)); throw al::backend_exception{ALC_INVALID_VALUE, "%s capture not supported", @@ -754,7 +699,7 @@ void DSoundCapture::open(const ALCchar *name) } mBufferBytes = DSCBDescription.dwBufferBytes; - setDefaultWFXChannelOrder(); + setChannelOrderFromWFXMask(InputType.dwChannelMask); mDevice->DeviceName = name; } diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 89053ed6..8e43aa7c 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -100,9 +100,8 @@ inline constexpr ReferenceTime operator "" _reftime(unsigned long long int n) no #define X5DOT1REAR (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT) #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) #define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) -#define X7DOT1_WIDE (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_FRONT_LEFT_OF_CENTER|SPEAKER_FRONT_RIGHT_OF_CENTER) -constexpr inline uint32_t MaskFromTopBits(uint32_t b) noexcept +constexpr inline DWORD MaskFromTopBits(DWORD b) noexcept { b |= b>>1; b |= b>>2; @@ -111,14 +110,13 @@ constexpr inline uint32_t MaskFromTopBits(uint32_t b) noexcept b |= b>>16; return b; } -constexpr uint32_t MonoMask{MaskFromTopBits(MONO)}; -constexpr uint32_t StereoMask{MaskFromTopBits(STEREO)}; -constexpr uint32_t QuadMask{MaskFromTopBits(QUAD)}; -constexpr uint32_t X51Mask{MaskFromTopBits(X5DOT1)}; -constexpr uint32_t X51RearMask{MaskFromTopBits(X5DOT1REAR)}; -constexpr uint32_t X61Mask{MaskFromTopBits(X6DOT1)}; -constexpr uint32_t X71Mask{MaskFromTopBits(X7DOT1)}; -constexpr uint32_t X71WideMask{MaskFromTopBits(X7DOT1_WIDE)}; +constexpr DWORD MonoMask{MaskFromTopBits(MONO)}; +constexpr DWORD StereoMask{MaskFromTopBits(STEREO)}; +constexpr DWORD QuadMask{MaskFromTopBits(QUAD)}; +constexpr DWORD X51Mask{MaskFromTopBits(X5DOT1)}; +constexpr DWORD X51RearMask{MaskFromTopBits(X5DOT1REAR)}; +constexpr DWORD X61Mask{MaskFromTopBits(X6DOT1)}; +constexpr DWORD X71Mask{MaskFromTopBits(X7DOT1)}; #define DEVNAME_HEAD "OpenAL Soft on " @@ -891,7 +889,7 @@ HRESULT WasapiPlayback::resetProxy() { const uint32_t chancount{OutputType.Format.nChannels}; const DWORD chanmask{OutputType.dwChannelMask}; - if(chancount >= 8 && ((chanmask&X71Mask)==X7DOT1 || (chanmask&X71WideMask)==X7DOT1_WIDE)) + if(chancount >= 8 && (chanmask&X71Mask) == X7DOT1) mDevice->FmtChans = DevFmtX71; else if(chancount >= 7 && (chanmask&X61Mask) == X6DOT1) mDevice->FmtChans = DevFmtX61; @@ -1010,7 +1008,7 @@ HRESULT WasapiPlayback::resetProxy() mDevice->Frequency = OutputType.Format.nSamplesPerSec; const uint32_t chancount{OutputType.Format.nChannels}; const DWORD chanmask{OutputType.dwChannelMask}; - if(chancount >= 8 && ((chanmask&X71Mask)==X7DOT1 || (chanmask&X71WideMask)==X7DOT1_WIDE)) + if(chancount >= 8 && (chanmask&X71Mask) == X7DOT1) mDevice->FmtChans = DevFmtX71; else if(chancount >= 7 && (chanmask&X61Mask) == X6DOT1) mDevice->FmtChans = DevFmtX61; @@ -1070,7 +1068,7 @@ HRESULT WasapiPlayback::resetProxy() mDevice->IsHeadphones = (mDevice->FmtChans == DevFmtStereo && (formfactor == Headphones || formfactor == Headset)); - setDefaultWFXChannelOrder(); + setChannelOrderFromWFXMask(OutputType.dwChannelMask); hr = mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, buf_time.count(), 0, &OutputType.Format, nullptr); diff --git a/alc/backends/winmm.cpp b/alc/backends/winmm.cpp index e1261969..4dd74705 100644 --- a/alc/backends/winmm.cpp +++ b/alc/backends/winmm.cpp @@ -28,6 +28,7 @@ #include <windows.h> #include <mmsystem.h> +#include <mmreg.h> #include <array> #include <atomic> @@ -263,7 +264,7 @@ bool WinMMPlayback::reset() { mDevice->BufferSize = static_cast<ALuint>(uint64_t{mDevice->BufferSize} * mFormat.nSamplesPerSec / mDevice->Frequency); - mDevice->BufferSize = (mDevice->BufferSize+3) & ~0x3; + mDevice->BufferSize = (mDevice->BufferSize+3) & ~0x3u; mDevice->UpdateSize = mDevice->BufferSize / 4; mDevice->Frequency = mFormat.nSamplesPerSec; @@ -295,16 +296,23 @@ bool WinMMPlayback::reset() return false; } + ALuint chanmask{}; if(mFormat.nChannels == 2) + { mDevice->FmtChans = DevFmtStereo; + chanmask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; + } else if(mFormat.nChannels == 1) + { mDevice->FmtChans = DevFmtMono; + chanmask = SPEAKER_FRONT_CENTER; + } else { ERR("Unhandled channel count: %d\n", mFormat.nChannels); return false; } - setDefaultWFXChannelOrder(); + setChannelOrderFromWFXMask(chanmask); ALuint BufferSize{mDevice->UpdateSize * mDevice->frameSizeFromFmt()}; |