commit f62ba59953e3b01d9940ea42d3aa1d7aecc8494f
parent 63fe6a3c1d5015d84eea470bcc77e1e74ab42f31
Author: Olav Sørensen <olav.sorensen@live.no>
Date: Sun, 12 Jan 2025 17:11:01 +0100
Code cleanup
Diffstat:
7 files changed, 118 insertions(+), 147 deletions(-)
diff --git a/src/ft2_audio.c b/src/ft2_audio.c
@@ -191,17 +191,17 @@ void audioSetInterpolationType(uint8_t interpolationType)
// set sinc LUT pointers
if (config.interpolation == INTERPOLATION_SINC8)
{
- fKaiserSinc = fKaiserSinc_8;
- fDownSample1 = fDownSample1_8;
- fDownSample2 = fDownSample2_8;
+ fSinc_1 = fSinc8_1;
+ fSinc_2 = fSinc8_2;
+ fSinc_3 = fSinc8_3;
audio.sincInterpolation = true;
}
else if (config.interpolation == INTERPOLATION_SINC16)
{
- fKaiserSinc = fKaiserSinc_16;
- fDownSample1 = fDownSample1_16;
- fDownSample2 = fDownSample2_16;
+ fSinc_1 = fSinc16_1;
+ fSinc_2 = fSinc16_2;
+ fSinc_3 = fSinc16_3;
audio.sincInterpolation = true;
}
@@ -394,12 +394,12 @@ void updateVoices(void)
if (audio.sincInterpolation)
{
// decide which sinc LUT to use according to the resampling ratio
- if (v->delta <= sincDownsample1Ratio)
- v->fSincLUT = fKaiserSinc;
- else if (v->delta <= sincDownsample2Ratio)
- v->fSincLUT = fDownSample1;
+ if (v->delta <= sincRatio1)
+ v->fSincLUT = fSinc_1;
+ else if (v->delta <= sincRatio2)
+ v->fSincLUT = fSinc_2;
else
- v->fSincLUT = fDownSample2;
+ v->fSincLUT = fSinc_3;
}
}
diff --git a/src/ft2_main.c b/src/ft2_main.c
@@ -147,7 +147,7 @@ int main(int argc, char *argv[])
#ifdef __APPLE__
osxSetDirToProgramDirFromArgs(argv);
#endif
- if (!setupExecutablePath() || !loadBMPs() || !calcCubicSplineTables() || !calcWindowedSincTables())
+ if (!setupExecutablePath() || !loadBMPs() || !setupCubicSplineTables() || !setupWindowedSincTables())
{
cleanUpAndExit();
return 1;
diff --git a/src/mixer/ft2_cubic_spline.c b/src/mixer/ft2_cubic_spline.c
@@ -10,7 +10,7 @@
float *f4PointCubicSplineLUT = NULL, *f6PointCubicSplineLUT = NULL; // globalized
-bool calcCubicSplineTables(void)
+bool setupCubicSplineTables(void)
{
float *fPtr;
diff --git a/src/mixer/ft2_cubic_spline.h b/src/mixer/ft2_cubic_spline.h
@@ -4,16 +4,19 @@
#include <stdbool.h>
#include "ft2_mix.h" // MIXER_FRAC_BITS
+#define CUBIC4P_SPLINE_WIDTH 4
+#define CUBIC4P_SPLINE_WIDTH_BITS 2 /* log2(CUBIC4P_SPLINE_WIDTH */
#define CUBIC4P_SPLINE_PHASES 8192
#define CUBIC4P_SPLINE_PHASES_BITS 13 // log2(CUBIC4P_SPLINE_PHASES)
-#define CUBIC4P_SPLINE_FSHIFT (MIXER_FRAC_BITS-(CUBIC4P_SPLINE_PHASES_BITS+2))
-#define CUBIC4P_SPLINE_FMASK ((4*CUBIC4P_SPLINE_PHASES)-4)
+#define CUBIC4P_SPLINE_FRACSHIFT (MIXER_FRAC_BITS-(CUBIC4P_SPLINE_PHASES_BITS+CUBIC4P_SPLINE_WIDTH_BITS))
+#define CUBIC4P_SPLINE_FRACMASK ((CUBIC4P_SPLINE_WIDTH*CUBIC4P_SPLINE_PHASES)-CUBIC4P_SPLINE_WIDTH)
+#define CUBIC6P_SPLINE_WIDTH 6
#define CUBIC6P_SPLINE_PHASES 8192
#define CUBIC6P_SPLINE_PHASES_BITS 13 // log2(CUBIC6P_SPLINE_PHASES)
-#define CUBIC6P_SPLINE_FSHIFT (MIXER_FRAC_BITS-CUBIC6P_SPLINE_PHASES_BITS)
+#define CUBIC6P_SPLINE_FRACSHIFT (MIXER_FRAC_BITS-CUBIC6P_SPLINE_PHASES_BITS)
extern float *f4PointCubicSplineLUT, *f6PointCubicSplineLUT;
-bool calcCubicSplineTables(void);
+bool setupCubicSplineTables(void);
void freeCubicSplineTables(void);
diff --git a/src/mixer/ft2_mix_macros.h b/src/mixer/ft2_mix_macros.h
@@ -133,7 +133,7 @@
#define CUBIC4P_SPLINE_INTERPOLATION(s, f, scale) \
{ \
- const float *t = f4PointCubicSplineLUT + (((uint32_t)(f) >> CUBIC4P_SPLINE_FSHIFT) & CUBIC4P_SPLINE_FMASK); \
+ const float *t = f4PointCubicSplineLUT + (((uint32_t)(f) >> CUBIC4P_SPLINE_FRACSHIFT) & CUBIC4P_SPLINE_FRACMASK); \
fSample = ((s[-1] * t[0]) + \
( s[0] * t[1]) + \
( s[1] * t[2]) + \
@@ -142,7 +142,7 @@
#define CUBIC6P_SPLINE_INTERPOLATION(s, f, scale) \
{ \
- const float *t = f6PointCubicSplineLUT + (((uint32_t)(f) >> CUBIC6P_SPLINE_FSHIFT) * 6); \
+ const float *t = f6PointCubicSplineLUT + (((uint32_t)(f) >> CUBIC6P_SPLINE_FRACSHIFT) * CUBIC6P_SPLINE_WIDTH); \
fSample = ((s[-2] * t[0]) + \
(s[-1] * t[1]) + \
( s[0] * t[2]) + \
@@ -215,7 +215,7 @@
#define WINDOWED_SINC8_INTERPOLATION(s, f, scale) \
{ \
- const float *t = v->fSincLUT + (((uint32_t)(f) >> SINC8_FSHIFT) & SINC8_FMASK); \
+ const float *t = v->fSincLUT + (((uint32_t)(f) >> SINC1_FRACSHIFT) & SINC1_FRACMASK); \
fSample = ((s[-3] * t[0]) + \
(s[-2] * t[1]) + \
(s[-1] * t[2]) + \
@@ -228,7 +228,7 @@
#define WINDOWED_SINC16_INTERPOLATION(s, f, scale) \
{ \
- const float *t = v->fSincLUT + (((uint32_t)(f) >> SINC16_FSHIFT) & SINC16_FMASK); \
+ const float *t = v->fSincLUT + (((uint32_t)(f) >> SINC2_FRACSHIFT) & SINC2_FRACMASK); \
fSample = (( s[-7] * t[0]) + \
( s[-6] * t[1]) + \
( s[-5] * t[2]) + \
diff --git a/src/mixer/ft2_windowed_sinc.c b/src/mixer/ft2_windowed_sinc.c
@@ -1,30 +1,25 @@
/*
-** Windowed-sinc (Kaiser window) w/ low-pass interpolation LUT generator
-**
-** This was originally based on OpenMPT's source code,
-** but it has been heavily modified.
+** Windowed-sinc LUT generator
*/
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <math.h>
-#include "ft2_windowed_sinc.h" // SINCx_TAPS, SINCx_PHASES
+#include "ft2_windowed_sinc.h" // SINCx_WIDTH, SINCx_PHASES
#include "../ft2_header.h" // PI
#include "../ft2_video.h" // showErrorMsgBox()
// globalized
-float *fKaiserSinc_8 = NULL, *fDownSample1_8 = NULL, *fDownSample2_8 = NULL;
-float *fKaiserSinc_16 = NULL, *fDownSample1_16 = NULL, *fDownSample2_16 = NULL;
-uint64_t sincDownsample1Ratio, sincDownsample2Ratio;
-
-// set based on selected sinc interpolator (8 point or 16 point)
-float *fKaiserSinc = NULL, *fDownSample1 = NULL, *fDownSample2 = NULL;
+float *fSinc8_1 = NULL, *fSinc8_2 = NULL, *fSinc8_3 = NULL;
+float *fSinc16_1 = NULL, *fSinc16_2 = NULL, *fSinc16_3 = NULL;
+float *fSinc_1 = NULL, *fSinc_2 = NULL, *fSinc_3 = NULL;
+uint64_t sincRatio1, sincRatio2;
// zeroth-order modified Bessel function of the first kind (series approximation)
-static double besselI0(double z)
+static inline double besselI0(double z)
{
-#define EPSILON (1E-15)
+#define EPSILON (1E-15) /* lower than this gives no accuracy benefits (verified), just slower compute time */
double s = 1.0, ds = 1.0, d = 2.0;
const double zz = z * z;
@@ -40,148 +35,122 @@ static double besselI0(double z)
return s;
}
-static void generateSincLUT(float *fOutput, uint32_t filterWidth, uint32_t numPhases, const double beta, const double lpCutoff)
+static inline double sinc(double x, const double cutoff)
{
- const double I0Beta = besselI0(beta);
- const double kPi = PI * lpCutoff;
- const double iMul = 1.0 / numPhases;
- const double xMul = 1.0 / ((filterWidth / 2) * (filterWidth / 2));
-
- const uint32_t length = filterWidth * numPhases;
- const uint32_t tapBits = (uint32_t)log2(filterWidth);
- const uint32_t phasesBits = (uint32_t)log2(numPhases);
- const uint32_t tapsMinus1 = filterWidth - 1;
- const int32_t midPoint = (filterWidth / 2) * numPhases;
-
- for (uint32_t i = 0; i < length; i++)
+ if (x == 0.0)
{
- const int32_t ix = ((tapsMinus1 - (i & tapsMinus1)) << phasesBits) + (i >> tapBits);
-
- double dSinc = 1.0;
- if (ix != midPoint)
- {
- const double x = (ix - midPoint) * iMul;
- const double xPi = x * kPi;
-
- // Kaiser window
- dSinc = (sin(xPi) * besselI0(beta * sqrt(1.0 - (x * x * xMul)))) / (I0Beta * xPi);
- }
-
- fOutput[i] = (float)(dSinc * lpCutoff);
+ return cutoff;
}
-}
-
-static double decibelsToKaiserBeta(double dB)
-{
- if (dB < 21.0)
- return 0.0;
- else if (dB <= 50.0)
- return 0.5842 * pow(dB - 21.0, 0.4) + 0.07886 * (dB - 21.0);
else
- return 0.1102 * (dB - 8.7);
+ {
+ x *= cutoff * PI;
+ return (sin(x) / x) * cutoff;
+ }
}
-static double rippleToDecibels(double ripple)
+static void generateWindowedSinc(float *fOutput, const int32_t filterWidth, const int32_t filterPhases, const double beta, const double cutoff)
{
- return 20.0 * log10(ripple);
+ const int32_t tapBits = (int32_t)log2(filterWidth);
+ const int32_t tapMask = filterWidth - 1;
+ const int32_t tapCenter = (filterWidth / 2) - 1;
+ const double besselI0Beta = 1.0 / besselI0(beta);
+ const double phaseMul = 1.0 / filterPhases;
+ const double xMul = 1.0 / (filterWidth / 2);
+
+ for (int32_t i = 0; i < filterWidth * filterPhases; i++)
+ {
+ const double x = ((i & tapMask) - tapCenter) - ((i >> tapBits) * phaseMul);
+
+ // Kaiser-Bessel window
+ const double n = x * xMul;
+ const double window = besselI0(beta * sqrt(1.0 - n * n)) * besselI0Beta;
+
+ fOutput[i] = (float)(sinc(x, cutoff) * window);
+ }
}
-bool calcWindowedSincTables(void)
+bool setupWindowedSincTables(void)
{
- fKaiserSinc_8 = (float *)malloc(SINC1_TAPS*SINC1_PHASES * sizeof (float));
- fDownSample1_8 = (float *)malloc(SINC1_TAPS*SINC1_PHASES * sizeof (float));
- fDownSample2_8 = (float *)malloc(SINC1_TAPS*SINC1_PHASES * sizeof (float));
- fKaiserSinc_16 = (float *)malloc(SINC2_TAPS*SINC2_PHASES * sizeof (float));
- fDownSample1_16 = (float *)malloc(SINC2_TAPS*SINC2_PHASES * sizeof (float));
- fDownSample2_16 = (float *)malloc(SINC2_TAPS*SINC2_PHASES * sizeof (float));
-
- if (fKaiserSinc_8 == NULL || fDownSample1_8 == NULL || fDownSample2_8 == NULL ||
- fKaiserSinc_16 == NULL || fDownSample1_16 == NULL || fDownSample2_16 == NULL)
+ fSinc8_1 = (float *)malloc(SINC1_WIDTH*SINC1_PHASES * sizeof (float));
+ fSinc8_2 = (float *)malloc(SINC1_WIDTH*SINC1_PHASES * sizeof (float));
+ fSinc8_3 = (float *)malloc(SINC1_WIDTH*SINC1_PHASES * sizeof (float));
+ fSinc16_1 = (float *)malloc(SINC2_WIDTH*SINC2_PHASES * sizeof (float));
+ fSinc16_2 = (float *)malloc(SINC2_WIDTH*SINC2_PHASES * sizeof (float));
+ fSinc16_3 = (float *)malloc(SINC2_WIDTH*SINC2_PHASES * sizeof (float));
+
+ if (fSinc8_1 == NULL || fSinc8_2 == NULL || fSinc8_3 == NULL ||
+ fSinc16_1 == NULL || fSinc16_2 == NULL || fSinc16_3 == NULL)
{
showErrorMsgBox("Not enough memory!");
return false;
}
- // resampling ratios for picking suitable downsample LUT
- const double ratio1 = 1.1875; // fKaiserSinc if <=
- const double ratio2 = 1.5; // fDownSample1 if <=, fDownSample2 if >
-
- sincDownsample1Ratio = (uint64_t)(ratio1 * MIXER_FRAC_SCALE);
- sincDownsample2Ratio = (uint64_t)(ratio2 * MIXER_FRAC_SCALE);
-
- /* Max ripple (to be converted into Kaiser beta parameter)
- **
- ** NOTE:
- ** These may not be the correct values. Proper calculation
- ** is needed, but is beyond my knowledge.
- */
- const double maxRipple1 = 1 << 16;
- const double maxRipple2 = 1 << 14;
- const double maxRipple3 = 1 << 12;
-
- // convert max ripple into sidelode attenuation (dB)
- double db1 = rippleToDecibels(maxRipple1);
- double db2 = rippleToDecibels(maxRipple2);
- double db3 = rippleToDecibels(maxRipple3);
-
- // convert sidelobe attenuation (dB) into Kaiser beta
- const double b1 = decibelsToKaiserBeta(db1);
- const double b2 = decibelsToKaiserBeta(db2);
- const double b3 = decibelsToKaiserBeta(db3);
-
- // low-pass cutoffs (could maybe use some further tweaking)
+ // LUT-select resampling ratios
+ const double ratio1 = 1.1875; // fSinc_1 if <=
+ const double ratio2 = 1.5; // fSinc_2 if <=, fSinc_3 if >
+
+ // calculate mixer delta limits for LUT-selector
+ sincRatio1 = (uint64_t)(ratio1 * MIXER_FRAC_SCALE);
+ sincRatio2 = (uint64_t)(ratio2 * MIXER_FRAC_SCALE);
+
+ // Kaiser-Bessel (window) beta (could maybe use some further tweaking)
+ const double b1 = 9.6;
+ const double b2 = 8.5;
+ const double b3 = 7.0;
+
+ // sinc low-pass cutoff (could maybe use some further tweaking)
const double c1 = 1.000;
const double c2 = 0.500;
const double c3 = 0.425;
// 8 point
- generateSincLUT(fKaiserSinc_8, SINC1_TAPS, SINC1_PHASES, b1, c1);
- generateSincLUT(fDownSample1_8, SINC1_TAPS, SINC1_PHASES, b2, c2);
- generateSincLUT(fDownSample2_8, SINC1_TAPS, SINC1_PHASES, b3, c3);
+ generateWindowedSinc(fSinc8_1, SINC1_WIDTH, SINC1_PHASES, b1, c1);
+ generateWindowedSinc(fSinc8_2, SINC1_WIDTH, SINC1_PHASES, b2, c2);
+ generateWindowedSinc(fSinc8_3, SINC1_WIDTH, SINC1_PHASES, b3, c3);
// 16 point
- generateSincLUT(fKaiserSinc_16, SINC2_TAPS, SINC2_PHASES, b1, c1);
- generateSincLUT(fDownSample1_16, SINC2_TAPS, SINC2_PHASES, b2, c2);
- generateSincLUT(fDownSample2_16, SINC2_TAPS, SINC2_PHASES, b3, c3);
+ generateWindowedSinc(fSinc16_1, SINC2_WIDTH, SINC2_PHASES, b1, c1);
+ generateWindowedSinc(fSinc16_2, SINC2_WIDTH, SINC2_PHASES, b2, c2);
+ generateWindowedSinc(fSinc16_3, SINC2_WIDTH, SINC2_PHASES, b3, c3);
return true;
}
void freeWindowedSincTables(void)
{
- if (fKaiserSinc_8 != NULL)
+ if (fSinc8_1 != NULL)
{
- free(fKaiserSinc_8);
- fKaiserSinc_8 = NULL;
+ free(fSinc8_1);
+ fSinc8_1 = NULL;
}
- if (fDownSample1_8 != NULL)
+ if (fSinc8_2 != NULL)
{
- free(fDownSample1_8);
- fDownSample1_8 = NULL;
+ free(fSinc8_2);
+ fSinc8_2 = NULL;
}
- if (fDownSample2_8 != NULL)
+ if (fSinc8_3 != NULL)
{
- free(fDownSample2_8);
- fDownSample2_8 = NULL;
+ free(fSinc8_3);
+ fSinc8_3 = NULL;
}
- if (fKaiserSinc_16 != NULL)
+ if (fSinc16_1 != NULL)
{
- free(fKaiserSinc_16);
- fKaiserSinc_16 = NULL;
+ free(fSinc16_1);
+ fSinc16_1 = NULL;
}
- if (fDownSample1_16 != NULL)
+ if (fSinc16_2 != NULL)
{
- free(fDownSample1_16);
- fDownSample1_16 = NULL;
+ free(fSinc16_2);
+ fSinc16_2 = NULL;
}
- if (fDownSample2_16 != NULL)
+ if (fSinc16_3 != NULL)
{
- free(fDownSample2_16);
- fDownSample2_16 = NULL;
+ free(fSinc16_3);
+ fSinc16_3 = NULL;
}
}
diff --git a/src/mixer/ft2_windowed_sinc.h b/src/mixer/ft2_windowed_sinc.h
@@ -4,25 +4,24 @@
#include <stdbool.h>
#include "ft2_mix.h" // MIXER_FRAC_BITS
-#define SINC1_TAPS 8
-#define SINC8_WIDTH_BITS 3 // log2(SINC1_TAPS)
+#define SINC1_WIDTH 8
+#define SINC1_WIDTH_BITS 3 // log2(SINC1_WIDTH)
#define SINC1_PHASES 8192
#define SINC1_PHASES_BITS 13 // log2(SINC1_PHASES)
-#define SINC8_FSHIFT (MIXER_FRAC_BITS-(SINC1_PHASES_BITS+SINC8_WIDTH_BITS))
-#define SINC8_FMASK ((SINC1_TAPS*SINC1_PHASES)-SINC1_TAPS)
+#define SINC1_FRACSHIFT (MIXER_FRAC_BITS-(SINC1_PHASES_BITS+SINC1_WIDTH_BITS))
+#define SINC1_FRACMASK ((SINC1_WIDTH*SINC1_PHASES)-SINC1_WIDTH)
-#define SINC2_TAPS 16
-#define SINC16_WIDTH_BITS 4 // log2(SINC2_TAPS)
+#define SINC2_WIDTH 16
+#define SINC2_WIDTH_BITS 4 // log2(SINC2_WIDTH)
#define SINC2_PHASES 8192
#define SINC2_PHASES_BITS 13 // log2(SINC2_PHASES)
-#define SINC16_FSHIFT (MIXER_FRAC_BITS-(SINC2_PHASES_BITS+SINC16_WIDTH_BITS))
-#define SINC16_FMASK ((SINC2_TAPS*SINC2_PHASES)-SINC2_TAPS)
+#define SINC2_FRACSHIFT (MIXER_FRAC_BITS-(SINC2_PHASES_BITS+SINC2_WIDTH_BITS))
+#define SINC2_FRACMASK ((SINC2_WIDTH*SINC2_PHASES)-SINC2_WIDTH)
-extern float *fKaiserSinc_8, *fDownSample1_8, *fDownSample2_8;
-extern float *fKaiserSinc_16, *fDownSample1_16, *fDownSample2_16;
+extern float *fSinc8_1, *fSinc8_2, *fSinc8_3;
+extern float *fSinc16_1, *fSinc16_2, *fSinc16_3;
+extern float *fSinc_1, *fSinc_2, *fSinc_3;
+extern uint64_t sincRatio1, sincRatio2;
-extern float *fKaiserSinc, *fDownSample1, *fDownSample2;
-extern uint64_t sincDownsample1Ratio, sincDownsample2Ratio;
-
-bool calcWindowedSincTables(void);
+bool setupWindowedSincTables(void);
void freeWindowedSincTables(void);