@@ -106,9 +106,20 @@ constexpr auto assume_aligned_span(std::span<T,N> const s) noexcept -> std::span
106106 * Left = (S + D)/2
107107 * Right = (S - D)/2
108108 *
109+ * FIXME: There seems to be something incorrect in the initial conversion math,
110+ * as some tests indicate the height (Z) is inverted from what it should be.
111+ * That is, sounds above the horizon are encoded as if they're below the
112+ * horizon, both compared to other encodings, as well as with decoder tests.
113+ * I've tested and checked my transforms in different ways but get the same
114+ * result, suggesting this is accurate to the original math. This should be
115+ * invested, but to fix it for now, we just negate Z:
116+ *
117+ * S = 0.576794682542*W + 0.333130895776*X + 0.375368569468*Z
118+ * D = j(0.88801610065*W + -0.512878512974*X) + 0.666477825862*Y
119+ *
109120 * Or to preapply the half scale:
110121 *
111- * S = 0.288397341271*W + 0.166565447888*X + - 0.187684284734*Z
122+ * S = 0.288397341271*W + 0.166565447888*X + 0.187684284734*Z
112123 * D = j(0.444008050325*W + -0.256439256487*X) + 0.333238912931*Y
113124 *
114125 * Left = S + D
@@ -134,11 +145,11 @@ void TsmeEncoder<N>::encode(const std::span<float> LeftOut, const std::span<floa
134145 std::ranges::copy (zinput, std::next (mZ .begin (), sFilterDelay ));
135146 std::ranges::copy (xinput, std::next (mX .begin (), sFilterDelay ));
136147
137- /* S = 0.288397341271*W + 0.166565447888*X + - 0.187684284734*Z */
148+ /* S = 0.288397341271*W + 0.166565447888*X + 0.187684284734*Z */
138149 std::ranges::transform (mW | std::views::take (samplesToDo), mX , mS .begin (),
139150 [](const float w, const float x) { return 0 .288397341271f *w + 0 .166565447888f *x; });
140151 std::ranges::transform (mS | std::views::take (samplesToDo), mZ , mS .begin (),
141- [](const float wx, const float z) { return wx + - 0 .187684284734f *z; });
152+ [](const float wx, const float z) { return wx + 0 .187684284734f *z; });
142153
143154 /* Precompute j(0.444008050325*W + -0.256439256487*X) and store in mD. */
144155 auto dstore = mD .begin ();
@@ -267,11 +278,11 @@ void TsmeEncoderIIR::encode(const std::span<float> LeftOut, const std::span<floa
267278 const auto zinput = assume_aligned_span<16 >(InSamples[2 ].first (samplesToDo));
268279 const auto xinput = assume_aligned_span<16 >(InSamples[3 ].first (samplesToDo));
269280
270- /* S = 0.288397341271*W + 0.166565447888*X - 0.187684284734*Z */
281+ /* S = 0.288397341271*W + 0.166565447888*X + 0.187684284734*Z */
271282 std::ranges::transform (winput, xinput, mTemp .begin (),
272283 [](const float w, const float x) { return 0 .288397341271f *w + 0 .166565447888f *x; });
273284 std::ranges::transform (mTemp , zinput, mTemp .begin (),
274- [](const float wx, const float z) { return wx - 0 .187684284734f *z; });
285+ [](const float wx, const float z) { return wx + 0 .187684284734f *z; });
275286 process (mFilter1WXZ , Filter1Coeff, std::span{mTemp }.first (samplesToDo), true ,
276287 std::span{mS }.subspan (1 ));
277288 mS [0 ] = mDelayWXZ ; mDelayWXZ = mS [samplesToDo];
@@ -310,5 +321,4 @@ void TsmeEncoderIIR::encode(const std::span<float> LeftOut, const std::span<floa
310321}
311322
312323template struct TsmeEncoder <TsmeLength256>;
313-
314324template struct TsmeEncoder <TsmeLength512>;
0 commit comments