aboutsummaryrefslogtreecommitdiffstats
path: root/alc
diff options
context:
space:
mode:
Diffstat (limited to 'alc')
-rw-r--r--alc/backends/base.cpp55
-rw-r--r--alc/backends/base.h5
-rw-r--r--alc/backends/dsound.cpp151
-rw-r--r--alc/backends/wasapi.cpp24
-rw-r--r--alc/backends/winmm.cpp12
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()};