aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2015-11-05 09:42:08 -0800
committerChris Robinson <[email protected]>2015-11-05 09:42:08 -0800
commitb9e192b78a384ff13d87c606502373725042509c (patch)
treee5b99bba51f713e2f671b9ffbc37b22a1cdf5ba1 /OpenAL32
parentdce3d0c7bf8f68c0dc4d98870f9e8119742004c0 (diff)
Implement a band-limited sinc resampler
This is essentially a 12-point sinc resampler, unless it's resampling to a rate higher than the output, at which point it will vary between 12 and 24 points and do anti-aliasing to avoid/reduce frequencies going over nyquist. Code provided by Christopher Fitzgerald.
Diffstat (limited to 'OpenAL32')
-rw-r--r--OpenAL32/Include/alSource.h2
-rw-r--r--OpenAL32/Include/alu.h34
2 files changed, 32 insertions, 4 deletions
diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h
index c101b321..13596161 100644
--- a/OpenAL32/Include/alSource.h
+++ b/OpenAL32/Include/alSource.h
@@ -37,6 +37,8 @@ typedef struct ALvoice {
alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES];
+ BsincState SincState;
+
DirectParams Direct;
SendParams Send[MAX_SENDS];
} ALvoice;
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index 27cf6713..0832fbfb 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -22,10 +22,10 @@
#define MAX_PITCH (255)
/* Maximum number of buffer samples before the current pos needed for resampling. */
-#define MAX_PRE_SAMPLES 4
+#define MAX_PRE_SAMPLES 12
/* Maximum number of buffer samples after the current pos needed for resampling. */
-#define MAX_POST_SAMPLES 4
+#define MAX_POST_SAMPLES 12
#ifdef __cplusplus
@@ -36,6 +36,29 @@ struct ALsource;
struct ALvoice;
+/* The number of distinct scale and phase intervals within the filter table. */
+#define BSINC_SCALE_BITS 4
+#define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
+#define BSINC_PHASE_BITS 4
+#define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
+
+/* Interpolator state. Kind of a misnomer since the interpolator itself is
+ * stateless. This just keeps it from having to recompute scale-related
+ * mappings for every sample.
+ */
+typedef struct BsincState {
+ ALfloat sf; /* Scale interpolation factor. */
+ ALuint m; /* Coefficient count. */
+ ALint l; /* Left coefficient offset. */
+ struct {
+ const ALfloat *filter; /* Filter coefficients. */
+ const ALfloat *scDelta; /* Scale deltas. */
+ const ALfloat *phDelta; /* Phase deltas. */
+ const ALfloat *spDelta; /* Scale-phase deltas. */
+ } coeffs[BSINC_PHASE_COUNT];
+} BsincState;
+
+
typedef union aluVector {
alignas(16) ALfloat v[4];
} aluVector;
@@ -132,8 +155,9 @@ typedef struct SendParams {
} SendParams;
-typedef const ALfloat* (*ResamplerFunc)(const ALfloat *src, ALuint frac, ALuint increment,
- ALfloat *restrict dst, ALuint dstlen);
+typedef const ALfloat* (*ResamplerFunc)(const BsincState *state,
+ const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen
+);
typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
ALfloat (*restrict OutBuffer)[BUFFERSIZE], struct MixGains *Gains,
@@ -203,6 +227,8 @@ union ResamplerCoeffs {
};
extern alignas(16) union ResamplerCoeffs ResampleCoeffs;
+extern alignas(16) const ALfloat bsincTab[18840];
+
inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
{