aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2021-04-02 07:21:17 -0700
committerChris Robinson <[email protected]>2021-04-02 07:21:17 -0700
commitc7f3a02956263ac7f7f767e2e63e80ae1ed7ca71 (patch)
tree27bd508d5533b4bb31a0a395b5799ff5bc67b1ee
parenta2c45f892884d0196079671826a19238517146fb (diff)
Add an option to decode stereo as UHJ in alffplay
-rw-r--r--examples/alffplay.cpp213
1 files changed, 137 insertions, 76 deletions
diff --git a/examples/alffplay.cpp b/examples/alffplay.cpp
index 6886a42d..c905f51a 100644
--- a/examples/alffplay.cpp
+++ b/examples/alffplay.cpp
@@ -86,6 +86,18 @@ typedef void (AL_APIENTRY*LPALGETBUFFERPTRSOFT)(ALuint buffer, ALenum param, ALv
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);
#endif
+#ifndef AL_SOFT_UHJ
+#define AL_SOFT_UHJ
+#define AL_FORMAT_UHJ2CHN8_SOFT 0x19A2
+#define AL_FORMAT_UHJ2CHN16_SOFT 0x19A3
+#define AL_FORMAT_UHJ2CHN_FLOAT32_SOFT 0x19A4
+#define AL_FORMAT_UHJ3CHN8_SOFT 0x19A5
+#define AL_FORMAT_UHJ3CHN16_SOFT 0x19A6
+#define AL_FORMAT_UHJ3CHN_FLOAT32_SOFT 0x19A7
+#define AL_FORMAT_UHJ4CHN8_SOFT 0x19A8
+#define AL_FORMAT_UHJ4CHN16_SOFT 0x19A9
+#define AL_FORMAT_UHJ4CHN_FLOAT32_SOFT 0x19AA
+#endif
#endif /* ALLOW_EXPERIMENTAL_EXTS */
}
@@ -109,6 +121,7 @@ const std::string AppName{"alffplay"};
ALenum DirectOutMode{AL_FALSE};
bool EnableWideStereo{false};
+bool EnableUhjDecode{false};
bool DisableVideo{false};
LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT;
LPALCGETINTEGER64VSOFT alcGetInteger64vSOFT;
@@ -939,7 +952,6 @@ int AudioState::handler()
{
std::unique_lock<std::mutex> srclock{mSrcMutex, std::defer_lock};
milliseconds sleep_time{AudioBufferTime / 3};
- ALenum fmt;
#ifdef AL_SOFT_events
const std::array<ALenum,3> evt_types{{
@@ -958,30 +970,53 @@ int AudioState::handler()
ALenum ambi_scale{AL_FUMA_SOFT};
#endif
+ ALenum FormatStereo8{AL_FORMAT_STEREO8};
+ ALenum FormatStereo16{AL_FORMAT_STEREO16};
+ ALenum FormatStereo32F{AL_FORMAT_STEREO_FLOAT32};
+#ifdef AL_SOFT_UHJ
+ if(EnableUhjDecode)
+ {
+ FormatStereo8 = AL_FORMAT_UHJ2CHN8_SOFT;
+ FormatStereo16 = AL_FORMAT_UHJ2CHN16_SOFT;
+ FormatStereo32F = AL_FORMAT_UHJ2CHN_FLOAT32_SOFT;
+ }
+#endif
+
/* Find a suitable format for OpenAL. */
mDstChanLayout = 0;
mFormat = AL_NONE;
- if((mCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLTP) &&
- alIsExtensionPresent("AL_EXT_FLOAT32"))
+ if((mCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLTP
+ || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_DBL
+ || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_DBLP
+ || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_S32
+ || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_S32P
+ || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_S64
+ || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_S64P)
+ && alIsExtensionPresent("AL_EXT_FLOAT32"))
{
mDstSampleFmt = AV_SAMPLE_FMT_FLT;
mFrameSize = 4;
- if(mCodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1 &&
- alIsExtensionPresent("AL_EXT_MCFORMATS") &&
- (fmt=alGetEnumValue("AL_FORMAT_71CHN32")) != AL_NONE && fmt != -1)
- {
- mDstChanLayout = mCodecCtx->channel_layout;
- mFrameSize *= 8;
- mFormat = fmt;
- }
- if((mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1 ||
- mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK) &&
- alIsExtensionPresent("AL_EXT_MCFORMATS") &&
- (fmt=alGetEnumValue("AL_FORMAT_51CHN32")) != AL_NONE && fmt != -1)
+ if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
{
- mDstChanLayout = mCodecCtx->channel_layout;
- mFrameSize *= 6;
- mFormat = fmt;
+ if(mCodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1)
+ {
+ mDstChanLayout = mCodecCtx->channel_layout;
+ mFrameSize *= 8;
+ mFormat = alGetEnumValue("AL_FORMAT_71CHN32");
+ }
+ if(mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1
+ || mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK)
+ {
+ mDstChanLayout = mCodecCtx->channel_layout;
+ mFrameSize *= 6;
+ mFormat = alGetEnumValue("AL_FORMAT_51CHN32");
+ }
+ if(mCodecCtx->channel_layout == AV_CH_LAYOUT_QUAD)
+ {
+ mDstChanLayout = mCodecCtx->channel_layout;
+ mFrameSize *= 4;
+ mFormat = alGetEnumValue("AL_FORMAT_QUAD32");
+ }
}
if(mCodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
{
@@ -994,48 +1029,57 @@ int AudioState::handler()
* have no way to specify if the source is actually B-Format (let alone
* if it's 2D or 3D).
*/
- if(mCodecCtx->channel_layout == 0 && mCodecCtx->channels >= 4 &&
- alIsExtensionPresent("AL_EXT_BFORMAT") &&
- (fmt=alGetEnumValue("AL_FORMAT_BFORMAT3D_FLOAT32")) != AL_NONE && fmt != -1)
+ if(mCodecCtx->channel_layout == 0 && mCodecCtx->channels >= 4
+ && alIsExtensionPresent("AL_EXT_BFORMAT"))
{
- int order{static_cast<int>(std::sqrt(mCodecCtx->channels)) - 1};
- if((order+1)*(order+1) == mCodecCtx->channels ||
- (order+1)*(order+1) + 2 == mCodecCtx->channels)
+ /* Calculate what should be the ambisonic order from the number of
+ * channels, and confirm that's the number of channels. Opus allows
+ * an optional non-diegetic stereo stream with the B-Format stream,
+ * which we can ignore, so check for that too.
+ */
+ auto order = static_cast<int>(std::sqrt(mCodecCtx->channels)) - 1;
+ int channels{(order+1) * (order+1)};
+ if(channels == mCodecCtx->channels || channels+2 == mCodecCtx->channels)
{
/* OpenAL only supports first-order with AL_EXT_BFORMAT, which
* is 4 channels for 3D buffers.
*/
mFrameSize *= 4;
- mFormat = fmt;
+ mFormat = alGetEnumValue("AL_FORMAT_BFORMAT3D_FLOAT32");
}
}
- if(!mFormat)
+ if(!mFormat || mFormat == -1)
{
mDstChanLayout = AV_CH_LAYOUT_STEREO;
mFrameSize *= 2;
- mFormat = AL_FORMAT_STEREO_FLOAT32;
+ mFormat = FormatStereo32F;
}
}
if(mCodecCtx->sample_fmt == AV_SAMPLE_FMT_U8 || mCodecCtx->sample_fmt == AV_SAMPLE_FMT_U8P)
{
mDstSampleFmt = AV_SAMPLE_FMT_U8;
mFrameSize = 1;
- if(mCodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1 &&
- alIsExtensionPresent("AL_EXT_MCFORMATS") &&
- (fmt=alGetEnumValue("AL_FORMAT_71CHN8")) != AL_NONE && fmt != -1)
+ if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
{
- mDstChanLayout = mCodecCtx->channel_layout;
- mFrameSize *= 8;
- mFormat = fmt;
- }
- if((mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1 ||
- mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK) &&
- alIsExtensionPresent("AL_EXT_MCFORMATS") &&
- (fmt=alGetEnumValue("AL_FORMAT_51CHN8")) != AL_NONE && fmt != -1)
- {
- mDstChanLayout = mCodecCtx->channel_layout;
- mFrameSize *= 6;
- mFormat = fmt;
+ if(mCodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1)
+ {
+ mDstChanLayout = mCodecCtx->channel_layout;
+ mFrameSize *= 8;
+ mFormat = alGetEnumValue("AL_FORMAT_71CHN8");
+ }
+ if(mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1
+ || mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK)
+ {
+ mDstChanLayout = mCodecCtx->channel_layout;
+ mFrameSize *= 6;
+ mFormat = alGetEnumValue("AL_FORMAT_51CHN8");
+ }
+ if(mCodecCtx->channel_layout == AV_CH_LAYOUT_QUAD)
+ {
+ mDstChanLayout = mCodecCtx->channel_layout;
+ mFrameSize *= 4;
+ mFormat = alGetEnumValue("AL_FORMAT_QUAD8");
+ }
}
if(mCodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
{
@@ -1043,45 +1087,49 @@ int AudioState::handler()
mFrameSize *= 1;
mFormat = AL_FORMAT_MONO8;
}
- if(mCodecCtx->channel_layout == 0 && mCodecCtx->channels >= 4 &&
- alIsExtensionPresent("AL_EXT_BFORMAT") &&
- (fmt=alGetEnumValue("AL_FORMAT_BFORMAT3D8")) != AL_NONE && fmt != -1)
+ if(mCodecCtx->channel_layout == 0 && mCodecCtx->channels >= 4
+ && alIsExtensionPresent("AL_EXT_BFORMAT"))
{
- int order{static_cast<int>(std::sqrt(mCodecCtx->channels)) - 1};
- if((order+1)*(order+1) == mCodecCtx->channels ||
- (order+1)*(order+1) + 2 == mCodecCtx->channels)
+ auto order = static_cast<int>(std::sqrt(mCodecCtx->channels)) - 1;
+ int channels{(order+1) * (order+1)};
+ if(channels == mCodecCtx->channels || channels+2 == mCodecCtx->channels)
{
mFrameSize *= 4;
- mFormat = fmt;
+ mFormat = alGetEnumValue("AL_FORMAT_BFORMAT3D_8");
}
}
- if(!mFormat)
+ if(!mFormat || mFormat == -1)
{
mDstChanLayout = AV_CH_LAYOUT_STEREO;
mFrameSize *= 2;
- mFormat = AL_FORMAT_STEREO8;
+ mFormat = FormatStereo8;
}
}
- if(!mFormat)
+ if(!mFormat || mFormat == -1)
{
mDstSampleFmt = AV_SAMPLE_FMT_S16;
mFrameSize = 2;
- if(mCodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1 &&
- alIsExtensionPresent("AL_EXT_MCFORMATS") &&
- (fmt=alGetEnumValue("AL_FORMAT_71CHN16")) != AL_NONE && fmt != -1)
+ if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
{
- mDstChanLayout = mCodecCtx->channel_layout;
- mFrameSize *= 8;
- mFormat = fmt;
- }
- if((mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1 ||
- mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK) &&
- alIsExtensionPresent("AL_EXT_MCFORMATS") &&
- (fmt=alGetEnumValue("AL_FORMAT_51CHN16")) != AL_NONE && fmt != -1)
- {
- mDstChanLayout = mCodecCtx->channel_layout;
- mFrameSize *= 6;
- mFormat = fmt;
+ if(mCodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1)
+ {
+ mDstChanLayout = mCodecCtx->channel_layout;
+ mFrameSize *= 8;
+ mFormat = alGetEnumValue("AL_FORMAT_71CHN16");
+ }
+ if(mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1
+ || mCodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK)
+ {
+ mDstChanLayout = mCodecCtx->channel_layout;
+ mFrameSize *= 6;
+ mFormat = alGetEnumValue("AL_FORMAT_51CHN16");
+ }
+ if(mCodecCtx->channel_layout == AV_CH_LAYOUT_QUAD)
+ {
+ mDstChanLayout = mCodecCtx->channel_layout;
+ mFrameSize *= 4;
+ mFormat = alGetEnumValue("AL_FORMAT_QUAD16");
+ }
}
if(mCodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
{
@@ -1089,23 +1137,22 @@ int AudioState::handler()
mFrameSize *= 1;
mFormat = AL_FORMAT_MONO16;
}
- if(mCodecCtx->channel_layout == 0 && mCodecCtx->channels >= 4 &&
- alIsExtensionPresent("AL_EXT_BFORMAT") &&
- (fmt=alGetEnumValue("AL_FORMAT_BFORMAT3D16")) != AL_NONE && fmt != -1)
+ if(mCodecCtx->channel_layout == 0 && mCodecCtx->channels >= 4
+ && alIsExtensionPresent("AL_EXT_BFORMAT"))
{
- int order{static_cast<int>(std::sqrt(mCodecCtx->channels)) - 1};
- if((order+1)*(order+1) == mCodecCtx->channels ||
- (order+1)*(order+1) + 2 == mCodecCtx->channels)
+ auto order = static_cast<int>(std::sqrt(mCodecCtx->channels)) - 1;
+ int channels{(order+1) * (order+1)};
+ if(channels == mCodecCtx->channels || channels+2 == mCodecCtx->channels)
{
mFrameSize *= 4;
- mFormat = fmt;
+ mFormat = alGetEnumValue("AL_FORMAT_BFORMAT3D_16");
}
}
- if(!mFormat)
+ if(!mFormat || mFormat == -1)
{
mDstChanLayout = AV_CH_LAYOUT_STEREO;
mFrameSize *= 2;
- mFormat = AL_FORMAT_STEREO16;
+ mFormat = FormatStereo16;
}
}
void *samples{nullptr};
@@ -1986,6 +2033,20 @@ int main(int argc, char *argv[])
EnableWideStereo = true;
}
}
+ else if(strcmp(argv[fileidx], "-uhj") == 0)
+ {
+#ifdef AL_SOFT_UHJ
+ if(!alIsExtensionPresent("AL_SOFTX_UHJ"))
+ std::cerr<< "AL_SOFT_UHJ not supported for UHJ decoding" <<std::endl;
+ else
+ {
+ std::cout<< "Found AL_SOFT_UHJ" <<std::endl;
+ EnableUhjDecode = true;
+ }
+#else
+ std::cerr<< "AL_SOFT_UHJ not supported for UHJ decoding" <<std::endl;
+#endif
+ }
else if(strcmp(argv[fileidx], "-novideo") == 0)
DisableVideo = true;
else