aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/effects/pshifter.c81
1 files changed, 42 insertions, 39 deletions
diff --git a/Alc/effects/pshifter.c b/Alc/effects/pshifter.c
index a0cf4f45..15e26e3d 100644
--- a/Alc/effects/pshifter.c
+++ b/Alc/effects/pshifter.c
@@ -29,8 +29,16 @@
#include "alError.h"
#include "alu.h"
+
#define MAX_SIZE 2048
+#define STFT_SIZE (MAX_SIZE>>1)
+#define STFT_HALF_SIZE (STFT_SIZE>>1)
+#define OVERSAMP (1<<2)
+
+#define STFT_STEP (STFT_SIZE / OVERSAMP)
+#define FIFO_LATENCY (STFT_STEP * (OVERSAMP-1))
+
typedef struct ALcomplex {
ALfloat Real;
ALfloat Imag;
@@ -51,10 +59,6 @@ typedef struct ALpshifterState {
/* Effect parameters */
ALsizei count;
- ALsizei STFT_size;
- ALsizei step;
- ALsizei FIFOLatency;
- ALsizei oversamp;
ALfloat PitchShift;
ALfloat Frequency;
@@ -205,13 +209,10 @@ static void ALpshifterState_Construct(ALpshifterState *state)
ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
SET_VTABLE2(ALpshifterState, ALeffectState, state);
- /*Initializing parameters and set to zero the buffers */
- state->STFT_size = MAX_SIZE>>1;
- state->oversamp = 1<<2;
-
- state->step = state->STFT_size / state->oversamp ;
- state->FIFOLatency = state->step * ( state->oversamp-1 );
- state->count = state->FIFOLatency;
+ /* Initializing parameters and set to zero the buffers. */
+ state->count = FIFO_LATENCY;
+ state->PitchShift = 1.0f;
+ state->Frequency = 1.0f;
memset(state->InFIFO, 0, sizeof(state->InFIFO));
memset(state->OutFIFO, 0, sizeof(state->OutFIFO));
@@ -222,10 +223,10 @@ static void ALpshifterState_Construct(ALpshifterState *state)
memset(state->Analysis_buffer, 0, sizeof(state->Analysis_buffer));
/* Create lockup table of the Hann window for the desired size, i.e. STFT_size */
- for ( i = 0; i < state->STFT_size>>1 ; i++ )
+ for ( i = 0; i < STFT_SIZE>>1 ; i++ )
{
- state->window[i] = state->window[state->STFT_size-(i+1)] \
- = 0.5f * ( 1 - cosf(F_TAU*(ALfloat)i/(ALfloat)(state->STFT_size-1)));
+ state->window[i] = state->window[STFT_SIZE-(i+1)]
+ = 0.5f * ( 1 - cosf(F_TAU*(ALfloat)i/(ALfloat)(STFT_SIZE-1)));
}
}
@@ -258,30 +259,26 @@ 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_bin = state->Frequency / (ALfloat)STFT_SIZE;
ALfloat *restrict bufferOut = state->BufferOut;
- ALsizei i, j, k, STFT_half_size;
- ALfloat freq_bin, expected, tmp;
- ALphasor component;
-
- STFT_half_size = state->STFT_size >> 1;
- freq_bin = state->Frequency / (ALfloat)state->STFT_size;
- expected = F_TAU / (ALfloat)state->oversamp;
+ ALsizei i, j, k;
for (i = 0; i < SamplesToDo; i++)
{
/* Fill FIFO buffer with samples data */
state->InFIFO[state->count] = SamplesIn[0][i];
- bufferOut[i] = state->OutFIFO[state->count - state->FIFOLatency];
+ bufferOut[i] = state->OutFIFO[state->count - FIFO_LATENCY];
state->count++;
/* Check whether FIFO buffer is filled */
- if ( state->count >= state->STFT_size )
+ if ( state->count >= STFT_SIZE )
{
- state->count = state->FIFOLatency;
+ state->count = FIFO_LATENCY;
/* Real signal windowing and store in FFTbuffer */
- for ( k = 0; k < state->STFT_size; k++ )
+ for ( k = 0; k < STFT_SIZE; k++ )
{
state->FFTbuffer[k].Real = state->InFIFO[k] * state->window[k];
state->FFTbuffer[k].Imag = 0.0f;
@@ -289,13 +286,16 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
/* ANALYSIS */
/* Apply FFT to FFTbuffer data */
- FFT( state->FFTbuffer, state->STFT_size, -1 );
+ FFT( state->FFTbuffer, STFT_SIZE, -1 );
/* Analyze the obtained data. Since the real FFT is symmetric, only
* STFT_half_size+1 samples are needed.
*/
- for ( k = 0; k <= STFT_half_size; k++ )
+ for ( k = 0; k <= STFT_HALF_SIZE; k++ )
{
+ ALphasor component;
+ ALfloat tmp;
+
/* Compute amplitude and phase */
component = rect2polar( state->FFTbuffer[k] );
@@ -322,13 +322,13 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
/* PROCESSING */
/* pitch shifting */
- memset(state->Syntesis_buffer, 0, state->STFT_size*sizeof(ALfrequencyDomain));
+ memset(state->Syntesis_buffer, 0, STFT_SIZE*sizeof(ALfrequencyDomain));
- for (k = 0; k <= STFT_half_size; k++)
+ for (k = 0; k <= STFT_HALF_SIZE; k++)
{
j = fastf2i( (ALfloat)k*state->PitchShift );
- if ( j <= STFT_half_size )
+ if ( j <= STFT_HALF_SIZE )
{
state->Syntesis_buffer[j].Amplitude += state->Analysis_buffer[k].Amplitude;
state->Syntesis_buffer[j].Frequency = state->Analysis_buffer[k].Frequency *
@@ -338,10 +338,13 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
/* SYNTHESIS */
/* Synthesis the processing data */
- for ( k = 0; k <= STFT_half_size; k++ )
+ for ( k = 0; k <= STFT_HALF_SIZE; k++ )
{
+ ALphasor component;
+ ALfloat tmp;
+
/* Compute bin deviation from scaled freq */
- tmp = state->Syntesis_buffer[k].Frequency /freq_bin - (ALfloat)k;
+ tmp = state->Syntesis_buffer[k].Frequency/freq_bin - (ALfloat)k;
/* Calculate actual delta phase and accumulate it to get bin phase */
state->SumPhase[k] += ((ALfloat)k + tmp) * expected;
@@ -354,22 +357,22 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
}
/* zero negative frequencies for recontruct a real signal */
- memset( &state->FFTbuffer[STFT_half_size+1], 0, (STFT_half_size-1) * sizeof(ALcomplex) );
+ memset( &state->FFTbuffer[STFT_HALF_SIZE+1], 0, (STFT_HALF_SIZE-1)*sizeof(ALcomplex));
/* Apply iFFT to buffer data */
- FFT( state->FFTbuffer, state->STFT_size, 1 );
+ FFT( state->FFTbuffer, STFT_SIZE, 1 );
/* Windowing and add to output */
- for( k=0; k < state->STFT_size; k++ )
+ for( k=0; k < STFT_SIZE; k++ )
{
state->OutputAccum[k] += 2.0f * state->window[k]*state->FFTbuffer[k].Real /
- (STFT_half_size * state->oversamp);
+ (STFT_HALF_SIZE * OVERSAMP);
}
/* Shift accumulator, input & output FIFO */
- memmove(state->OutFIFO , state->OutputAccum , state->step *sizeof(ALfloat));
- memmove(state->OutputAccum, state->OutputAccum+state->step, state->STFT_size *sizeof(ALfloat));
- memmove(state->InFIFO , state->InFIFO +state->step, state->FIFOLatency*sizeof(ALfloat));
+ memmove(state->OutFIFO , state->OutputAccum , STFT_STEP *sizeof(ALfloat));
+ memmove(state->OutputAccum, state->OutputAccum+STFT_STEP, STFT_SIZE *sizeof(ALfloat));
+ memmove(state->InFIFO , state->InFIFO +STFT_STEP, FIFO_LATENCY*sizeof(ALfloat));
}
}