aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/effects/distortion.c
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/effects/distortion.c')
-rw-r--r--Alc/effects/distortion.c46
1 files changed, 21 insertions, 25 deletions
diff --git a/Alc/effects/distortion.c b/Alc/effects/distortion.c
index 837e4d3b..8fba07df 100644
--- a/Alc/effects/distortion.c
+++ b/Alc/effects/distortion.c
@@ -41,6 +41,8 @@ typedef struct ALdistortionState {
ALfilterState bandpass;
ALfloat attenuation;
ALfloat edge_coeff;
+
+ ALfloat Buffer[2][BUFFERSIZE];
} ALdistortionState;
static ALvoid ALdistortionState_Destruct(ALdistortionState *state);
@@ -106,73 +108,67 @@ static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCcontex
static ALvoid ALdistortionState_process(ALdistortionState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
+ ALfloat (*restrict buffer)[BUFFERSIZE] = state->Buffer;
const ALfloat fc = state->edge_coeff;
- ALsizei it, kt;
ALsizei base;
+ ALsizei i, k;
for(base = 0;base < SamplesToDo;)
{
- float buffer[2][64 * 4];
- ALsizei td = mini(64, SamplesToDo-base);
-
/* Perform 4x oversampling to avoid aliasing. Oversampling greatly
* improves distortion quality and allows to implement lowpass and
* bandpass filters using high frequencies, at which classic IIR
* filters became unstable.
*/
+ ALsizei todo = mini(BUFFERSIZE, (SamplesToDo-base) * 4);
- /* Fill oversample buffer using zero stuffing. */
- for(it = 0;it < td;it++)
- {
- /* Multiply the sample by the amount of oversampling to maintain
- * the signal's power.
- */
- buffer[0][it*4 + 0] = SamplesIn[0][it+base] * 4.0f;
- buffer[0][it*4 + 1] = 0.0f;
- buffer[0][it*4 + 2] = 0.0f;
- buffer[0][it*4 + 3] = 0.0f;
- }
+ /* Fill oversample buffer using zero stuffing. Multiply the sample by
+ * the amount of oversampling to maintain the signal's power.
+ */
+ for(i = 0;i < todo;i++)
+ buffer[0][i] = !(i&3) ? SamplesIn[0][(i>>2)+base] * 4.0f : 0.0f;
/* First step, do lowpass filtering of original signal. Additionally
* perform buffer interpolation and lowpass cutoff for oversampling
* (which is fortunately first step of distortion). So combine three
* operations into the one.
*/
- ALfilterState_process(&state->lowpass, buffer[1], buffer[0], td*4);
+ ALfilterState_process(&state->lowpass, buffer[1], buffer[0], todo);
/* Second step, do distortion using waveshaper function to emulate
* signal processing during tube overdriving. Three steps of
* waveshaping are intended to modify waveform without boost/clipping/
* attenuation process.
*/
- for(it = 0;it < td*4;it++)
+ for(i = 0;i < todo;i++)
{
- ALfloat smp = buffer[1][it];
+ ALfloat smp = buffer[1][i];
smp = (1.0f + fc) * smp/(1.0f + fc*fabsf(smp));
smp = (1.0f + fc) * smp/(1.0f + fc*fabsf(smp)) * -1.0f;
smp = (1.0f + fc) * smp/(1.0f + fc*fabsf(smp));
- buffer[0][it] = smp;
+ buffer[0][i] = smp;
}
/* Third step, do bandpass filtering of distorted signal. */
- ALfilterState_process(&state->bandpass, buffer[1], buffer[0], td*4);
+ ALfilterState_process(&state->bandpass, buffer[1], buffer[0], todo);
- for(kt = 0;kt < NumChannels;kt++)
+ todo >>= 2;
+ for(k = 0;k < NumChannels;k++)
{
/* Fourth step, final, do attenuation and perform decimation,
* storing only one sample out of four.
*/
- ALfloat gain = state->Gain[kt];
+ ALfloat gain = state->Gain[k];
if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
continue;
- for(it = 0;it < td;it++)
- SamplesOut[kt][base+it] += gain * buffer[1][it*4];
+ for(i = 0;i < todo;i++)
+ SamplesOut[k][base+i] += gain * buffer[1][i*4];
}
- base += td;
+ base += todo;
}
}