Add support for 4-channel UHJ
Also add the SOFT moniker to the new macros
This commit is contained in:
parent
b5e36007f1
commit
f33edc3b30
@ -275,6 +275,7 @@ ALuint ChannelsFromUserFmt(UserFmtChannels chans, ALuint ambiorder) noexcept
|
||||
case UserFmtBFormat3D: return (ambiorder+1) * (ambiorder+1);
|
||||
case UserFmtUHJ2: return 2;
|
||||
case UserFmtUHJ3: return 3;
|
||||
case UserFmtUHJ4: return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -471,6 +472,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
|
||||
case UserFmtBFormat3D: DstChannels = FmtBFormat3D; break;
|
||||
case UserFmtUHJ2: DstChannels = FmtUHJ2; break;
|
||||
case UserFmtUHJ3: DstChannels = FmtUHJ3; break;
|
||||
case UserFmtUHJ4: DstChannels = FmtUHJ4; break;
|
||||
}
|
||||
if UNLIKELY(static_cast<long>(SrcChannels) != static_cast<long>(DstChannels))
|
||||
SETERR_RETURN(context, AL_INVALID_ENUM, , "Invalid format");
|
||||
@ -507,7 +509,9 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
|
||||
unpackalign, NameFromUserFmtType(SrcType));
|
||||
|
||||
const ALuint ambiorder{(DstChannels == FmtBFormat2D || DstChannels == FmtBFormat3D) ?
|
||||
ALBuf->UnpackAmbiOrder : ((DstChannels == FmtUHJ2 || DstChannels == FmtUHJ3) ? 1 : 0)};
|
||||
ALBuf->UnpackAmbiOrder :
|
||||
((DstChannels == FmtUHJ2 || DstChannels == FmtUHJ3 || DstChannels == FmtUHJ4) ? 1 :
|
||||
0)};
|
||||
|
||||
if((access&AL_PRESERVE_DATA_BIT_SOFT))
|
||||
{
|
||||
@ -630,6 +634,7 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq,
|
||||
case UserFmtBFormat3D: DstChannels = FmtBFormat3D; break;
|
||||
case UserFmtUHJ2: DstChannels = FmtUHJ2; break;
|
||||
case UserFmtUHJ3: DstChannels = FmtUHJ3; break;
|
||||
case UserFmtUHJ4: DstChannels = FmtUHJ4; break;
|
||||
}
|
||||
if UNLIKELY(static_cast<long>(SrcChannels) != static_cast<long>(DstChannels))
|
||||
SETERR_RETURN(context, AL_INVALID_ENUM,, "Invalid format");
|
||||
@ -651,7 +656,9 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq,
|
||||
SETERR_RETURN(context, AL_INVALID_ENUM,, "Unsupported callback format");
|
||||
|
||||
const ALuint ambiorder{(DstChannels == FmtBFormat2D || DstChannels == FmtBFormat3D) ?
|
||||
ALBuf->UnpackAmbiOrder : ((DstChannels == FmtUHJ2 || DstChannels == FmtUHJ3) ? 1 : 0)};
|
||||
ALBuf->UnpackAmbiOrder :
|
||||
((DstChannels == FmtUHJ2 || DstChannels == FmtUHJ3 || DstChannels == FmtUHJ4) ? 1 :
|
||||
0)};
|
||||
|
||||
constexpr uint line_size{BufferLineSize + MaxPostVoiceLoad};
|
||||
al::vector<al::byte,16>(FrameSizeFromFmt(DstChannels, DstType, ambiorder) *
|
||||
@ -684,7 +691,7 @@ al::optional<DecompResult> DecomposeUserFormat(ALenum format)
|
||||
UserFmtChannels channels;
|
||||
UserFmtType type;
|
||||
};
|
||||
static const std::array<FormatMap,52> UserFmtList{{
|
||||
static const std::array<FormatMap,55> UserFmtList{{
|
||||
{ AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte },
|
||||
{ AL_FORMAT_MONO16, UserFmtMono, UserFmtShort },
|
||||
{ AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat },
|
||||
@ -741,13 +748,17 @@ al::optional<DecompResult> DecomposeUserFormat(ALenum format)
|
||||
{ AL_FORMAT_BFORMAT3D_FLOAT32, UserFmtBFormat3D, UserFmtFloat },
|
||||
{ AL_FORMAT_BFORMAT3D_MULAW, UserFmtBFormat3D, UserFmtMulaw },
|
||||
|
||||
{ AL_FORMAT_UHJ2CHN8, UserFmtUHJ2, UserFmtUByte },
|
||||
{ AL_FORMAT_UHJ2CHN16, UserFmtUHJ2, UserFmtShort },
|
||||
{ AL_FORMAT_UHJ2CHN_FLOAT32, UserFmtUHJ2, UserFmtFloat },
|
||||
{ AL_FORMAT_UHJ2CHN8_SOFT, UserFmtUHJ2, UserFmtUByte },
|
||||
{ AL_FORMAT_UHJ2CHN16_SOFT, UserFmtUHJ2, UserFmtShort },
|
||||
{ AL_FORMAT_UHJ2CHN_FLOAT32_SOFT, UserFmtUHJ2, UserFmtFloat },
|
||||
|
||||
{ AL_FORMAT_UHJ3CHN8, UserFmtUHJ3, UserFmtUByte },
|
||||
{ AL_FORMAT_UHJ3CHN16, UserFmtUHJ3, UserFmtShort },
|
||||
{ AL_FORMAT_UHJ3CHN_FLOAT32, UserFmtUHJ3, UserFmtFloat },
|
||||
{ AL_FORMAT_UHJ3CHN8_SOFT, UserFmtUHJ3, UserFmtUByte },
|
||||
{ AL_FORMAT_UHJ3CHN16_SOFT, UserFmtUHJ3, UserFmtShort },
|
||||
{ AL_FORMAT_UHJ3CHN_FLOAT32_SOFT, UserFmtUHJ3, UserFmtFloat },
|
||||
|
||||
{ AL_FORMAT_UHJ4CHN8_SOFT, UserFmtUHJ4, UserFmtUByte },
|
||||
{ AL_FORMAT_UHJ4CHN16_SOFT, UserFmtUHJ4, UserFmtShort },
|
||||
{ AL_FORMAT_UHJ4CHN_FLOAT32_SOFT, UserFmtUHJ4, UserFmtFloat },
|
||||
}};
|
||||
|
||||
for(const auto &fmt : UserFmtList)
|
||||
|
@ -37,6 +37,7 @@ enum UserFmtChannels : unsigned char {
|
||||
UserFmtBFormat3D = FmtBFormat3D,
|
||||
UserFmtUHJ2 = FmtUHJ2,
|
||||
UserFmtUHJ3 = FmtUHJ3,
|
||||
UserFmtUHJ4 = FmtUHJ4,
|
||||
};
|
||||
|
||||
|
||||
|
@ -444,10 +444,10 @@ void InitVoice(Voice *voice, ALsource *source, ALbufferQueueItem *BufferList, AL
|
||||
voice->mFmtChannels = buffer->mChannels;
|
||||
voice->mFmtType = buffer->mType;
|
||||
voice->mFrameSize = buffer->frameSizeFromFmt();
|
||||
voice->mAmbiLayout = (buffer->mChannels==FmtUHJ2 || buffer->mChannels==FmtUHJ3) ?
|
||||
AmbiLayout::FuMa : buffer->mAmbiLayout;
|
||||
voice->mAmbiScaling = (buffer->mChannels==FmtUHJ2 || buffer->mChannels==FmtUHJ3) ?
|
||||
AmbiScaling::FuMa : buffer->mAmbiScaling;
|
||||
voice->mAmbiLayout = (buffer->mChannels == FmtUHJ2 || buffer->mChannels == FmtUHJ3
|
||||
|| voice->mFmtChannels == FmtUHJ4) ? AmbiLayout::FuMa : buffer->mAmbiLayout;
|
||||
voice->mAmbiScaling = (buffer->mChannels == FmtUHJ2 || buffer->mChannels == FmtUHJ3
|
||||
|| voice->mFmtChannels == FmtUHJ4) ? AmbiScaling::FuMa : buffer->mAmbiScaling;
|
||||
voice->mAmbiOrder = buffer->mAmbiOrder;
|
||||
|
||||
if(buffer->mCallback) voice->mFlags |= VoiceIsCallback;
|
||||
|
@ -791,13 +791,15 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
|
||||
case FmtBFormat3D:
|
||||
case FmtUHJ2:
|
||||
case FmtUHJ3:
|
||||
case FmtUHJ4:
|
||||
DirectChannels = DirectMode::Off;
|
||||
break;
|
||||
}
|
||||
|
||||
voice->mFlags &= ~(VoiceHasHrtf | VoiceHasNfc);
|
||||
if(voice->mFmtChannels == FmtBFormat2D || voice->mFmtChannels == FmtBFormat3D
|
||||
|| voice->mFmtChannels == FmtUHJ2 || voice->mFmtChannels == FmtUHJ3)
|
||||
|| voice->mFmtChannels == FmtUHJ2 || voice->mFmtChannels == FmtUHJ3
|
||||
|| voice->mFmtChannels == FmtUHJ4)
|
||||
{
|
||||
/* Special handling for B-Format sources. */
|
||||
|
||||
@ -1560,7 +1562,8 @@ void CalcSourceParams(Voice *voice, ALCcontext *context, bool force)
|
||||
|
||||
if((voice->mProps.DirectChannels != DirectMode::Off && voice->mFmtChannels != FmtMono
|
||||
&& voice->mFmtChannels != FmtBFormat2D && voice->mFmtChannels != FmtBFormat3D
|
||||
&& voice->mFmtChannels != FmtUHJ2 && voice->mFmtChannels != FmtUHJ3)
|
||||
&& voice->mFmtChannels != FmtUHJ2 && voice->mFmtChannels != FmtUHJ3
|
||||
&& voice->mFmtChannels != FmtUHJ3)
|
||||
|| voice->mProps.mSpatializeMode==SpatializeMode::Off
|
||||
|| (voice->mProps.mSpatializeMode==SpatializeMode::Auto && voice->mFmtChannels != FmtMono))
|
||||
CalcNonAttnSourceParams(voice, &voice->mProps, context);
|
||||
|
@ -35,6 +35,7 @@ uint ChannelsFromFmt(FmtChannels chans, uint ambiorder) noexcept
|
||||
case FmtBFormat3D: return (ambiorder+1) * (ambiorder+1);
|
||||
case FmtUHJ2: return 2;
|
||||
case FmtUHJ3: return 3;
|
||||
case FmtUHJ4: return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ enum FmtChannels : unsigned char {
|
||||
FmtBFormat3D,
|
||||
FmtUHJ2, /* 2-channel UHJ, aka "BHJ", stereo-compatible */
|
||||
FmtUHJ3, /* 3-channel UHJ, aka "THJ", first-two channels are stereo-compatible */
|
||||
FmtUHJ4, /* 4-channel UHJ, aka "PHJ", first-two channels are stereo-compatible */
|
||||
};
|
||||
|
||||
enum class AmbiLayout : unsigned char {
|
||||
|
@ -382,7 +382,7 @@ void ConvolutionState::update(const ALCcontext *context, const EffectSlot *slot,
|
||||
* Not that UHJ should really ever be used for convolution, but it's a
|
||||
* valid format regardless.
|
||||
*/
|
||||
if((mChannels == FmtUHJ2 || mChannels == FmtUHJ3) && target.RealOut
|
||||
if((mChannels == FmtUHJ2 || mChannels == FmtUHJ3 || mChannels == FmtUHJ4) && target.RealOut
|
||||
&& target.RealOut->ChannelIndex[FrontLeft] != INVALID_CHANNEL_INDEX
|
||||
&& target.RealOut->ChannelIndex[FrontRight] != INVALID_CHANNEL_INDEX)
|
||||
{
|
||||
@ -436,6 +436,7 @@ void ConvolutionState::update(const ALCcontext *context, const EffectSlot *slot,
|
||||
case FmtBFormat3D:
|
||||
case FmtUHJ2:
|
||||
case FmtUHJ3:
|
||||
case FmtUHJ4:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -78,12 +78,15 @@ ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, const ALCchar *de
|
||||
|
||||
#ifndef AL_SOFT_UHJ
|
||||
#define AL_SOFT_UHJ
|
||||
#define AL_FORMAT_UHJ2CHN8 0x19A2
|
||||
#define AL_FORMAT_UHJ2CHN16 0x19A3
|
||||
#define AL_FORMAT_UHJ2CHN_FLOAT32 0x19A4
|
||||
#define AL_FORMAT_UHJ3CHN8 0x19A5
|
||||
#define AL_FORMAT_UHJ3CHN16 0x19A6
|
||||
#define AL_FORMAT_UHJ3CHN_FLOAT32 0x19A7
|
||||
#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
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -529,7 +529,8 @@ void Voice::mix(const State vstate, ALCcontext *Context, const uint SamplesToDo)
|
||||
Counter = std::min(Counter, 64u);
|
||||
|
||||
const uint PostPadding{MaxResamplerEdge +
|
||||
((mFmtChannels==FmtUHJ2 || mFmtChannels==FmtUHJ3) ? uint{UhjDecoder::sFilterDelay} : 0u)};
|
||||
((mFmtChannels==FmtUHJ2 || mFmtChannels==FmtUHJ3 || mFmtChannels==FmtUHJ4)
|
||||
? uint{UhjDecoder::sFilterDelay} : 0u)};
|
||||
uint buffers_done{0u};
|
||||
uint OutPos{0u};
|
||||
do {
|
||||
@ -635,9 +636,12 @@ void Voice::mix(const State vstate, ALCcontext *Context, const uint SamplesToDo)
|
||||
|
||||
if(mDecoder)
|
||||
{
|
||||
std::array<float*,3> samples{{mVoiceSamples[0].data() + MaxResamplerEdge,
|
||||
std::array<float*,4> samples{{mVoiceSamples[0].data() + MaxResamplerEdge,
|
||||
mVoiceSamples[1].data() + MaxResamplerEdge,
|
||||
mVoiceSamples[2].data() + MaxResamplerEdge}};
|
||||
mVoiceSamples[2].data() + MaxResamplerEdge,
|
||||
nullptr}};
|
||||
if(mVoiceSamples.size() > 3)
|
||||
samples[3] = mVoiceSamples[3].data() + MaxResamplerEdge;
|
||||
const size_t srcOffset{(increment*DstBufferSize + DataPosFrac)>>MixerFracBits};
|
||||
SrcBufferSize = SrcBufferSize - PostPadding + MaxResamplerEdge;
|
||||
mDecoder->decode(samples, SrcBufferSize, srcOffset);
|
||||
@ -823,9 +827,9 @@ void Voice::mix(const State vstate, ALCcontext *Context, const uint SamplesToDo)
|
||||
|
||||
void Voice::prepare(ALCdevice *device)
|
||||
{
|
||||
if((mFmtChannels == FmtUHJ2 || mFmtChannels == FmtUHJ3) && !mDecoder)
|
||||
if((mFmtChannels == FmtUHJ2 || mFmtChannels == FmtUHJ3 || mFmtChannels==FmtUHJ4) && !mDecoder)
|
||||
mDecoder = std::make_unique<UhjDecoder>();
|
||||
else if(mFmtChannels != FmtUHJ2 && mFmtChannels != FmtUHJ3)
|
||||
else if(mFmtChannels != FmtUHJ2 && mFmtChannels != FmtUHJ3 && mFmtChannels != FmtUHJ4)
|
||||
mDecoder = nullptr;
|
||||
|
||||
/* Clear the stepping value explicitly so the mixer knows not to mix this
|
||||
|
@ -109,7 +109,7 @@ void Uhj2Encoder::encode(const FloatBufferSpan LeftOut, const FloatBufferSpan Ri
|
||||
* UHJ should not be run through a normal B-Format decoder, as it needs
|
||||
* different shelf filters.
|
||||
*/
|
||||
void UhjDecoder::decode(const al::span<float*, 3> Samples, const size_t SamplesToDo,
|
||||
void UhjDecoder::decode(const al::span<float*,4> Samples, const size_t SamplesToDo,
|
||||
const size_t ForwardSamples)
|
||||
{
|
||||
ASSUME(SamplesToDo > 0);
|
||||
@ -137,13 +137,12 @@ void UhjDecoder::decode(const al::span<float*, 3> Samples, const size_t SamplesT
|
||||
std::copy_n(mTemp.cbegin()+ForwardSamples, mDTHistory.size(), mDTHistory.begin());
|
||||
PShift.process({xoutput, SamplesToDo}, mTemp.data());
|
||||
|
||||
/* W = 0.981530*S + 0.197484*j(0.828347*D + 0.767835*T) */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
{
|
||||
/* W = 0.981530*S + 0.197484*j(0.828347*D + 0.767835*T) */
|
||||
woutput[i] = 0.981530f*mS[i] + 0.197484f*xoutput[i];
|
||||
/* X = 0.418504*S - j(0.828347*D + 0.767835*T) */
|
||||
/* X = 0.418504*S - j(0.828347*D + 0.767835*T) */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
xoutput[i] = 0.418504f*mS[i] - xoutput[i];
|
||||
}
|
||||
|
||||
/* Precompute j*S and store in youtput. */
|
||||
tmpiter = std::copy(mSHistory.cbegin(), mSHistory.cend(), mTemp.begin());
|
||||
@ -151,9 +150,14 @@ void UhjDecoder::decode(const al::span<float*, 3> Samples, const size_t SamplesT
|
||||
std::copy_n(mTemp.cbegin()+ForwardSamples, mSHistory.size(), mSHistory.begin());
|
||||
PShift.process({youtput, SamplesToDo}, mTemp.data());
|
||||
|
||||
/* Y = 0.795954*D - 0.676406*T + j(0.186626*S) */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
{
|
||||
/* Y = 0.795954*D - 0.676406*T + j(0.186626*S) */
|
||||
youtput[i] = 0.795954f*mD[i] - 0.676406f*mT[i] + 0.186626f*youtput[i];
|
||||
|
||||
if(Samples[3])
|
||||
{
|
||||
/* Z = 1.023332*Q */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
Samples[3][i] = 1.023332f*Samples[3][i];
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ struct UhjDecoder {
|
||||
|
||||
alignas(16) std::array<float,BufferLineSize+MaxResamplerEdge + sFilterDelay*2> mTemp{};
|
||||
|
||||
void decode(const al::span<float*,3> Samples, const size_t SamplesToDo,
|
||||
void decode(const al::span<float*,4> Samples, const size_t SamplesToDo,
|
||||
const size_t ForwardSamples);
|
||||
|
||||
DEF_NEWDEL(UhjDecoder)
|
||||
|
Loading…
x
Reference in New Issue
Block a user