diff options
author | Chris Robinson <[email protected]> | 2015-11-05 09:42:08 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2015-11-05 09:42:08 -0800 |
commit | b9e192b78a384ff13d87c606502373725042509c (patch) | |
tree | e5b99bba51f713e2f671b9ffbc37b22a1cdf5ba1 /OpenAL32 | |
parent | dce3d0c7bf8f68c0dc4d98870f9e8119742004c0 (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.h | 2 | ||||
-rw-r--r-- | OpenAL32/Include/alu.h | 34 |
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) { |