diff options
-rw-r--r-- | al/buffer.cpp | 29 | ||||
-rw-r--r-- | al/buffer.h | 1 | ||||
-rw-r--r-- | al/source.cpp | 8 | ||||
-rw-r--r-- | alc/alu.cpp | 7 | ||||
-rw-r--r-- | alc/buffer_storage.cpp | 1 | ||||
-rw-r--r-- | alc/buffer_storage.h | 1 | ||||
-rw-r--r-- | alc/effects/convolution.cpp | 3 | ||||
-rw-r--r-- | alc/inprogext.h | 15 | ||||
-rw-r--r-- | alc/voice.cpp | 14 | ||||
-rw-r--r-- | core/uhjfilter.cpp | 18 | ||||
-rw-r--r-- | core/uhjfilter.h | 2 |
11 files changed, 64 insertions, 35 deletions
diff --git a/al/buffer.cpp b/al/buffer.cpp index 23020559..6b82ce7f 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -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) diff --git a/al/buffer.h b/al/buffer.h index 47729cbe..a9bc0e71 100644 --- a/al/buffer.h +++ b/al/buffer.h @@ -37,6 +37,7 @@ enum UserFmtChannels : unsigned char { UserFmtBFormat3D = FmtBFormat3D, UserFmtUHJ2 = FmtUHJ2, UserFmtUHJ3 = FmtUHJ3, + UserFmtUHJ4 = FmtUHJ4, }; diff --git a/al/source.cpp b/al/source.cpp index 6d56549a..72337d74 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -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; diff --git a/alc/alu.cpp b/alc/alu.cpp index 7e6d6ca6..57cea740 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -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); diff --git a/alc/buffer_storage.cpp b/alc/buffer_storage.cpp index 1e35220a..3eb1e28a 100644 --- a/alc/buffer_storage.cpp +++ b/alc/buffer_storage.cpp @@ -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; } diff --git a/alc/buffer_storage.h b/alc/buffer_storage.h index 135b9b83..733a62e3 100644 --- a/alc/buffer_storage.h +++ b/alc/buffer_storage.h @@ -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 { diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index 1ee59604..5bb52656 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -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; } diff --git a/alc/inprogext.h b/alc/inprogext.h index 4f9c6715..091703e2 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -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 diff --git a/alc/voice.cpp b/alc/voice.cpp index 577d5f72..7e761b29 100644 --- a/alc/voice.cpp +++ b/alc/voice.cpp @@ -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 diff --git a/core/uhjfilter.cpp b/core/uhjfilter.cpp index d535522c..6f01e608 100644 --- a/core/uhjfilter.cpp +++ b/core/uhjfilter.cpp @@ -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]; } } diff --git a/core/uhjfilter.h b/core/uhjfilter.h index b07488e5..22b3d4df 100644 --- a/core/uhjfilter.h +++ b/core/uhjfilter.h @@ -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) |