mirror of
https://github.com/love2d/megasource.git
synced 2026-08-21 13:10:24 +02:00
Update OpenAL Soft to 1.19.1.
This commit is contained in:
@@ -29,6 +29,8 @@
|
||||
#include "alu.h"
|
||||
#include "filters/defs.h"
|
||||
|
||||
#include "alcomplex.h"
|
||||
|
||||
|
||||
#define STFT_SIZE 1024
|
||||
#define STFT_HALF_SIZE (STFT_SIZE>>1)
|
||||
@@ -37,35 +39,33 @@
|
||||
#define STFT_STEP (STFT_SIZE / OVERSAMP)
|
||||
#define FIFO_LATENCY (STFT_STEP * (OVERSAMP-1))
|
||||
|
||||
typedef struct ALcomplex {
|
||||
ALfloat Real;
|
||||
ALfloat Imag;
|
||||
} ALcomplex;
|
||||
|
||||
typedef struct ALphasor {
|
||||
ALfloat Amplitude;
|
||||
ALfloat Phase;
|
||||
ALdouble Amplitude;
|
||||
ALdouble Phase;
|
||||
} ALphasor;
|
||||
|
||||
typedef struct ALFrequencyDomain {
|
||||
ALfloat Amplitude;
|
||||
ALfloat Frequency;
|
||||
ALdouble Amplitude;
|
||||
ALdouble Frequency;
|
||||
} ALfrequencyDomain;
|
||||
|
||||
|
||||
typedef struct ALpshifterState {
|
||||
DERIVE_FROM_TYPE(ALeffectState);
|
||||
|
||||
/* Effect parameters */
|
||||
ALsizei count;
|
||||
ALsizei PitchShiftI;
|
||||
ALfloat PitchShift;
|
||||
ALfloat FreqPerBin;
|
||||
|
||||
/*Effects buffers*/
|
||||
ALfloat InFIFO[STFT_SIZE];
|
||||
ALfloat OutFIFO[STFT_STEP];
|
||||
ALfloat LastPhase[STFT_HALF_SIZE+1];
|
||||
ALfloat SumPhase[STFT_HALF_SIZE+1];
|
||||
ALfloat OutputAccum[STFT_SIZE];
|
||||
ALdouble LastPhase[STFT_HALF_SIZE+1];
|
||||
ALdouble SumPhase[STFT_HALF_SIZE+1];
|
||||
ALdouble OutputAccum[STFT_SIZE];
|
||||
|
||||
ALcomplex FFTbuffer[STFT_SIZE];
|
||||
|
||||
@@ -89,7 +89,7 @@ DEFINE_ALEFFECTSTATE_VTABLE(ALpshifterState);
|
||||
|
||||
|
||||
/* Define a Hann window, used to filter the STFT input and output. */
|
||||
alignas(16) static ALfloat HannWindow[STFT_SIZE];
|
||||
alignas(16) static ALdouble HannWindow[STFT_SIZE];
|
||||
|
||||
static void InitHannWindow(void)
|
||||
{
|
||||
@@ -99,124 +99,65 @@ static void InitHannWindow(void)
|
||||
for(i = 0;i < STFT_SIZE>>1;i++)
|
||||
{
|
||||
ALdouble val = sin(M_PI * (ALdouble)i / (ALdouble)(STFT_SIZE-1));
|
||||
HannWindow[i] = HannWindow[STFT_SIZE-(i+1)] = (ALfloat)(val * val);
|
||||
HannWindow[i] = HannWindow[STFT_SIZE-1-i] = val * val;
|
||||
}
|
||||
}
|
||||
static alonce_flag HannInitOnce = AL_ONCE_FLAG_INIT;
|
||||
|
||||
|
||||
static inline ALint double2int(ALdouble d)
|
||||
{
|
||||
#if ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
|
||||
!defined(__SSE2_MATH__)) || (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP < 2)
|
||||
ALint sign, shift;
|
||||
ALint64 mant;
|
||||
union {
|
||||
ALdouble d;
|
||||
ALint64 i64;
|
||||
} conv;
|
||||
|
||||
conv.d = d;
|
||||
sign = (conv.i64>>63) | 1;
|
||||
shift = ((conv.i64>>52)&0x7ff) - (1023+52);
|
||||
|
||||
/* Over/underflow */
|
||||
if(UNLIKELY(shift >= 63 || shift < -52))
|
||||
return 0;
|
||||
|
||||
mant = (conv.i64&I64(0xfffffffffffff)) | I64(0x10000000000000);
|
||||
if(LIKELY(shift < 0))
|
||||
return (ALint)(mant >> -shift) * sign;
|
||||
return (ALint)(mant << shift) * sign;
|
||||
|
||||
#else
|
||||
|
||||
return (ALint)d;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Converts ALcomplex to ALphasor */
|
||||
static inline ALphasor rect2polar(ALcomplex number)
|
||||
{
|
||||
ALphasor polar;
|
||||
|
||||
polar.Amplitude = sqrtf(number.Real*number.Real + number.Imag*number.Imag);
|
||||
polar.Phase = atan2f(number.Imag , number.Real);
|
||||
polar.Amplitude = sqrt(number.Real*number.Real + number.Imag*number.Imag);
|
||||
polar.Phase = atan2(number.Imag, number.Real);
|
||||
|
||||
return polar;
|
||||
}
|
||||
|
||||
/* Converts ALphasor to ALcomplex */
|
||||
static inline ALcomplex polar2rect(ALphasor number)
|
||||
static inline ALcomplex polar2rect(ALphasor number)
|
||||
{
|
||||
ALcomplex cartesian;
|
||||
|
||||
cartesian.Real = number.Amplitude * cosf(number.Phase);
|
||||
cartesian.Imag = number.Amplitude * sinf(number.Phase);
|
||||
cartesian.Real = number.Amplitude * cos(number.Phase);
|
||||
cartesian.Imag = number.Amplitude * sin(number.Phase);
|
||||
|
||||
return cartesian;
|
||||
}
|
||||
|
||||
/* Addition of two complex numbers (ALcomplex format) */
|
||||
static inline ALcomplex complex_add(ALcomplex a, ALcomplex b)
|
||||
{
|
||||
ALcomplex result;
|
||||
|
||||
result.Real = a.Real + b.Real;
|
||||
result.Imag = a.Imag + b.Imag;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Subtraction of two complex numbers (ALcomplex format) */
|
||||
static inline ALcomplex complex_sub(ALcomplex a, ALcomplex b)
|
||||
{
|
||||
ALcomplex result;
|
||||
|
||||
result.Real = a.Real - b.Real;
|
||||
result.Imag = a.Imag - b.Imag;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Multiplication of two complex numbers (ALcomplex format) */
|
||||
static inline ALcomplex complex_mult(ALcomplex a, ALcomplex b)
|
||||
{
|
||||
ALcomplex result;
|
||||
|
||||
result.Real = a.Real*b.Real - a.Imag*b.Imag;
|
||||
result.Imag = a.Imag*b.Real + a.Real*b.Imag;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Iterative implementation of 2-radix FFT (In-place algorithm). Sign = -1 is
|
||||
* FFT and 1 is iFFT (inverse). Fills FFTBuffer[0...FFTSize-1] with the
|
||||
* Discrete Fourier Transform (DFT) of the time domain data stored in
|
||||
* FFTBuffer[0...FFTSize-1]. FFTBuffer is an array of complex numbers
|
||||
* (ALcomplex), FFTSize MUST BE power of two.
|
||||
*/
|
||||
static inline ALvoid FFT(ALcomplex *FFTBuffer, ALsizei FFTSize, ALfloat Sign)
|
||||
{
|
||||
ALsizei i, j, k, mask, step, step2;
|
||||
ALcomplex temp, u, w;
|
||||
ALfloat arg;
|
||||
|
||||
/* Bit-reversal permutation applied to a sequence of FFTSize items */
|
||||
for(i = 1;i < FFTSize-1;i++)
|
||||
{
|
||||
for(mask = 0x1, j = 0;mask < FFTSize;mask <<= 1)
|
||||
{
|
||||
if((i&mask) != 0)
|
||||
j++;
|
||||
j <<= 1;
|
||||
}
|
||||
j >>= 1;
|
||||
|
||||
if(i < j)
|
||||
{
|
||||
temp = FFTBuffer[i];
|
||||
FFTBuffer[i] = FFTBuffer[j];
|
||||
FFTBuffer[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterative form of Danielson–Lanczos lemma */
|
||||
for(i = 1, step = 2;i < FFTSize;i<<=1, step<<=1)
|
||||
{
|
||||
step2 = step >> 1;
|
||||
arg = F_PI / step2;
|
||||
|
||||
w.Real = cosf(arg);
|
||||
w.Imag = sinf(arg) * Sign;
|
||||
|
||||
u.Real = 1.0f;
|
||||
u.Imag = 0.0f;
|
||||
|
||||
for(j = 0;j < step2;j++)
|
||||
{
|
||||
for(k = j;k < FFTSize;k+=step)
|
||||
{
|
||||
temp = complex_mult(FFTBuffer[k+step2], u);
|
||||
FFTBuffer[k+step2] = complex_sub(FFTBuffer[k], temp);
|
||||
FFTBuffer[k] = complex_add(FFTBuffer[k], temp);
|
||||
}
|
||||
|
||||
u = complex_mult(u, w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ALpshifterState_Construct(ALpshifterState *state)
|
||||
{
|
||||
@@ -234,9 +175,10 @@ static ALvoid ALpshifterState_Destruct(ALpshifterState *state)
|
||||
static ALboolean ALpshifterState_deviceUpdate(ALpshifterState *state, ALCdevice *device)
|
||||
{
|
||||
/* (Re-)initializing parameters and clear the buffers. */
|
||||
state->count = FIFO_LATENCY;
|
||||
state->PitchShift = 1.0f;
|
||||
state->FreqPerBin = device->Frequency / (ALfloat)STFT_SIZE;
|
||||
state->count = FIFO_LATENCY;
|
||||
state->PitchShiftI = FRACTIONONE;
|
||||
state->PitchShift = 1.0f;
|
||||
state->FreqPerBin = device->Frequency / (ALfloat)STFT_SIZE;
|
||||
|
||||
memset(state->InFIFO, 0, sizeof(state->InFIFO));
|
||||
memset(state->OutFIFO, 0, sizeof(state->OutFIFO));
|
||||
@@ -257,13 +199,16 @@ static ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *c
|
||||
{
|
||||
const ALCdevice *device = context->Device;
|
||||
ALfloat coeffs[MAX_AMBI_COEFFS];
|
||||
float pitch;
|
||||
|
||||
state->PitchShift = powf(2.0f,
|
||||
pitch = powf(2.0f,
|
||||
(ALfloat)(props->Pshifter.CoarseTune*100 + props->Pshifter.FineTune) / 1200.0f
|
||||
);
|
||||
state->PitchShiftI = fastf2i(pitch*FRACTIONONE);
|
||||
state->PitchShift = state->PitchShiftI * (1.0f/FRACTIONONE);
|
||||
|
||||
CalcAngleCoeffs(0.0f, 0.0f, 0.0f, coeffs);
|
||||
ComputeDryPanGains(&device->Dry, coeffs, slot->Params.Gain, state->TargetGains);
|
||||
ComputePanGains(&device->Dry, coeffs, slot->Params.Gain, state->TargetGains);
|
||||
}
|
||||
|
||||
static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
|
||||
@@ -272,8 +217,8 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
|
||||
* http://blogs.zynaptiq.com/bernsee/pitch-shifting-using-the-ft/
|
||||
*/
|
||||
|
||||
static const ALfloat expected = F_TAU / (ALfloat)OVERSAMP;
|
||||
const ALfloat freq_per_bin = state->FreqPerBin;
|
||||
static const ALdouble expected = M_PI*2.0 / OVERSAMP;
|
||||
const ALdouble freq_per_bin = state->FreqPerBin;
|
||||
ALfloat *restrict bufferOut = state->BufferOut;
|
||||
ALsizei count = state->count;
|
||||
ALsizei i, j, k;
|
||||
@@ -296,12 +241,12 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
|
||||
for(k = 0;k < STFT_SIZE;k++)
|
||||
{
|
||||
state->FFTbuffer[k].Real = state->InFIFO[k] * HannWindow[k];
|
||||
state->FFTbuffer[k].Imag = 0.0f;
|
||||
state->FFTbuffer[k].Imag = 0.0;
|
||||
}
|
||||
|
||||
/* ANALYSIS */
|
||||
/* Apply FFT to FFTbuffer data */
|
||||
FFT(state->FFTbuffer, STFT_SIZE, -1.0f);
|
||||
complex_fft(state->FFTbuffer, STFT_SIZE, -1.0);
|
||||
|
||||
/* Analyze the obtained data. Since the real FFT is symmetric, only
|
||||
* STFT_HALF_SIZE+1 samples are needed.
|
||||
@@ -309,18 +254,18 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
|
||||
for(k = 0;k < STFT_HALF_SIZE+1;k++)
|
||||
{
|
||||
ALphasor component;
|
||||
ALfloat tmp;
|
||||
ALdouble tmp;
|
||||
ALint qpd;
|
||||
|
||||
/* Compute amplitude and phase */
|
||||
component = rect2polar(state->FFTbuffer[k]);
|
||||
|
||||
/* Compute phase difference and subtract expected phase difference */
|
||||
tmp = (component.Phase - state->LastPhase[k]) - (ALfloat)k*expected;
|
||||
tmp = (component.Phase - state->LastPhase[k]) - k*expected;
|
||||
|
||||
/* Map delta phase into +/- Pi interval */
|
||||
qpd = fastf2i(tmp / F_PI);
|
||||
tmp -= F_PI * (ALfloat)(qpd + (qpd%2));
|
||||
qpd = double2int(tmp / M_PI);
|
||||
tmp -= M_PI * (qpd + (qpd%2));
|
||||
|
||||
/* Get deviation from bin frequency from the +/- Pi interval */
|
||||
tmp /= expected;
|
||||
@@ -329,8 +274,8 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
|
||||
* for maintain the gain (because half of bins are used) and store
|
||||
* amplitude and true frequency in analysis buffer.
|
||||
*/
|
||||
state->Analysis_buffer[k].Amplitude = 2.0f * component.Amplitude;
|
||||
state->Analysis_buffer[k].Frequency = ((ALfloat)k + tmp) * freq_per_bin;
|
||||
state->Analysis_buffer[k].Amplitude = 2.0 * component.Amplitude;
|
||||
state->Analysis_buffer[k].Frequency = (k + tmp) * freq_per_bin;
|
||||
|
||||
/* Store actual phase[k] for the calculations in the next frame*/
|
||||
state->LastPhase[k] = component.Phase;
|
||||
@@ -340,13 +285,13 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
|
||||
/* pitch shifting */
|
||||
for(k = 0;k < STFT_HALF_SIZE+1;k++)
|
||||
{
|
||||
state->Syntesis_buffer[k].Amplitude = 0.0f;
|
||||
state->Syntesis_buffer[k].Frequency = 0.0f;
|
||||
state->Syntesis_buffer[k].Amplitude = 0.0;
|
||||
state->Syntesis_buffer[k].Frequency = 0.0;
|
||||
}
|
||||
|
||||
for(k = 0;k < STFT_HALF_SIZE+1;k++)
|
||||
{
|
||||
j = fastf2i((ALfloat)k * state->PitchShift);
|
||||
j = (k*state->PitchShiftI) >> FRACTIONBITS;
|
||||
if(j >= STFT_HALF_SIZE+1) break;
|
||||
|
||||
state->Syntesis_buffer[j].Amplitude += state->Analysis_buffer[k].Amplitude;
|
||||
@@ -359,13 +304,13 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
|
||||
for(k = 0;k < STFT_HALF_SIZE+1;k++)
|
||||
{
|
||||
ALphasor component;
|
||||
ALfloat tmp;
|
||||
ALdouble tmp;
|
||||
|
||||
/* Compute bin deviation from scaled freq */
|
||||
tmp = state->Syntesis_buffer[k].Frequency/freq_per_bin - (ALfloat)k;
|
||||
tmp = state->Syntesis_buffer[k].Frequency/freq_per_bin - k;
|
||||
|
||||
/* Calculate actual delta phase and accumulate it to get bin phase */
|
||||
state->SumPhase[k] += ((ALfloat)k + tmp) * expected;
|
||||
state->SumPhase[k] += (k + tmp) * expected;
|
||||
|
||||
component.Amplitude = state->Syntesis_buffer[k].Amplitude;
|
||||
component.Phase = state->SumPhase[k];
|
||||
@@ -376,22 +321,22 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
|
||||
/* zero negative frequencies for recontruct a real signal */
|
||||
for(k = STFT_HALF_SIZE+1;k < STFT_SIZE;k++)
|
||||
{
|
||||
state->FFTbuffer[k].Real = 0.0f;
|
||||
state->FFTbuffer[k].Imag = 0.0f;
|
||||
state->FFTbuffer[k].Real = 0.0;
|
||||
state->FFTbuffer[k].Imag = 0.0;
|
||||
}
|
||||
|
||||
/* Apply iFFT to buffer data */
|
||||
FFT(state->FFTbuffer, STFT_SIZE, 1.0f);
|
||||
complex_fft(state->FFTbuffer, STFT_SIZE, 1.0);
|
||||
|
||||
/* Windowing and add to output */
|
||||
for(k = 0;k < STFT_SIZE;k++)
|
||||
state->OutputAccum[k] += HannWindow[k] * state->FFTbuffer[k].Real /
|
||||
(0.5f * STFT_HALF_SIZE * OVERSAMP);
|
||||
(0.5 * STFT_HALF_SIZE * OVERSAMP);
|
||||
|
||||
/* Shift accumulator, input & output FIFO */
|
||||
for(k = 0;k < STFT_STEP;k++) state->OutFIFO[k] = state->OutputAccum[k];
|
||||
for(k = 0;k < STFT_STEP;k++) state->OutFIFO[k] = (ALfloat)state->OutputAccum[k];
|
||||
for(j = 0;k < STFT_SIZE;k++,j++) state->OutputAccum[j] = state->OutputAccum[k];
|
||||
for(;j < STFT_SIZE;j++) state->OutputAccum[j] = 0.0f;
|
||||
for(;j < STFT_SIZE;j++) state->OutputAccum[j] = 0.0;
|
||||
for(k = 0;k < FIFO_LATENCY;k++)
|
||||
state->InFIFO[k] = state->InFIFO[k+STFT_STEP];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user