ref: 65ae4b974e929be2bf6340739a17e9c9dcf70d67
parent: fb2d7b8e8a87528b180a3cd55f8011336573ba7b
author: Olav Sørensen <olav.sorensen@live.no>
date: Fri Feb 23 12:28:14 EST 2024
Sinc 16-point -> sinc 32-point
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@
If these don't work for you, you'll have to compile the code manually.
# Improvements over original DOS version
-- The channel resampler/mixer uses floating-point arithmetics for less errors, and has extra interpolation options (4-point cubic spline, 8-point/16-point windowed-sinc)
+- The channel resampler/mixer uses floating-point arithmetics for less errors, and has extra interpolation options (4-point cubic spline, 8-point/32-point windowed-sinc)
- The sample loader supports FLAC/AIFF samples and more WAV types than original FT2. It will also attempt to tune the sample (finetune and rel. note) to its playback frequency on load.
- It contains a new "Trim" feature, which will remove unused stuff to potentially make the module smaller
- Drag n' drop of modules/samples
--- a/src/ft2_audio.c
+++ b/src/ft2_audio.c
@@ -195,6 +195,8 @@
lockMixerCallback();
audio.interpolationType = interpolationType;
+ audio.sincInterpolation = false;
+
// set sinc LUT pointers
if (config.interpolation == INTERPOLATION_SINC8)
{
@@ -201,12 +203,23 @@
fKaiserSinc = fKaiserSinc_8;
fDownSample1 = fDownSample1_8;
fDownSample2 = fDownSample2_8;
+
+ // modelled after OpenMPT
+ audio.sincRatio1 = (uintCPUWord_t)(1.1875 * MIXER_FRAC_SCALE);
+ audio.sincRatio2 = (uintCPUWord_t)(1.5 * MIXER_FRAC_SCALE);
+
+ audio.sincInterpolation = true;
}
- else if (config.interpolation == INTERPOLATION_SINC16)
+ else if (config.interpolation == INTERPOLATION_SINC32)
{
- fKaiserSinc = fKaiserSinc_16;
- fDownSample1 = fDownSample1_16;
- fDownSample2 = fDownSample2_16;
+ fKaiserSinc = fKaiserSinc_32;
+ fDownSample1 = fDownSample1_32;
+ fDownSample2 = fDownSample2_32;
+
+ audio.sincRatio1 = (uintCPUWord_t)(2.375 * MIXER_FRAC_SCALE);
+ audio.sincRatio2 = (uintCPUWord_t)(3.0 * MIXER_FRAC_SCALE);
+
+ audio.sincInterpolation = true;
}
unlockMixerCallback();
@@ -389,12 +402,13 @@
// set voice delta
const uintCPUWord_t delta = v->oldDelta = (intCPUWord_t)((dHz * audio.dHz2MixDeltaMul) + 0.5); // Hz -> fixed-point delta (rounded)
- if (audio.interpolationType == INTERPOLATION_SINC8 || audio.interpolationType == INTERPOLATION_SINC16)
+ //const double dRatio = delta / (double)MIXER_FRAC_SCALE;
+
+ if (audio.sincInterpolation) // decide which sinc LUT to use according to the resampling ratio
{
- // decide which sinc LUT to use according to the resampling ratio
- if (delta <= (uintCPUWord_t)(1.1875 * MIXER_FRAC_SCALE))
+ if (delta <= audio.sincRatio1)
v->fSincLUT = fKaiserSinc;
- else if (delta <= (uintCPUWord_t)(1.5 * MIXER_FRAC_SCALE))
+ else if (delta <= audio.sincRatio2)
v->fSincLUT = fDownSample1;
else
v->fSincLUT = fDownSample2;
--- a/src/ft2_audio.h
+++ b/src/ft2_audio.h
@@ -42,7 +42,7 @@
char *currInputDevice, *currOutputDevice, *lastWorkingAudioDeviceName;
char *inputDeviceNames[MAX_AUDIO_DEVICES], *outputDeviceNames[MAX_AUDIO_DEVICES];
volatile bool locked, resetSyncTickTimeFlag, volumeRampingFlag;
- bool linearPeriodsFlag, rescanAudioDevicesSupported;
+ bool linearPeriodsFlag, rescanAudioDevicesSupported, sincInterpolation;
volatile uint8_t interpolationType;
int32_t inputDeviceNum, outputDeviceNum, lastWorkingAudioFreq, lastWorkingAudioBits;
uint32_t quickVolRampSamples, freq;
@@ -52,6 +52,7 @@
uint32_t audLatencyPerfValInt, tickTimeIntTab[(MAX_BPM-MIN_BPM)+1];
uint64_t audLatencyPerfValFrac, tickTimeFracTab[(MAX_BPM-MIN_BPM)+1];
+ uintCPUWord_t sincRatio1, sincRatio2;
uint64_t tickTime64, tickTime64Frac;
--- a/src/ft2_config.c
+++ b/src/ft2_config.c
@@ -833,8 +833,8 @@
tmpID = RB_CONFIG_AUDIO_INTRP_DISABLED;
else if (config.interpolation == INTERPOLATION_LINEAR)
tmpID = RB_CONFIG_AUDIO_INTRP_LINEAR;
- else if (config.interpolation == INTERPOLATION_SINC16)
- tmpID = RB_CONFIG_AUDIO_INTRP_SINC16;
+ else if (config.interpolation == INTERPOLATION_SINC32)
+ tmpID = RB_CONFIG_AUDIO_INTRP_SINC32;
else if (config.interpolation == INTERPOLATION_CUBIC)
tmpID = RB_CONFIG_AUDIO_INTRP_CUBIC;
else
@@ -1175,7 +1175,7 @@
textOutShadow(406, 119, PAL_FORGRND, PAL_DSKTOP2, "Linear (FT2)");
textOutShadow(406, 133, PAL_FORGRND, PAL_DSKTOP2, "Cubic spline");
textOutShadow(406, 147, PAL_FORGRND, PAL_DSKTOP2, "Sinc (8 point)");
- textOutShadow(406, 161, PAL_FORGRND, PAL_DSKTOP2, "Sinc (16 point)");
+ textOutShadow(406, 161, PAL_FORGRND, PAL_DSKTOP2, "Sinc (32 point)");
textOutShadow(509, 3, PAL_FORGRND, PAL_DSKTOP2, "Audio output rate:");
textOutShadow(525, 17, PAL_FORGRND, PAL_DSKTOP2, "44100Hz");
@@ -1642,11 +1642,11 @@
checkRadioButton(RB_CONFIG_AUDIO_INTRP_SINC8);
}
-void rbConfigAudioIntrp16PointSinc(void)
+void rbConfigAudioIntrp32PointSinc(void)
{
- config.interpolation = INTERPOLATION_SINC16;
+ config.interpolation = INTERPOLATION_SINC32;
audioSetInterpolationType(config.interpolation);
- checkRadioButton(RB_CONFIG_AUDIO_INTRP_SINC16);
+ checkRadioButton(RB_CONFIG_AUDIO_INTRP_SINC32);
}
void rbConfigAudio44kHz(void)
--- a/src/ft2_config.h
+++ b/src/ft2_config.h
@@ -23,7 +23,7 @@
INTERPOLATION_DISABLED = 0,
INTERPOLATION_SINC8 = 1,
INTERPOLATION_LINEAR = 2,
- INTERPOLATION_SINC16 = 3,
+ INTERPOLATION_SINC32 = 3,
INTERPOLATION_CUBIC = 4,
// ------
@@ -222,7 +222,7 @@
void rbConfigAudioIntrpLinear(void);
void rbConfigAudioIntrpCubic(void);
void rbConfigAudioIntrp8PointSinc(void);
-void rbConfigAudioIntrp16PointSinc(void);
+void rbConfigAudioIntrp32PointSinc(void);
void rbConfigAudio44kHz(void);
void rbConfigAudio48kHz(void);
#if CPU_64BIT
--- a/src/ft2_radiobuttons.c
+++ b/src/ft2_radiobuttons.c
@@ -90,7 +90,7 @@
{ 390, 118, 91, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpLinear },
{ 390, 132, 86, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrpCubic },
{ 390, 146, 95, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrp8PointSinc },
- { 390, 160, 102, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrp16PointSinc },
+ { 390, 160, 102, RB_GROUP_CONFIG_AUDIO_INTERPOLATION, rbConfigAudioIntrp32PointSinc },
// audio output frequency
//x, y, w, group, funcOnUp
--- a/src/ft2_radiobuttons.h
+++ b/src/ft2_radiobuttons.h
@@ -60,7 +60,7 @@
RB_CONFIG_AUDIO_INTRP_LINEAR,
RB_CONFIG_AUDIO_INTRP_CUBIC,
RB_CONFIG_AUDIO_INTRP_SINC8,
- RB_CONFIG_AUDIO_INTRP_SINC16,
+ RB_CONFIG_AUDIO_INTRP_SINC32,
// AUDIO FREQUENCY
RB_CONFIG_AUDIO_44KHZ,
--- a/src/ft2_replayer.h
+++ b/src/ft2_replayer.h
@@ -218,9 +218,9 @@
int32_t length, loopStart, loopLength;
// fix for resampling interpolation taps
- int8_t leftEdgeTapSamples8[32];
- int16_t leftEdgeTapSamples16[32];
- int16_t fixedSmp[32];
+ int8_t leftEdgeTapSamples8[MAX_TAPS*2];
+ int16_t leftEdgeTapSamples16[MAX_TAPS*2];
+ int16_t fixedSmp[MAX_TAPS*2];
int32_t fixedPos;
} sample_t;
--- a/src/mixer/ft2_mix.c
+++ b/src/mixer/ft2_mix.c
@@ -9,7 +9,7 @@
** (Note: Mixing macros can be found in ft2_mix_macros.h)
**
** Specifications:
-** - Interpolation: None, 2-tap linear, 4-tap cubic spline, 8-tap windowed-sinc, 16-tap windowed-sinc
+** - Interpolation: None, 2-tap linear, 4-tap cubic spline, 8-tap windowed-sinc, 32-tap windowed-sinc
** - FT2-styled linear volume ramping (can be turned off)
** - 32.32 (16.16 if 32-bit CPU) fixed-point precision for resampling delta/position
** - 32-bit floating-point precision for mixing and interpolation
@@ -464,7 +464,7 @@
SET_BACK_MIXER_POS
}
-static void mix8bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bNoLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int8_t *base, *smpPtr;
float fSample, *fMixBufferL, *fMixBufferR;
@@ -484,19 +484,19 @@
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS
}
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS
}
@@ -506,7 +506,7 @@
SET_BACK_MIXER_POS
}
-static void mix8bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int8_t *base, *smpPtr;
int8_t *smpTapPtr;
@@ -530,19 +530,19 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
INC_POS
}
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
INC_POS
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
INC_POS
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
INC_POS
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
INC_POS
}
}
@@ -550,19 +550,19 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS
}
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS
}
}
@@ -573,7 +573,7 @@
SET_BACK_MIXER_POS
}
-static void mix8bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bBidiLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int8_t *base, *revBase, *smpPtr;
int8_t *smpTapPtr;
@@ -598,19 +598,19 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
INC_POS_BIDI
}
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
INC_POS_BIDI
}
}
@@ -618,19 +618,19 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS_BIDI
}
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
INC_POS_BIDI
}
}
@@ -1336,7 +1336,7 @@
SET_BACK_MIXER_POS
}
-static void mix8bRampNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bRampNoLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int8_t *base, *smpPtr;
float fSample, *fMixBufferL, *fMixBufferR;
@@ -1358,7 +1358,7 @@
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
}
@@ -1365,16 +1365,16 @@
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
}
@@ -1386,7 +1386,7 @@
SET_BACK_MIXER_POS
}
-static void mix8bRampLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bRampLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int8_t *base, *smpPtr;
int8_t *smpTapPtr;
@@ -1412,7 +1412,7 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS
}
@@ -1419,16 +1419,16 @@
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS
}
@@ -1437,7 +1437,7 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
}
@@ -1444,16 +1444,16 @@
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
}
@@ -1466,7 +1466,7 @@
SET_BACK_MIXER_POS
}
-static void mix8bRampBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix8bRampBidiLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int8_t *base, *revBase, *smpPtr;
int8_t *smpTapPtr;
@@ -1493,7 +1493,7 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS_BIDI
}
@@ -1500,16 +1500,16 @@
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_8BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS_BIDI
}
@@ -1518,7 +1518,7 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS_BIDI
}
@@ -1525,16 +1525,16 @@
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_8BIT_SMP_S16INTRP
+ RENDER_8BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS_BIDI
}
@@ -2198,7 +2198,7 @@
SET_BACK_MIXER_POS
}
-static void mix16bNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bNoLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int16_t *base, *smpPtr;
float fSample, *fMixBufferL, *fMixBufferR;
@@ -2218,19 +2218,19 @@
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS
}
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS
}
@@ -2240,7 +2240,7 @@
SET_BACK_MIXER_POS
}
-static void mix16bLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int16_t *base, *smpPtr;
int16_t *smpTapPtr;
@@ -2264,19 +2264,19 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
INC_POS
}
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
INC_POS
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
INC_POS
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
INC_POS
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
INC_POS
}
}
@@ -2284,19 +2284,19 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS
}
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS
}
}
@@ -2307,7 +2307,7 @@
SET_BACK_MIXER_POS
}
-static void mix16bBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bBidiLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int16_t *base, *revBase, *smpPtr;
int16_t *smpTapPtr;
@@ -2332,19 +2332,19 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
INC_POS_BIDI
}
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
INC_POS_BIDI
}
}
@@ -2352,19 +2352,19 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS_BIDI
}
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
INC_POS_BIDI
}
}
@@ -3070,7 +3070,7 @@
SET_BACK_MIXER_POS
}
-static void mix16bRampNoLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bRampNoLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int16_t *base, *smpPtr;
float fSample, *fMixBufferL, *fMixBufferR;
@@ -3092,7 +3092,7 @@
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
}
@@ -3099,16 +3099,16 @@
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
}
@@ -3120,7 +3120,7 @@
SET_BACK_MIXER_POS
}
-static void mix16bRampLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bRampLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int16_t *base, *smpPtr;
int16_t *smpTapPtr;
@@ -3146,7 +3146,7 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS
}
@@ -3153,16 +3153,16 @@
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS
}
@@ -3171,7 +3171,7 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
}
@@ -3178,16 +3178,16 @@
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS
}
@@ -3200,7 +3200,7 @@
SET_BACK_MIXER_POS
}
-static void mix16bRampBidiLoopS16Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
+static void mix16bRampBidiLoopS32Intrp(voice_t *v, uint32_t bufferPos, uint32_t numSamples)
{
const int16_t *base, *revBase, *smpPtr;
int16_t *smpTapPtr;
@@ -3227,7 +3227,7 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS_BIDI
}
@@ -3234,16 +3234,16 @@
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP_TAP_FIX
+ RENDER_16BIT_SMP_S32INTRP_TAP_FIX
VOLUME_RAMPING
INC_POS_BIDI
}
@@ -3252,7 +3252,7 @@
{
for (i = 0; i < (samplesToMix & 3); i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS_BIDI
}
@@ -3259,16 +3259,16 @@
samplesToMix >>= 2;
for (i = 0; i < samplesToMix; i++)
{
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS_BIDI
- RENDER_16BIT_SMP_S16INTRP
+ RENDER_16BIT_SMP_S32INTRP
VOLUME_RAMPING
INC_POS_BIDI
}
@@ -3510,9 +3510,9 @@
(mixFunc)mix8bNoLoopLIntrp,
(mixFunc)mix8bLoopLIntrp,
(mixFunc)mix8bBidiLoopLIntrp,
- (mixFunc)mix8bNoLoopS16Intrp,
- (mixFunc)mix8bLoopS16Intrp,
- (mixFunc)mix8bBidiLoopS16Intrp,
+ (mixFunc)mix8bNoLoopS32Intrp,
+ (mixFunc)mix8bLoopS32Intrp,
+ (mixFunc)mix8bBidiLoopS32Intrp,
(mixFunc)mix8bNoLoopCIntrp,
(mixFunc)mix8bLoopCIntrp,
(mixFunc)mix8bBidiLoopCIntrp,
@@ -3527,9 +3527,9 @@
(mixFunc)mix16bNoLoopLIntrp,
(mixFunc)mix16bLoopLIntrp,
(mixFunc)mix16bBidiLoopLIntrp,
- (mixFunc)mix16bNoLoopS16Intrp,
- (mixFunc)mix16bLoopS16Intrp,
- (mixFunc)mix16bBidiLoopS16Intrp,
+ (mixFunc)mix16bNoLoopS32Intrp,
+ (mixFunc)mix16bLoopS32Intrp,
+ (mixFunc)mix16bBidiLoopS32Intrp,
(mixFunc)mix16bNoLoopCIntrp,
(mixFunc)mix16bLoopCIntrp,
(mixFunc)mix16bBidiLoopCIntrp,
@@ -3546,9 +3546,9 @@
(mixFunc)mix8bRampNoLoopLIntrp,
(mixFunc)mix8bRampLoopLIntrp,
(mixFunc)mix8bRampBidiLoopLIntrp,
- (mixFunc)mix8bRampNoLoopS16Intrp,
- (mixFunc)mix8bRampLoopS16Intrp,
- (mixFunc)mix8bRampBidiLoopS16Intrp,
+ (mixFunc)mix8bRampNoLoopS32Intrp,
+ (mixFunc)mix8bRampLoopS32Intrp,
+ (mixFunc)mix8bRampBidiLoopS32Intrp,
(mixFunc)mix8bRampNoLoopCIntrp,
(mixFunc)mix8bRampLoopCIntrp,
(mixFunc)mix8bRampBidiLoopCIntrp,
@@ -3563,9 +3563,9 @@
(mixFunc)mix16bRampNoLoopLIntrp,
(mixFunc)mix16bRampLoopLIntrp,
(mixFunc)mix16bRampBidiLoopLIntrp,
- (mixFunc)mix16bRampNoLoopS16Intrp,
- (mixFunc)mix16bRampLoopS16Intrp,
- (mixFunc)mix16bRampBidiLoopS16Intrp,
+ (mixFunc)mix16bRampNoLoopS32Intrp,
+ (mixFunc)mix16bRampLoopS32Intrp,
+ (mixFunc)mix16bRampBidiLoopS32Intrp,
(mixFunc)mix16bRampNoLoopCIntrp,
(mixFunc)mix16bRampLoopCIntrp,
(mixFunc)mix16bRampBidiLoopCIntrp
--- a/src/mixer/ft2_mix.h
+++ b/src/mixer/ft2_mix.h
@@ -3,7 +3,7 @@
#include <stdint.h>
#include "../ft2_cpu.h"
-#define MAX_TAPS 16
+#define MAX_TAPS 32
#define MAX_LEFT_TAPS ((MAX_TAPS/2)-1)
#define MAX_RIGHT_TAPS (MAX_TAPS/2)
--- a/src/mixer/ft2_mix_macros.h
+++ b/src/mixer/ft2_mix_macros.h
@@ -218,47 +218,79 @@
}
#endif
-#if SINC16_FSHIFT>=0
-#define WINDOWED_SINC16_INTERPOLATION(s, f, scale) \
+#if SINC32_FSHIFT>=0
+#define WINDOWED_SINC32_INTERPOLATION(s, f, scale) \
{ \
- const float *t = v->fSincLUT + (((uint32_t)(f) >> SINC16_FSHIFT) & SINC16_FMASK); \
- fSample = ((s[-7] * t[0]) + \
- (s[-6] * t[1]) + \
- (s[-5] * t[2]) + \
- (s[-4] * t[3]) + \
- (s[-3] * t[4]) + \
- (s[-2] * t[5]) + \
- (s[-1] * t[6]) + \
- ( s[0] * t[7]) + \
- ( s[1] * t[8]) + \
- ( s[2] * t[9]) + \
- ( s[3] * t[10]) + \
- ( s[4] * t[11]) + \
- ( s[5] * t[12]) + \
- ( s[6] * t[13]) + \
- ( s[7] * t[14]) + \
- ( s[8] * t[15])) * (1.0f / scale); \
+ const float *t = v->fSincLUT + (((uint32_t)(f) >> SINC32_FSHIFT) & SINC32_FMASK); \
+ fSample = ((s[-15] * t[0]) + \
+ (s[-14] * t[1]) + \
+ (s[-13] * t[2]) + \
+ (s[-12] * t[3]) + \
+ (s[-11] * t[4]) + \
+ (s[-10] * t[5]) + \
+ ( s[-9] * t[6]) + \
+ ( s[-8] * t[7]) + \
+ ( s[-7] * t[8]) + \
+ ( s[-6] * t[9]) + \
+ ( s[-5] * t[10]) + \
+ ( s[-4] * t[11]) + \
+ ( s[-3] * t[12]) + \
+ ( s[-2] * t[13]) + \
+ ( s[-1] * t[14]) + \
+ ( s[0] * t[15]) + \
+ ( s[1] * t[16]) + \
+ ( s[2] * t[17]) + \
+ ( s[3] * t[18]) + \
+ ( s[4] * t[19]) + \
+ ( s[5] * t[20]) + \
+ ( s[6] * t[21]) + \
+ ( s[7] * t[22]) + \
+ ( s[8] * t[23]) + \
+ ( s[9] * t[24]) + \
+ ( s[10] * t[25]) + \
+ ( s[11] * t[26]) + \
+ ( s[12] * t[27]) + \
+ ( s[13] * t[28]) + \
+ ( s[14] * t[29]) + \
+ ( s[15] * t[30]) + \
+ ( s[16] * t[31])) * (1.0f / scale); \
}
#else
-#define WINDOWED_SINC16_INTERPOLATION(s, f, scale) \
+#define WINDOWED_SINC32_INTERPOLATION(s, f, scale) \
{ \
- const float *t = v->fSincLUT + (((uint32_t)(f) << -SINC16_FSHIFT) & SINC16_FMASK); \
- fSample = ((s[-7] * t[0]) + \
- (s[-6] * t[1]) + \
- (s[-5] * t[2]) + \
- (s[-4] * t[3]) + \
- (s[-3] * t[4]) + \
- (s[-2] * t[5]) + \
- (s[-1] * t[6]) + \
- ( s[0] * t[7]) + \
- ( s[1] * t[8]) + \
- ( s[2] * t[9]) + \
- ( s[3] * t[10]) + \
- ( s[4] * t[11]) + \
- ( s[5] * t[12]) + \
- ( s[6] * t[13]) + \
- ( s[7] * t[14]) + \
- ( s[8] * t[15])) * (1.0f / scale); \
+ const float *t = v->fSincLUT + (((uint32_t)(f) << -SINC32_FSHIFT) & SINC32_FMASK); \
+ fSample = ((s[-15] * t[0]) + \
+ (s[-14] * t[1]) + \
+ (s[-13] * t[2]) + \
+ (s[-12] * t[3]) + \
+ (s[-11] * t[4]) + \
+ (s[-10] * t[5]) + \
+ ( s[-9] * t[6]) + \
+ ( s[-8] * t[7]) + \
+ ( s[-7] * t[8]) + \
+ ( s[-6] * t[9]) + \
+ ( s[-5] * t[10]) + \
+ ( s[-4] * t[11]) + \
+ ( s[-3] * t[12]) + \
+ ( s[-2] * t[13]) + \
+ ( s[-1] * t[14]) + \
+ ( s[0] * t[15]) + \
+ ( s[1] * t[16]) + \
+ ( s[2] * t[17]) + \
+ ( s[3] * t[18]) + \
+ ( s[4] * t[19]) + \
+ ( s[5] * t[20]) + \
+ ( s[6] * t[21]) + \
+ ( s[7] * t[22]) + \
+ ( s[8] * t[23]) + \
+ ( s[9] * t[24]) + \
+ ( s[10] * t[25]) + \
+ ( s[11] * t[26]) + \
+ ( s[12] * t[27]) + \
+ ( s[13] * t[28]) + \
+ ( s[14] * t[29]) + \
+ ( s[15] * t[30]) + \
+ ( s[16] * t[31])) * (1.0f / scale); \
}
#endif
@@ -272,13 +304,13 @@
*fMixBufferL++ += fSample * fVolumeL; \
*fMixBufferR++ += fSample * fVolumeR;
-#define RENDER_8BIT_SMP_S16INTRP \
- WINDOWED_SINC16_INTERPOLATION(smpPtr, positionFrac, 128) \
+#define RENDER_8BIT_SMP_S32INTRP \
+ WINDOWED_SINC32_INTERPOLATION(smpPtr, positionFrac, 128) \
*fMixBufferL++ += fSample * fVolumeL; \
*fMixBufferR++ += fSample * fVolumeR;
-#define RENDER_16BIT_SMP_S16INTRP \
- WINDOWED_SINC16_INTERPOLATION(smpPtr, positionFrac, 32768) \
+#define RENDER_16BIT_SMP_S32INTRP \
+ WINDOWED_SINC32_INTERPOLATION(smpPtr, positionFrac, 32768) \
*fMixBufferL++ += fSample * fVolumeL; \
*fMixBufferR++ += fSample * fVolumeR;
@@ -298,15 +330,15 @@
*fMixBufferL++ += fSample * fVolumeL; \
*fMixBufferR++ += fSample * fVolumeR;
-#define RENDER_8BIT_SMP_S16INTRP_TAP_FIX \
+#define RENDER_8BIT_SMP_S32INTRP_TAP_FIX \
smpTapPtr = (smpPtr <= leftEdgePtr) ? (int8_t *)&v->leftEdgeTaps8[(int32_t)(smpPtr-loopStartPtr)] : (int8_t *)smpPtr; \
- WINDOWED_SINC16_INTERPOLATION(smpTapPtr, positionFrac, 128) \
+ WINDOWED_SINC32_INTERPOLATION(smpTapPtr, positionFrac, 128) \
*fMixBufferL++ += fSample * fVolumeL; \
*fMixBufferR++ += fSample * fVolumeR;
-#define RENDER_16BIT_SMP_S16INTRP_TAP_FIX \
+#define RENDER_16BIT_SMP_S32INTRP_TAP_FIX \
smpTapPtr = (smpPtr <= leftEdgePtr) ? (int16_t *)&v->leftEdgeTaps16[(int32_t)(smpPtr-loopStartPtr)] : (int16_t *)smpPtr; \
- WINDOWED_SINC16_INTERPOLATION(smpTapPtr, positionFrac, 32768) \
+ WINDOWED_SINC32_INTERPOLATION(smpTapPtr, positionFrac, 32768) \
*fMixBufferL++ += fSample * fVolumeL; \
*fMixBufferR++ += fSample * fVolumeR;
--- a/src/mixer/ft2_windowed_sinc.c
+++ b/src/mixer/ft2_windowed_sinc.c
@@ -1,7 +1,5 @@
-/* Code taken from the OpenMPT project, which has a BSD license which is
-** compatible with this project.
-**
-** The code has been slightly modified.
+/* The code in this file is based on code from the OpenMPT project,
+** which shares the same coding license as this project.
*/
#include <stdint.h>
@@ -15,24 +13,23 @@
// globalized
float *fKaiserSinc_8 = NULL, *fDownSample1_8 = NULL, *fDownSample2_8 = NULL;
-float *fKaiserSinc_16 = NULL, *fDownSample1_16 = NULL, *fDownSample2_16 = NULL;
+float *fKaiserSinc_32 = NULL, *fDownSample1_32 = NULL, *fDownSample2_32 = NULL;
-// set based on selected sinc interpolator (8 point or 16 point)
+// set based on selected sinc interpolator (8 point or 32 point)
float *fKaiserSinc = NULL, *fDownSample1 = NULL, *fDownSample2 = NULL;
-static double Izero(double y) // Compute Bessel function Izero(y) using a series approximation
+// zeroth-order modified Bessel function of the first kind (series approximation)
+static double besselI0(double z)
{
- double s = 1.0, ds = 1.0, d = 0.0;
+ double s = 1.0, ds = 1.0, d = 2.0;
- const double epsilon = 1E-9; // 8bitbubsy: 1E-7 -> 1E-9 for added precision (still fast to calculate)
-
do
{
- d = d + 2.0;
- ds = ds * (y * y) / (d * d);
- s = s + ds;
+ ds *= (z * z) / (d * d);
+ s += ds;
+ d += 2.0;
}
- while (ds > epsilon * s);
+ while (ds > s*1E-15);
return s;
}
@@ -39,7 +36,7 @@
static void getSinc(uint32_t numTaps, float *fLUTPtr, const double beta, const double cutoff)
{
- const double izeroBeta = Izero(beta);
+ const double I0Beta = besselI0(beta);
const double kPi = MY_PI * cutoff;
const uint32_t length = numTaps * SINC_PHASES;
@@ -50,18 +47,16 @@
for (uint32_t i = 0; i < length; i++)
{
- const int32_t ix = ((tapsMinus1 - (i & tapsMinus1)) * SINC_PHASES) + (i >> tapBits);
+ const int32_t ix = ((tapsMinus1 - (i & tapsMinus1)) << SINC_PHASES_BITS) + (i >> tapBits);
- double dSinc;
- if (ix == midTap)
+ double dSinc = 1.0;
+ if (ix != midTap)
{
- dSinc = 1.0;
- }
- else
- {
const double x = (ix - midTap) * (1.0 / SINC_PHASES);
const double xPi = x * kPi;
- dSinc = sin(xPi) * Izero(beta * sqrt(1.0 - x * x * xMul)) / (izeroBeta * xPi); // Kaiser window
+
+ // sinc with Kaiser window
+ dSinc = (sin(xPi) * besselI0(beta * sqrt(1.0 - (x * x * xMul)))) / (I0Beta * xPi);
}
fLUTPtr[i] = (float)(dSinc * cutoff);
@@ -68,30 +63,42 @@
}
}
+static double dBToKaiserBeta(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);
+}
+
bool calcWindowedSincTables(void)
-{
- fKaiserSinc_8 = (float *)malloc(8*SINC_PHASES * sizeof (float));
- fDownSample1_8 = (float *)malloc(8*SINC_PHASES * sizeof (float));
- fDownSample2_8 = (float *)malloc(8*SINC_PHASES * sizeof (float));
+{
+ fKaiserSinc_8 = (float *)malloc(SINC1_TAPS*SINC_PHASES * sizeof (float));
+ fDownSample1_8 = (float *)malloc(SINC1_TAPS*SINC_PHASES * sizeof (float));
+ fDownSample2_8 = (float *)malloc(SINC1_TAPS*SINC_PHASES * sizeof (float));
- fKaiserSinc_16 = (float *)malloc(16*SINC_PHASES * sizeof (float));
- fDownSample1_16 = (float *)malloc(16*SINC_PHASES * sizeof (float));
- fDownSample2_16 = (float *)malloc(16*SINC_PHASES * sizeof (float));
+ fKaiserSinc_32 = (float *)malloc(SINC2_TAPS*SINC_PHASES * sizeof (float));
+ fDownSample1_32 = (float *)malloc(SINC2_TAPS*SINC_PHASES * sizeof (float));
+ fDownSample2_32 = (float *)malloc(SINC2_TAPS*SINC_PHASES * sizeof (float));
if (fKaiserSinc_8 == NULL || fDownSample1_8 == NULL || fDownSample2_8 == NULL ||
- fKaiserSinc_16 == NULL || fDownSample1_16 == NULL || fDownSample2_16 == NULL)
+ fKaiserSinc_32 == NULL || fDownSample1_32 == NULL || fDownSample2_32 == NULL)
{
showErrorMsgBox("Not enough memory!");
return false;
}
- getSinc(8, fKaiserSinc_8, 9.6377, 1.0);
- getSinc(8, fDownSample1_8, 8.5, 0.5);
- getSinc(8, fDownSample2_8, 7.3, 0.425);
+ // 8 point (modelled after OpenMPT)
+ getSinc(SINC1_TAPS, fKaiserSinc_8, dBToKaiserBeta(96.15645), 1.000);
+ getSinc(SINC1_TAPS, fDownSample1_8, dBToKaiserBeta(85.83249), 0.500);
+ getSinc(SINC1_TAPS, fDownSample2_8, dBToKaiserBeta(72.22088), 0.425);
- getSinc(16, fKaiserSinc_16, 9.6377, 1.0);
- getSinc(16, fDownSample1_16, 8.5, 0.5);
- getSinc(16, fDownSample2_16, 7.3, 0.425);
+ // 32 point
+ getSinc(SINC2_TAPS, fKaiserSinc_32, dBToKaiserBeta(96.0), 1.000);
+ getSinc(SINC2_TAPS, fDownSample1_32, dBToKaiserBeta(86.0), 0.500);
+ getSinc(SINC2_TAPS, fDownSample2_32, dBToKaiserBeta(74.0), 0.425);
return true;
}
@@ -116,21 +123,21 @@
fDownSample2_8 = NULL;
}
- if (fKaiserSinc_16 != NULL)
+ if (fKaiserSinc_32 != NULL)
{
- free(fKaiserSinc_16);
- fKaiserSinc_16 = NULL;
+ free(fKaiserSinc_32);
+ fKaiserSinc_32 = NULL;
}
- if (fDownSample1_16 != NULL)
+ if (fDownSample1_32 != NULL)
{
- free(fDownSample1_16);
- fDownSample1_16 = NULL;
+ free(fDownSample1_32);
+ fDownSample1_32 = NULL;
}
- if (fDownSample2_16 != NULL)
+ if (fDownSample2_32 != NULL)
{
- free(fDownSample2_16);
- fDownSample2_16 = NULL;
+ free(fDownSample2_32);
+ fDownSample2_32 = NULL;
}
}
--- a/src/mixer/ft2_windowed_sinc.h
+++ b/src/mixer/ft2_windowed_sinc.h
@@ -9,15 +9,19 @@
#define SINC_PHASES_BITS 13 // log2(SINC_PHASES)
// do not change these!
-#define SINC8_WIDTH_BITS 3 // log2(8)
+
+#define SINC1_TAPS 8
+#define SINC8_WIDTH_BITS 3 // log2(SINC1_TAPS)
#define SINC8_FSHIFT (MIXER_FRAC_BITS-(SINC_PHASES_BITS+SINC8_WIDTH_BITS))
-#define SINC8_FMASK ((8*SINC_PHASES)-8)
-#define SINC16_WIDTH_BITS 4 // log2(16)
-#define SINC16_FSHIFT (MIXER_FRAC_BITS-(SINC_PHASES_BITS+SINC16_WIDTH_BITS))
-#define SINC16_FMASK ((16*SINC_PHASES)-16)
+#define SINC8_FMASK ((SINC1_TAPS*SINC_PHASES)-SINC1_TAPS)
+#define SINC2_TAPS 32
+#define SINC32_WIDTH_BITS 5 // log2(SINC2_TAPS)
+#define SINC32_FSHIFT (MIXER_FRAC_BITS-(SINC_PHASES_BITS+SINC32_WIDTH_BITS))
+#define SINC32_FMASK ((SINC2_TAPS*SINC_PHASES)-SINC2_TAPS)
+
extern float *fKaiserSinc_8, *fDownSample1_8, *fDownSample2_8;
-extern float *fKaiserSinc_16, *fDownSample1_16, *fDownSample2_16;
+extern float *fKaiserSinc_32, *fDownSample1_32, *fDownSample2_32;
extern float *fKaiserSinc, *fDownSample1, *fDownSample2;