aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2022-11-03 19:42:08 -0700
committerChris Robinson <[email protected]>2022-11-03 19:42:08 -0700
commite9ad8571ba93dd6631a9c05a05a28ede95728d9e (patch)
tree391684e8c815ccbd72db91c19c630bcb4549bf29
parent551a18a15c66440e3a5478c8b3d6b973f36c33d3 (diff)
Add preliminary support for 7.1.4 output modes
I don't know how different sound APIs handle 7.1.4 ("Atmos" or "Auro3D") output, but currently it simply specifies the additional channels with the height channel labels. This isn't likely how it works for a virtualized channel bed, for playing over other with-height configurations (7.1.2, 5.1.4, etc), but this should be an okay start.
-rw-r--r--alc/alc.cpp3
-rw-r--r--alc/backends/base.cpp28
-rw-r--r--alc/backends/coreaudio.cpp1
-rw-r--r--alc/backends/dsound.cpp3
-rw-r--r--alc/backends/oboe.cpp1
-rw-r--r--alc/backends/opensl.cpp5
-rw-r--r--alc/backends/pipewire.cpp9
-rw-r--r--alc/backends/pulseaudio.cpp18
-rw-r--r--alc/backends/wasapi.cpp22
-rw-r--r--alc/backends/wave.cpp4
-rw-r--r--alc/backends/winmm.cpp1
-rw-r--r--alc/context.cpp4
-rw-r--r--alc/device.cpp4
-rw-r--r--alc/panning.cpp31
-rw-r--r--core/devformat.cpp2
-rw-r--r--core/devformat.h1
-rw-r--r--docs/ambdec.txt6
-rw-r--r--presets/hex-quad.ambdec53
-rw-r--r--presets/presets.txt11
19 files changed, 201 insertions, 6 deletions
diff --git a/alc/alc.cpp b/alc/alc.cpp
index f6385e27..5f9bfa9b 100644
--- a/alc/alc.cpp
+++ b/alc/alc.cpp
@@ -1482,6 +1482,7 @@ ALCenum EnumFromDevFmt(DevFmtChannels channels)
case DevFmtX71: return ALC_7POINT1_SOFT;
case DevFmtAmbi3D: return ALC_BFORMAT3D_SOFT;
/* FIXME: Shouldn't happen. */
+ case DevFmtX714:
case DevFmtX3D71: break;
}
throw std::runtime_error{"Invalid DevFmtChannels: "+std::to_string(int(channels))};
@@ -1953,6 +1954,7 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
{ "surround51", DevFmtX51, 0 },
{ "surround61", DevFmtX61, 0 },
{ "surround71", DevFmtX71, 0 },
+ { "surround714", DevFmtX714, 0 },
{ "surround3d71", DevFmtX3D71, 0 },
{ "surround51rear", DevFmtX51, 0 },
{ "ambi1", DevFmtAmbi3D, 1 },
@@ -2133,6 +2135,7 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
case DevFmtX51: device->RealOut.RemixMap = X51Downmix; break;
case DevFmtX61: device->RealOut.RemixMap = X61Downmix; break;
case DevFmtX71: device->RealOut.RemixMap = X71Downmix; break;
+ case DevFmtX714: device->RealOut.RemixMap = X71Downmix; break;
case DevFmtX3D71: device->RealOut.RemixMap = X51Downmix; break;
case DevFmtAmbi3D: break;
}
diff --git a/alc/backends/base.cpp b/alc/backends/base.cpp
index 4abd7c03..6838c7e3 100644
--- a/alc/backends/base.cpp
+++ b/alc/backends/base.cpp
@@ -98,6 +98,20 @@ void BackendBase::setDefaultWFXChannelOrder()
mDevice->RealOut.ChannelIndex[SideLeft] = 6;
mDevice->RealOut.ChannelIndex[SideRight] = 7;
break;
+ case DevFmtX714:
+ mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
+ mDevice->RealOut.ChannelIndex[FrontRight] = 1;
+ mDevice->RealOut.ChannelIndex[FrontCenter] = 2;
+ mDevice->RealOut.ChannelIndex[LFE] = 3;
+ mDevice->RealOut.ChannelIndex[BackLeft] = 4;
+ mDevice->RealOut.ChannelIndex[BackRight] = 5;
+ mDevice->RealOut.ChannelIndex[SideLeft] = 6;
+ mDevice->RealOut.ChannelIndex[SideRight] = 7;
+ mDevice->RealOut.ChannelIndex[TopFrontLeft] = 8;
+ mDevice->RealOut.ChannelIndex[TopFrontRight] = 9;
+ mDevice->RealOut.ChannelIndex[TopBackLeft] = 10;
+ mDevice->RealOut.ChannelIndex[TopBackRight] = 11;
+ break;
case DevFmtX3D71:
mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
mDevice->RealOut.ChannelIndex[FrontRight] = 1;
@@ -137,6 +151,20 @@ void BackendBase::setDefaultChannelOrder()
mDevice->RealOut.ChannelIndex[SideLeft] = 6;
mDevice->RealOut.ChannelIndex[SideRight] = 7;
return;
+ case DevFmtX714:
+ mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
+ mDevice->RealOut.ChannelIndex[FrontRight] = 1;
+ mDevice->RealOut.ChannelIndex[BackLeft] = 2;
+ mDevice->RealOut.ChannelIndex[BackRight] = 3;
+ mDevice->RealOut.ChannelIndex[FrontCenter] = 4;
+ mDevice->RealOut.ChannelIndex[LFE] = 5;
+ mDevice->RealOut.ChannelIndex[SideLeft] = 6;
+ mDevice->RealOut.ChannelIndex[SideRight] = 7;
+ mDevice->RealOut.ChannelIndex[TopFrontLeft] = 8;
+ mDevice->RealOut.ChannelIndex[TopFrontRight] = 9;
+ mDevice->RealOut.ChannelIndex[TopBackLeft] = 10;
+ mDevice->RealOut.ChannelIndex[TopBackRight] = 11;
+ break;
case DevFmtX3D71:
mDevice->RealOut.ChannelIndex[FrontLeft] = 0;
mDevice->RealOut.ChannelIndex[FrontRight] = 1;
diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp
index 8b45fefe..d6392271 100644
--- a/alc/backends/coreaudio.cpp
+++ b/alc/backends/coreaudio.cpp
@@ -748,6 +748,7 @@ void CoreAudioCapture::open(const char *name)
case DevFmtX51:
case DevFmtX61:
case DevFmtX71:
+ case DevFmtX714:
case DevFmtX3D71:
case DevFmtAmbi3D:
throw al::backend_exception{al::backend_error::DeviceError, "%s not supported",
diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp
index 3f2bf8df..f549c0fe 100644
--- a/alc/backends/dsound.cpp
+++ b/alc/backends/dsound.cpp
@@ -115,6 +115,7 @@ HRESULT (WINAPI *pDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallbac
#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 X7DOT1DOT4 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT|SPEAKER_TOP_FRONT_LEFT|SPEAKER_TOP_FRONT_RIGHT|SPEAKER_TOP_BACK_LEFT|SPEAKER_TOP_BACK_RIGHT)
#define MAX_UPDATES 128
@@ -424,6 +425,7 @@ bool DSoundPlayback::reset()
case DevFmtX51: OutputType.dwChannelMask = isRear51 ? X5DOT1REAR : X5DOT1; break;
case DevFmtX61: OutputType.dwChannelMask = X6DOT1; break;
case DevFmtX71: OutputType.dwChannelMask = X7DOT1; break;
+ case DevFmtX714: OutputType.dwChannelMask = X7DOT1DOT4; break;
case DevFmtX3D71: OutputType.dwChannelMask = X7DOT1; break;
}
@@ -638,6 +640,7 @@ void DSoundCapture::open(const char *name)
case DevFmtX51: InputType.dwChannelMask = X5DOT1; break;
case DevFmtX61: InputType.dwChannelMask = X6DOT1; break;
case DevFmtX71: InputType.dwChannelMask = X7DOT1; break;
+ case DevFmtX714: InputType.dwChannelMask = X7DOT1DOT4; break;
case DevFmtX3D71:
case DevFmtAmbi3D:
WARN("%s capture not supported\n", DevFmtChannelsString(mDevice->FmtChans));
diff --git a/alc/backends/oboe.cpp b/alc/backends/oboe.cpp
index 7b1dc966..32e4d4dd 100644
--- a/alc/backends/oboe.cpp
+++ b/alc/backends/oboe.cpp
@@ -245,6 +245,7 @@ void OboeCapture::open(const char *name)
case DevFmtX51:
case DevFmtX61:
case DevFmtX71:
+ case DevFmtX714:
case DevFmtX3D71:
case DevFmtAmbi3D:
throw al::backend_exception{al::backend_error::DeviceError, "%s capture not supported",
diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp
index 49e5c268..9ecde509 100644
--- a/alc/backends/opensl.cpp
+++ b/alc/backends/opensl.cpp
@@ -75,6 +75,11 @@ constexpr SLuint32 GetChannelMask(DevFmtChannels chans) noexcept
case DevFmtX3D71: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_BACK_LEFT |
SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT;
+ case DevFmtX714: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
+ SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_BACK_LEFT |
+ SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT |
+ SL_SPEAKER_TOP_FRONT_LEFT | SL_SPEAKER_TOP_FRONT_RIGHT | SL_SPEAKER_TOP_BACK_LEFT |
+ SL_SPEAKER_TOP_BACK_RIGHT;
case DevFmtAmbi3D:
break;
}
diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp
index acb4616f..0b36aba1 100644
--- a/alc/backends/pipewire.cpp
+++ b/alc/backends/pipewire.cpp
@@ -644,6 +644,10 @@ const spa_audio_channel MonoMap[]{
}, X71Map[]{
SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR
+}, X714Map[]{
+ SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR,
+ SPA_AUDIO_CHANNEL_TFL, SPA_AUDIO_CHANNEL_TFR, SPA_AUDIO_CHANNEL_TRL, SPA_AUDIO_CHANNEL_TRR
};
/**
@@ -747,7 +751,9 @@ void DeviceNode::parsePositions(const spa_pod *value) noexcept
mIs51Rear = false;
- if(MatchChannelMap(chanmap, X71Map))
+ if(MatchChannelMap(chanmap, X714Map))
+ mChannels = DevFmtX714;
+ else if(MatchChannelMap(chanmap, X71Map))
mChannels = DevFmtX71;
else if(MatchChannelMap(chanmap, X61Map))
mChannels = DevFmtX61;
@@ -1232,6 +1238,7 @@ spa_audio_info_raw make_spa_info(DeviceBase *device, bool is51rear, use_f32p_e u
break;
case DevFmtX61: map = X61Map; break;
case DevFmtX71: map = X71Map; break;
+ case DevFmtX714: map = X714Map; break;
case DevFmtX3D71: map = X71Map; break;
case DevFmtAmbi3D:
info.flags |= SPA_AUDIO_FLAG_UNPOSITIONED;
diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp
index f3fe856e..3862ec2e 100644
--- a/alc/backends/pulseaudio.cpp
+++ b/alc/backends/pulseaudio.cpp
@@ -234,6 +234,15 @@ constexpr pa_channel_map MonoChanMap{
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT
}
+}, X714ChanMap{
+ 12, {
+ PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
+ PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
+ PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
+ PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT,
+ PA_CHANNEL_POSITION_TOP_FRONT_LEFT, PA_CHANNEL_POSITION_TOP_FRONT_RIGHT,
+ PA_CHANNEL_POSITION_TOP_REAR_LEFT, PA_CHANNEL_POSITION_TOP_REAR_RIGHT
+ }
};
@@ -704,7 +713,8 @@ void PulsePlayback::sinkInfoCallback(pa_context*, const pa_sink_info *info, int
pa_channel_map map;
bool is_51rear;
};
- static constexpr std::array<ChannelMap,7> chanmaps{{
+ static constexpr std::array<ChannelMap,8> chanmaps{{
+ { DevFmtX714, X714ChanMap, false },
{ DevFmtX71, X71ChanMap, false },
{ DevFmtX61, X61ChanMap, false },
{ DevFmtX51, X51ChanMap, false },
@@ -895,6 +905,9 @@ bool PulsePlayback::reset()
case DevFmtX3D71:
chanmap = X71ChanMap;
break;
+ case DevFmtX714:
+ chanmap = X714ChanMap;
+ break;
}
setDefaultWFXChannelOrder();
@@ -1179,6 +1192,9 @@ void PulseCapture::open(const char *name)
case DevFmtX71:
chanmap = X71ChanMap;
break;
+ case DevFmtX714:
+ chanmap = X714ChanMap;
+ break;
case DevFmtX3D71:
case DevFmtAmbi3D:
throw al::backend_exception{al::backend_error::DeviceError, "%s capture not supported",
diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp
index 9007da1b..0a5294ac 100644
--- a/alc/backends/wasapi.cpp
+++ b/alc/backends/wasapi.cpp
@@ -102,6 +102,7 @@ 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 X7DOT1DOT4 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT|SPEAKER_TOP_FRONT_LEFT|SPEAKER_TOP_FRONT_RIGHT|SPEAKER_TOP_BACK_LEFT|SPEAKER_TOP_BACK_RIGHT)
constexpr inline DWORD MaskFromTopBits(DWORD b) noexcept
{
@@ -119,6 +120,7 @@ constexpr DWORD X51Mask{MaskFromTopBits(X5DOT1)};
constexpr DWORD X51RearMask{MaskFromTopBits(X5DOT1REAR)};
constexpr DWORD X61Mask{MaskFromTopBits(X6DOT1)};
constexpr DWORD X71Mask{MaskFromTopBits(X7DOT1)};
+constexpr DWORD X714Mask{MaskFromTopBits(X7DOT1DOT4)};
constexpr char DevNameHead[] = "OpenAL Soft on ";
constexpr size_t DevNameHeadLen{al::size(DevNameHead) - 1};
@@ -888,7 +890,9 @@ HRESULT WasapiPlayback::resetProxy()
*/
const uint32_t chancount{OutputType.Format.nChannels};
const DWORD chanmask{OutputType.dwChannelMask};
- if(chancount >= 8 && (chanmask&X71Mask) == X7DOT1)
+ if(chancount >= 12 && (chanmask&X714Mask) == X7DOT1DOT4)
+ mDevice->FmtChans = DevFmtX71;
+ else if(chancount >= 8 && (chanmask&X71Mask) == X7DOT1)
mDevice->FmtChans = DevFmtX71;
else if(chancount >= 7 && (chanmask&X61Mask) == X6DOT1)
mDevice->FmtChans = DevFmtX61;
@@ -946,6 +950,10 @@ HRESULT WasapiPlayback::resetProxy()
OutputType.Format.nChannels = 8;
OutputType.dwChannelMask = X7DOT1;
break;
+ case DevFmtX714:
+ OutputType.Format.nChannels = 12;
+ OutputType.dwChannelMask = X7DOT1DOT4;
+ break;
}
switch(mDevice->FmtType)
{
@@ -1045,13 +1053,17 @@ HRESULT WasapiPlayback::resetProxy()
case DevFmtX3D71:
chansok = (chancount >= 8 && ((chanmask&X71Mask) == X7DOT1 || !chanmask));
break;
+ case DevFmtX714:
+ chansok = (chancount >= 12 && ((chanmask&X714Mask) == X7DOT1DOT4 || !chanmask));
case DevFmtAmbi3D:
break;
}
}
if(!chansok)
{
- if(chancount >= 8 && (chanmask&X71Mask) == X7DOT1)
+ 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;
@@ -1518,6 +1530,10 @@ HRESULT WasapiCapture::resetProxy()
InputType.Format.nChannels = 8;
InputType.dwChannelMask = X7DOT1;
break;
+ case DevFmtX714:
+ InputType.Format.nChannels = 12;
+ InputType.dwChannelMask = X7DOT1DOT4;
+ break;
case DevFmtX3D71:
case DevFmtAmbi3D:
@@ -1606,6 +1622,8 @@ HRESULT WasapiCapture::resetProxy()
case DevFmtX71:
case DevFmtX3D71:
return (chancount == 8 && (chanmask == 0 || (chanmask&X71Mask) == X7DOT1));
+ case DevFmtX714:
+ return (chancount == 12 && (chanmask == 0 || (chanmask&X714Mask) == X7DOT1DOT4));
case DevFmtAmbi3D:
return (chanmask == 0 && chancount == device->channelsFromFmt());
}
diff --git a/alc/backends/wave.cpp b/alc/backends/wave.cpp
index 80e93f69..f97f42f5 100644
--- a/alc/backends/wave.cpp
+++ b/alc/backends/wave.cpp
@@ -265,6 +265,10 @@ bool WaveBackend::reset()
case DevFmtX51: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x200 | 0x400; break;
case DevFmtX61: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x100 | 0x200 | 0x400; break;
case DevFmtX71: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400; break;
+ case DevFmtX714:
+ chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400 | 0x1000 | 0x4000
+ | 0x8000 | 0x20000;
+ break;
/* NOTE: Same as 7.1. */
case DevFmtX3D71: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400; break;
case DevFmtAmbi3D:
diff --git a/alc/backends/winmm.cpp b/alc/backends/winmm.cpp
index 14cc4f9e..38e1193f 100644
--- a/alc/backends/winmm.cpp
+++ b/alc/backends/winmm.cpp
@@ -469,6 +469,7 @@ void WinMMCapture::open(const char *name)
case DevFmtX51:
case DevFmtX61:
case DevFmtX71:
+ case DevFmtX714:
case DevFmtX3D71:
case DevFmtAmbi3D:
throw al::backend_exception{al::backend_error::DeviceError, "%s capture not supported",
diff --git a/alc/context.cpp b/alc/context.cpp
index a892bb6d..07ae6434 100644
--- a/alc/context.cpp
+++ b/alc/context.cpp
@@ -535,6 +535,10 @@ unsigned long ALCcontext::eax_detect_speaker_configuration() const
case DevFmtX51: return SPEAKERS_5;
case DevFmtX61: return SPEAKERS_6;
case DevFmtX71: return SPEAKERS_7;
+ /* 7.1.4 is compatible with 7.1. This could instead be HEADPHONES to
+ * suggest with-height surround sound (like HRTF).
+ */
+ case DevFmtX714: return SPEAKERS_7;
/* 3D7.1 is only compatible with 5.1. This could instead be HEADPHONES to
* suggest full-sphere surround sound (like HRTF).
*/
diff --git a/alc/device.cpp b/alc/device.cpp
index 6eeb907e..66b13c5e 100644
--- a/alc/device.cpp
+++ b/alc/device.cpp
@@ -84,8 +84,10 @@ auto ALCdevice::getOutputMode1() const noexcept -> OutputMode1
case DevFmtX51: return OutputMode1::X51;
case DevFmtX61: return OutputMode1::X61;
case DevFmtX71: return OutputMode1::X71;
+ case DevFmtX714:
case DevFmtX3D71:
- case DevFmtAmbi3D: break;
+ case DevFmtAmbi3D:
+ break;
}
return OutputMode1::Any;
}
diff --git a/alc/panning.cpp b/alc/panning.cpp
index 45daa5cf..1210b318 100644
--- a/alc/panning.cpp
+++ b/alc/panning.cpp
@@ -376,6 +376,10 @@ DecoderView MakeDecoderView(ALCdevice *device, const AmbDecConf *conf,
* RB = Back right
* CE = Front center
* CB = Back center
+ * LFT = Top front left
+ * RFT = Top front right
+ * LBT = Top back left
+ * RBT = Top back right
*
* Additionally, surround51 will acknowledge back speakers for side
* channels, to avoid issues with an ambdec expecting 5.1 to use the
@@ -398,6 +402,14 @@ DecoderView MakeDecoderView(ALCdevice *device, const AmbDecConf *conf,
ch = (device->FmtChans == DevFmtX51) ? SideRight : BackRight;
else if(speaker.Name == "CB")
ch = BackCenter;
+ else if(speaker.Name == "LFT")
+ ch = TopFrontLeft;
+ else if(speaker.Name == "RFT")
+ ch = TopFrontRight;
+ else if(speaker.Name == "LBT")
+ ch = TopBackLeft;
+ else if(speaker.Name == "RBT")
+ ch = TopBackRight;
else
{
int idx{};
@@ -554,6 +566,23 @@ constexpr DecoderConfig<DualBand, 6> X3D71Config{
{{1.666666667e-01f, 0.000000000e+00f, -2.356640879e-01f, 1.667265410e-01f}},
}}
};
+constexpr DecoderConfig<SingleBand, 10> X714Config{
+ 1, true, {{FrontLeft, FrontRight, SideLeft, SideRight, BackLeft, BackRight, TopFrontLeft, TopFrontRight, TopBackLeft, TopBackRight }},
+ DevAmbiScaling::N3D,
+ {{1.00000000e+0f, 1.00000000e+0f, 1.00000000e+0f}},
+ {{
+ {{1.27149251e-01f, 7.63047539e-02f, -3.64373750e-02f, 1.59700680e-01f}},
+ {{1.07005418e-01f, -7.67638760e-02f, -4.92129762e-02f, 1.29012797e-01f}},
+ {{1.26400196e-01f, 1.77494694e-01f, -3.71203389e-02f, 0.00000000e+00f}},
+ {{1.26396516e-01f, -1.77488059e-01f, -3.71297878e-02f, 0.00000000e+00f}},
+ {{1.06996956e-01f, 7.67615256e-02f, -4.92166307e-02f, -1.29001640e-01f}},
+ {{1.27145671e-01f, -7.63003471e-02f, -3.64353304e-02f, -1.59697510e-01f}},
+ {{8.80919747e-02f, 7.48940670e-02f, 9.08786244e-02f, 6.22527183e-02f}},
+ {{1.57880745e-01f, -7.28755272e-02f, 1.82364187e-01f, 8.74240284e-02f}},
+ {{1.57892225e-01f, 7.28944768e-02f, 1.82363474e-01f, -8.74301086e-02f}},
+ {{8.80892603e-02f, -7.48948724e-02f, 9.08779842e-02f, -6.22480443e-02f}},
+ }}
+};
void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize=false,
DecoderView decoder={})
@@ -568,6 +597,7 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize=
case DevFmtX51: decoder = X51Config; break;
case DevFmtX61: decoder = X61Config; break;
case DevFmtX71: decoder = X71Config; break;
+ case DevFmtX714: decoder = X714Config; break;
case DevFmtX3D71: decoder = X3D71Config; break;
case DevFmtAmbi3D:
auto&& acnmap = GetAmbiLayout(device->mAmbiLayout);
@@ -929,6 +959,7 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, al::optional<StereoEncoding
case DevFmtX51: layout = "surround51"; break;
case DevFmtX61: layout = "surround61"; break;
case DevFmtX71: layout = "surround71"; break;
+ case DevFmtX714: layout = "surround714"; break;
case DevFmtX3D71: layout = "surround3d71"; break;
/* Mono, Stereo, and Ambisonics output don't use custom decoders. */
case DevFmtMono:
diff --git a/core/devformat.cpp b/core/devformat.cpp
index cbe8eaf3..acdabc4f 100644
--- a/core/devformat.cpp
+++ b/core/devformat.cpp
@@ -28,6 +28,7 @@ uint ChannelsFromDevFmt(DevFmtChannels chans, uint ambiorder) noexcept
case DevFmtX51: return 6;
case DevFmtX61: return 7;
case DevFmtX71: return 8;
+ case DevFmtX714: return 12;
case DevFmtX3D71: return 8;
case DevFmtAmbi3D: return (ambiorder+1) * (ambiorder+1);
}
@@ -58,6 +59,7 @@ const char *DevFmtChannelsString(DevFmtChannels chans) noexcept
case DevFmtX51: return "5.1 Surround";
case DevFmtX61: return "6.1 Surround";
case DevFmtX71: return "7.1 Surround";
+ case DevFmtX714: return "7.1.4 Surround";
case DevFmtX3D71: return "3D7.1 Surround";
case DevFmtAmbi3D: return "Ambisonic 3D";
}
diff --git a/core/devformat.h b/core/devformat.h
index f2a372c1..485826a3 100644
--- a/core/devformat.h
+++ b/core/devformat.h
@@ -65,6 +65,7 @@ enum DevFmtChannels : unsigned char {
DevFmtX51,
DevFmtX61,
DevFmtX71,
+ DevFmtX714,
DevFmtX3D71,
DevFmtAmbi3D,
diff --git a/docs/ambdec.txt b/docs/ambdec.txt
index 5565ae06..a301004c 100644
--- a/docs/ambdec.txt
+++ b/docs/ambdec.txt
@@ -13,7 +13,7 @@ about ambisonics.
Starting with OpenAL Soft 1.18, version 3 of the file format is supported as a
means of specifying custom surround sound speaker layouts. These configuration
-files are also used to enable the high-quality ambisonic decoder.
+files are also used to enable per-speaker distance compensation.
File Format
@@ -155,6 +155,10 @@ LB = Back left
RB = Back right
CE = Front center
CB = Back center
+LFT = Top front left
+RFT = Top front right
+LBT = Top back left
+RBT = Top back right
Additionally, configuration files for surround51 will acknowledge back speakers
for side channels, to avoid issues with a configuration expecting 5.1 to use
diff --git a/presets/hex-quad.ambdec b/presets/hex-quad.ambdec
new file mode 100644
index 00000000..ce6cf8bf
--- /dev/null
+++ b/presets/hex-quad.ambdec
@@ -0,0 +1,53 @@
+# AmbDec configuration
+# Written by Ambisonic Decoder Toolbox, version 8.0
+
+# input channel order: W Y Z X
+
+/description 11_1_1h1v_allrad_5200_rE_max_1_band
+
+/version 3
+
+/dec/chan_mask f
+/dec/freq_bands 1
+/dec/speakers 11
+/dec/coeff_scale n3d
+
+/opt/input_scale n3d
+/opt/nfeff_comp output
+/opt/delay_comp on
+/opt/level_comp on
+/opt/xover_freq 400.000000
+/opt/xover_ratio 0.000000
+
+/speakers/{
+# id dist azim elev conn
+#-----------------------------------------------------------------------
+add_spkr LF 1.000000 30.000000 0.000000
+add_spkr RF 1.000000 -30.000000 0.000000
+add_spkr CE 1.000000 0.000000 0.000000
+add_spkr LS 1.000000 90.000000 0.000000
+add_spkr RS 1.000000 -90.000000 0.000000
+add_spkr LB 1.000000 150.000000 0.000000
+add_spkr RB 1.000000 -150.000000 0.000000
+add_spkr LFT 1.000000 45.000000 35.000000
+add_spkr RFT 1.000000 -45.000000 35.000000
+add_spkr LBT 1.000000 135.000000 35.000000
+add_spkr RBT 1.000000 -135.000000 35.000000
+/}
+
+/matrix/{
+order_gain 1.00000000e+00 1.00000000e+00 0.000000 0.000000
+add_row 1.27149251e-01 7.63047539e-02 -3.64373750e-02 1.59700680e-01
+add_row 1.07005418e-01 -7.67638760e-02 -4.92129762e-02 1.29012797e-01
+add_row 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00
+add_row 1.26400196e-01 1.77494694e-01 -3.71203389e-02 0.00000000e+00
+add_row 1.26396516e-01 -1.77488059e-01 -3.71297878e-02 0.00000000e+00
+add_row 1.06996956e-01 7.67615256e-02 -4.92166307e-02 -1.29001640e-01
+add_row 1.27145671e-01 -7.63003471e-02 -3.64353304e-02 -1.59697510e-01
+add_row 8.80919747e-02 7.48940670e-02 9.08786244e-02 6.22527183e-02
+add_row 1.57880745e-01 -7.28755272e-02 1.82364187e-01 8.74240284e-02
+add_row 1.57892225e-01 7.28944768e-02 1.82363474e-01 -8.74301086e-02
+add_row 8.80892603e-02 -7.48948724e-02 9.08779842e-02 -6.22480443e-02
+/}
+
+/end
diff --git a/presets/presets.txt b/presets/presets.txt
index 445d75a4..f75a53e9 100644
--- a/presets/presets.txt
+++ b/presets/presets.txt
@@ -36,6 +36,17 @@ is defined for the decoder, meaning that speaker will be silent for 3D sound
output). A "proper" 7.1 decoder may be provided in the future, but due to the
nature of the speaker configuration will have trade-offs.
+hex-quad.ambdec
+Specifies a flat-front hexagonal speaker setup, plus an elevated quad speaker
+setup, for 7.1.4 Surround output. The front left and right speakers are placed
+at +30 and -30 degrees, the side speakers are placed at +90 and -90 degrees,
+and the back speakers are placed at +150 and -150 degrees. The elevated
+speakers are placed at an elevation of +35 degrees, with the top front left and
+right speakers placed at +45 and -45 degrees, and the top back left and right
+speakers placed at +135 and -135 degrees. Similar to 7.1, the front-center
+speaker is not used for 3D sound, but will be used as appropriate with
+AL_SOFT_direct_channels or ALC_EXT_DEDICATED.
+
3D7.1.ambdec
Specifies a 3D7.1 speaker setup for 3D7.1 Surround output. Please see
docs/3D7.1.txt for information about speaker placement. Similar to 7.1, the