From b2fd8fde86d421109d7922ded7b4691384af2214 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Tue, 20 Jun 2023 02:47:17 +0200
Subject: [PATCH] lavu/tx: make 32-bit fixed-point transforms more bitexact
Using the sqrt/cos/sin approximations we have, the only parts left
which may be inexact are multiplies and divisions in some transforms.
---
libavutil/tx_priv.h | 2 ++
libavutil/tx_template.c | 38 +++++++++++++++++++++++++++----
tests/fate/ac3.mak | 2 +-
tests/ref/fate/unknown_layout-ac3 | 2 +-
tests/ref/lavf/rm | 2 +-
5 files changed, 38 insertions(+), 8 deletions(-)
@@ -110,6 +110,8 @@ typedef void TXComplex;
#elif defined(TX_INT32)
+#include "softfloat.h"
+
/* Properly rounds the result */
#define CMUL(dre, dim, are, aim, bre, bim) \
do { \
@@ -60,6 +60,17 @@ typedef struct FFTabInitData {
int factors[TX_MAX_SUB]; /* Must be sorted high -> low */
} FFTabInitData;
+#if defined(TX_INT32)
+static TXSample COS_GEN(double freq)
+{
+ int c_f, s_f;
+ av_sincos_sf(llrintf(freq * (1 << 30) / M_PI), &s_f, &c_f);
+ return av_clip64(((int64_t)c_f) << 1, INT32_MIN, INT32_MAX);
+}
+#else
+#define COS_GEN cos
+#endif
+
#define SR_TABLE(len) \
static av_cold void TX_TAB(ff_tx_init_tab_ ##len)(void) \
{ \
@@ -67,7 +78,7 @@ static av_cold void TX_TAB(ff_tx_init_tab_ ##len)(void) \
TXSample *tab = TX_TAB(ff_tx_tab_ ##len); \
\
for (int i = 0; i < len/4; i++) \
- *tab++ = RESCALE(cos(i*freq)); \
+ *tab++ = COS_GEN(i*freq); \
\
*tab = 0; \
}
@@ -1903,22 +1914,39 @@ int TX_TAB(ff_tx_mdct_gen_exp)(AVTXContext *s, int *pre_tab)
{
int off = 0;
int len4 = s->len >> 1;
- double scale = s->scale_d;
- const double theta = (scale < 0 ? len4 : 0) + 1.0/8.0;
+ const double theta = (s->scale_d < 0 ? len4 : 0) + 1.0/8.0;
size_t alloc = pre_tab ? 2*len4 : len4;
+#if defined(TX_INT32)
+ int scale = llrintf(fabs(s->scale_d) * (1 << 30));
+ SoftFloat scale_sf = av_int2sf(scale, 30);
+ scale_sf = av_sqrt_sf(scale_sf);
+#else
+ double scale = sqrt(fabs(s->scale_d));
+#endif
+
if (!(s->exp = av_malloc_array(alloc, sizeof(*s->exp))))
return AVERROR(ENOMEM);
- scale = sqrt(fabs(scale));
-
if (pre_tab)
off = len4;
for (int i = 0; i < len4; i++) {
const double alpha = M_PI_2 * (i + theta) / len4;
+
+#if defined(TX_INT32)
+ int c_f, s_f;
+ SoftFloat cos_sf, sin_sf;
+ av_sincos_sf(llrintf(alpha * (1 << 30) / M_PI), &s_f, &c_f);
+ cos_sf = av_int2sf(c_f, 30);
+ sin_sf = av_int2sf(s_f, 30);
+ cos_sf = av_mul_sf(cos_sf, scale_sf);
+ sin_sf = av_mul_sf(sin_sf, scale_sf);
+ s->exp[off + i] = (TXComplex){ av_sf2int(cos_sf, 30) << 1, av_sf2int(sin_sf, 30) << 1 };
+#else
s->exp[off + i] = (TXComplex){ RESCALE(cos(alpha) * scale),
RESCALE(sin(alpha) * scale) };
+#endif
}
if (pre_tab)
@@ -89,7 +89,7 @@ fate-ac3-fixed-encode: tests/data/asynth-44100-2.wav
fate-ac3-fixed-encode: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
fate-ac3-fixed-encode: CMD = md5 -i $(SRC) -c ac3_fixed -ab 128k -f ac3 -flags +bitexact -af aresample
fate-ac3-fixed-encode: CMP = oneline
-fate-ac3-fixed-encode: REF = e9d78bca187b4bbafc4512bcea8efd3e
+fate-ac3-fixed-encode: REF = 3c1781a78ba3ea653c145798511644eb
FATE_EAC3-$(call ALLYES, EAC3_DEMUXER EAC3_MUXER EAC3_CORE_BSF) += fate-eac3-core-bsf
fate-eac3-core-bsf: CMD = md5pipe -i $(TARGET_SAMPLES)/eac3/the_great_wall_7.1.eac3 -c:a copy -bsf:a eac3_core -fflags +bitexact -f eac3
@@ -1 +1 @@
-ff7e25844b3cb6abb571ef7e226cbafa
+c40992cfc42a620b592e03153a74ff68
@@ -1,2 +1,2 @@
-a7b0ac6e5131bbf662a07ccc82ab8618 *tests/data/lavf/lavf.rm
+b471964c3f313ed33245ef3e56f144c0 *tests/data/lavf/lavf.rm
346424 tests/data/lavf/lavf.rm
--
2.40.1