Skip to content

Commit

Permalink
Flip the sign for the super stereo phase shift components
Browse files Browse the repository at this point in the history
This shouldn't have any perceptual difference as the relative phase differences
are maintained, but this set up works nicer with 2-channel UHJ encoding.
Previously the stereo separation would be severely attenuated with 2-channel
UHJ output, whereas this better keeps the stereo separation with slightly
increased phase separation.
  • Loading branch information
kcat committed Jun 28, 2024
1 parent ac2983f commit 1f672eb
Showing 1 changed file with 15 additions and 15 deletions.
30 changes: 15 additions & 15 deletions core/uhjfilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -543,9 +543,9 @@ void UhjDecoderIIR::decode(const al::span<float*> samples, const size_t samplesT
* S = Left + Right
* D = Left - Right
*
* W = 0.6098637*S - 0.6896511*j*w*D
* X = 0.8624776*S + 0.7626955*j*w*D
* Y = 1.6822415*w*D - 0.2156194*j*S
* W = 0.6098637*S + 0.6896511*j*w*D
* X = 0.8624776*S - 0.7626955*j*w*D
* Y = 1.6822415*w*D + 0.2156194*j*S
*
* where j is a +90 degree phase shift. w is a variable control for the
* resulting stereo width, with the range 0 <= w <= 0.7.
Expand Down Expand Up @@ -611,12 +611,12 @@ void UhjStereoDecoder<N>::decode(const al::span<float*> samples, const size_t sa
std::copy_n(mTemp.cbegin()+samplesToDo, mDTHistory.size(), mDTHistory.begin());
PShift.process(xoutput, mTemp);

/* W = 0.6098637*S - 0.6896511*j*w*D */
/* W = 0.6098637*S + 0.6896511*j*w*D */
std::transform(mS.begin(), mS.begin()+samplesToDo, xoutput.begin(), woutput.begin(),
[](const float s, const float jd) noexcept { return 0.6098637f*s - 0.6896511f*jd; });
/* X = 0.8624776*S + 0.7626955*j*w*D */
[](const float s, const float jd) noexcept { return 0.6098637f*s + 0.6896511f*jd; });
/* X = 0.8624776*S - 0.7626955*j*w*D */
std::transform(mS.begin(), mS.begin()+samplesToDo, xoutput.begin(), xoutput.begin(),
[](const float s, const float jd) noexcept { return 0.8624776f*s + 0.7626955f*jd; });
[](const float s, const float jd) noexcept { return 0.8624776f*s - 0.7626955f*jd; });

/* Precompute j*S and store in youtput. */
tmpiter = std::copy(mSHistory.cbegin(), mSHistory.cend(), mTemp.begin());
Expand All @@ -625,9 +625,9 @@ void UhjStereoDecoder<N>::decode(const al::span<float*> samples, const size_t sa
std::copy_n(mTemp.cbegin()+samplesToDo, mSHistory.size(), mSHistory.begin());
PShift.process(youtput, mTemp);

/* Y = 1.6822415*w*D - 0.2156194*j*S */
/* Y = 1.6822415*w*D + 0.2156194*j*S */
std::transform(mD.begin(), mD.begin()+samplesToDo, youtput.begin(), youtput.begin(),
[](const float d, const float js) noexcept { return 1.6822415f*d - 0.2156194f*js; });
[](const float d, const float js) noexcept { return 1.6822415f*d + 0.2156194f*js; });
}

void UhjStereoDecoderIIR::decode(const al::span<float*> samples, const size_t samplesToDo,
Expand Down Expand Up @@ -689,12 +689,12 @@ void UhjStereoDecoderIIR::decode(const al::span<float*> samples, const size_t sa
if(mFirstRun) mFilter2D.processOne(Filter2Coeff, mD[0]);
mFilter2D.process(Filter2Coeff, al::span{mD}.subspan(1, samplesToDo), updateState, xoutput);

/* W = 0.6098637*S - 0.6896511*j*w*D */
/* W = 0.6098637*S + 0.6896511*j*w*D */
std::transform(mTemp.begin(), mTemp.begin()+samplesToDo, xoutput.begin(), woutput.begin(),
[](const float s, const float jd) noexcept { return 0.6098637f*s - 0.6896511f*jd; });
/* X = 0.8624776*S + 0.7626955*j*w*D */
[](const float s, const float jd) noexcept { return 0.6098637f*s + 0.6896511f*jd; });
/* X = 0.8624776*S - 0.7626955*j*w*D */
std::transform(mTemp.begin(), mTemp.begin()+samplesToDo, xoutput.begin(), xoutput.begin(),
[](const float s, const float jd) noexcept { return 0.8624776f*s + 0.7626955f*jd; });
[](const float s, const float jd) noexcept { return 0.8624776f*s - 0.7626955f*jd; });

/* Precompute j*S and store in youtput. */
if(mFirstRun) mFilter2S.processOne(Filter2Coeff, mS[0]);
Expand All @@ -703,9 +703,9 @@ void UhjStereoDecoderIIR::decode(const al::span<float*> samples, const size_t sa
/* Apply filter1 to D and store in mTemp. */
mFilter1D.process(Filter1Coeff, al::span{mD}.first(samplesToDo), updateState, mTemp);

/* Y = 1.6822415*w*D - 0.2156194*j*S */
/* Y = 1.6822415*w*D + 0.2156194*j*S */
std::transform(mTemp.begin(), mTemp.begin()+samplesToDo, youtput.begin(), youtput.begin(),
[](const float d, const float js) noexcept { return 1.6822415f*d - 0.2156194f*js; });
[](const float d, const float js) noexcept { return 1.6822415f*d + 0.2156194f*js; });

mFirstRun = false;
}
Expand Down

0 comments on commit 1f672eb

Please sign in to comment.