aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2021-03-20 03:03:47 -0700
committerChris Robinson <[email protected]>2021-03-20 03:14:10 -0700
commit7c697b9178b2f7bff6fec4fa9cbbf5390f13d2e5 (patch)
treee05fc701e07494da6974988e776ed33a92a38656 /core
parent063da94bd8f4e2dc0369c283a7fa0f124764eb1c (diff)
Fix the UHJ all-pass delay
For real this time. The non-all-passed signal needs a one-sample delay over the all-passed signal. Because of the way the all-pass FIR filter is structured, it wouldn't otherwise use the last buffered sample, allowing it to be shifted forward in time by one sample. Also, remove a couple unnecessary buffers.
Diffstat (limited to 'core')
-rw-r--r--core/uhjfilter.cpp12
-rw-r--r--core/uhjfilter.h7
2 files changed, 8 insertions, 11 deletions
diff --git a/core/uhjfilter.cpp b/core/uhjfilter.cpp
index 2dd41d15..3fbec3b3 100644
--- a/core/uhjfilter.cpp
+++ b/core/uhjfilter.cpp
@@ -244,13 +244,13 @@ void Uhj2Encoder::encode(const FloatBufferSpan LeftOut, const FloatBufferSpan Ri
/* Combine the previously delayed mid/side signal with the input. */
/* S = 0.9396926*W + 0.1855740*X */
- auto miditer = std::copy(mMidDelay.cbegin(), mMidDelay.cend(), mMid.begin());
+ auto miditer = mMid.begin() + sFilterSize;
std::transform(winput, winput+SamplesToDo, xinput, miditer,
[](const float w, const float x) noexcept -> float
{ return 0.9396926f*w + 0.1855740f*x; });
/* D = 0.6554516*Y */
- auto sideiter = std::copy(mSideDelay.cbegin(), mSideDelay.cend(), mSide.begin());
+ auto sideiter = mSide.begin() + sFilterSize;
std::transform(yinput, yinput+SamplesToDo, sideiter,
[](const float y) noexcept -> float { return 0.6554516f*y; });
@@ -260,10 +260,6 @@ void Uhj2Encoder::encode(const FloatBufferSpan LeftOut, const FloatBufferSpan Ri
for(size_t i{0};i < SamplesToDo;++i,++sideiter)
*sideiter += left[i] - right[i];
- /* Copy the future samples back to the delay buffers for next time. */
- std::copy_n(mMid.cbegin()+SamplesToDo, mMidDelay.size(), mMidDelay.begin());
- std::copy_n(mSide.cbegin()+SamplesToDo, mSideDelay.size(), mSideDelay.begin());
-
/* Now add the all-passed signal into the side signal. */
/* D += j(-0.3420201*W + 0.5098604*X) */
@@ -280,4 +276,8 @@ void Uhj2Encoder::encode(const FloatBufferSpan LeftOut, const FloatBufferSpan Ri
/* Right = (S - D)/2.0 */
for(size_t i{0};i < SamplesToDo;i++)
right[i] = (mMid[i] - mSide[i]) * 0.5f;
+
+ /* Copy the future samples to the front for next time. */
+ std::copy(mMid.cbegin()+SamplesToDo, mMid.cbegin()+SamplesToDo+sFilterSize, mMid.begin());
+ std::copy(mSide.cbegin()+SamplesToDo, mSide.cbegin()+SamplesToDo+sFilterSize, mSide.begin());
}
diff --git a/core/uhjfilter.h b/core/uhjfilter.h
index 7609533b..ff794355 100644
--- a/core/uhjfilter.h
+++ b/core/uhjfilter.h
@@ -14,15 +14,12 @@ struct Uhj2Encoder {
*/
constexpr static size_t sFilterSize{128};
- /* Delays for the unfiltered signal. */
- alignas(16) std::array<float,sFilterSize> mMidDelay{};
- alignas(16) std::array<float,sFilterSize> mSideDelay{};
-
+ /* Delays and processing storage for the unfiltered signal. */
alignas(16) std::array<float,BufferLineSize+sFilterSize> mMid{};
alignas(16) std::array<float,BufferLineSize+sFilterSize> mSide{};
/* History for the FIR filter. */
- alignas(16) std::array<float,sFilterSize*2> mSideHistory{};
+ alignas(16) std::array<float,sFilterSize*2 - 1> mSideHistory{};
alignas(16) std::array<float,BufferLineSize + sFilterSize*2> mTemp{};