aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2013-05-20 04:16:48 -0700
committerChris Robinson <[email protected]>2013-05-20 04:16:48 -0700
commit5b706f3bdc1a8c8f064a253b53b4e86f9d88da8d (patch)
tree611e350eb0fe6986423e7a0522b6a42af436187c
parent80459b13e45306958f9fa2087ef750f1e736818b (diff)
Process 64 samples at a time for some effects
This should help with the non-interleaved samples of the output, and allow skipping channels that don't contribute to the output.
-rw-r--r--Alc/alcDedicated.c3
-rw-r--r--Alc/alcDistortion.c157
-rw-r--r--Alc/alcEcho.c48
-rw-r--r--Alc/alcEqualizer.c76
-rw-r--r--Alc/alcModulator.c34
5 files changed, 201 insertions, 117 deletions
diff --git a/Alc/alcDedicated.c b/Alc/alcDedicated.c
index e10ad9e9..bb82bbcb 100644
--- a/Alc/alcDedicated.c
+++ b/Alc/alcDedicated.c
@@ -73,6 +73,9 @@ static ALvoid DedicatedProcess(ALeffectState *effect, ALuint SamplesToDo, const
for(c = 0;c < MaxChannels;c++)
{
+ if(!(gains[c] > 0.00001f))
+ continue;
+
for(i = 0;i < SamplesToDo;i++)
SamplesOut[c][i] = SamplesIn[i] * gains[c];
}
diff --git a/Alc/alcDistortion.c b/Alc/alcDistortion.c
index 05833680..315a7761 100644
--- a/Alc/alcDistortion.c
+++ b/Alc/alcDistortion.c
@@ -58,9 +58,6 @@ typedef struct ALdistortionState {
ALfloat frequency;
ALfloat attenuation;
ALfloat edge_coeff;
-
- /* Oversample data */
- ALfloat oversample_buffer[BUFFERSIZE][4];
} ALdistortionState;
static ALvoid DistortionDestroy(ALeffectState *effect)
@@ -134,81 +131,103 @@ static ALvoid DistortionUpdate(ALeffectState *effect, ALCdevice *Device, const A
static ALvoid DistortionProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
{
ALdistortionState *state = GET_PARENT_TYPE(ALdistortionState, ALeffectState, effect);
- float *RESTRICT oversample_buffer = &state->oversample_buffer[0][0];
+ const ALfloat fc = state->edge_coeff;
+ float oversample_buffer[64][4];
ALfloat tempsmp;
+ ALuint base;
ALuint it;
+ ALuint ot;
ALuint kt;
- /* 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. */
-
- /* Fill oversample buffer using zero stuffing */
- for(it = 0; it < SamplesToDo; it++)
+ for(base = 0;base < SamplesToDo;)
{
- oversample_buffer[it*4 + 0] = SamplesIn[it];
- oversample_buffer[it*4 + 1] = 0.0f;
- oversample_buffer[it*4 + 2] = 0.0f;
- oversample_buffer[it*4 + 3] = 0.0f;
- }
+ ALfloat temps[64];
+ ALuint td = minu(SamplesToDo-base, 64);
- /* 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. */
- for(it = 0; it < SamplesToDo * 4; it++)
- {
- tempsmp = state->lowpass.b[0] / state->lowpass.a[0] * oversample_buffer[it] +
- state->lowpass.b[1] / state->lowpass.a[0] * state->lowpass.x[0] +
- state->lowpass.b[2] / state->lowpass.a[0] * state->lowpass.x[1] -
- state->lowpass.a[1] / state->lowpass.a[0] * state->lowpass.y[0] -
- state->lowpass.a[2] / state->lowpass.a[0] * state->lowpass.y[1];
-
- state->lowpass.x[1] = state->lowpass.x[0];
- state->lowpass.x[0] = oversample_buffer[it];
- state->lowpass.y[1] = state->lowpass.y[0];
- state->lowpass.y[0] = tempsmp;
- /* Restore signal power by multiplying sample by amount of oversampling */
- oversample_buffer[it] = tempsmp * 4.0f;
- }
+ /* 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. */
- for(it = 0; it < SamplesToDo * 4; it++)
- {
- ALfloat smp = oversample_buffer[it];
- ALfloat fc = state->edge_coeff;
-
- /* 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. */
- 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));
-
- /* Third step, do bandpass filtering of distorted signal */
- tempsmp = state->bandpass.b[0] / state->bandpass.a[0] * smp +
- state->bandpass.b[1] / state->bandpass.a[0] * state->bandpass.x[0] +
- state->bandpass.b[2] / state->bandpass.a[0] * state->bandpass.x[1] -
- state->bandpass.a[1] / state->bandpass.a[0] * state->bandpass.y[0] -
- state->bandpass.a[2] / state->bandpass.a[0] * state->bandpass.y[1];
-
- state->bandpass.x[1] = state->bandpass.x[0];
- state->bandpass.x[0] = smp;
- state->bandpass.y[1] = state->bandpass.y[0];
- state->bandpass.y[0] = tempsmp;
- smp = tempsmp;
-
- /* Fourth step, final, do attenuation and perform decimation, */
- /* store only one sample out of 4. */
- if(!(it&3))
+ /* Fill oversample buffer using zero stuffing */
+ for(it = 0;it < td;it++)
+ {
+ oversample_buffer[it][0] = SamplesIn[it+base];
+ oversample_buffer[it][1] = 0.0f;
+ oversample_buffer[it][2] = 0.0f;
+ oversample_buffer[it][3] = 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. */
+ for(it = 0;it < td;it++)
{
- smp *= state->attenuation;
- for(kt = 0; kt < MaxChannels; kt++)
- SamplesOut[kt][it>>2] += state->Gain[kt] * smp;
+ for(ot = 0;ot < 4;ot++)
+ {
+ tempsmp = state->lowpass.b[0] / state->lowpass.a[0] * oversample_buffer[it][ot] +
+ state->lowpass.b[1] / state->lowpass.a[0] * state->lowpass.x[0] +
+ state->lowpass.b[2] / state->lowpass.a[0] * state->lowpass.x[1] -
+ state->lowpass.a[1] / state->lowpass.a[0] * state->lowpass.y[0] -
+ state->lowpass.a[2] / state->lowpass.a[0] * state->lowpass.y[1];
+
+ state->lowpass.x[1] = state->lowpass.x[0];
+ state->lowpass.x[0] = oversample_buffer[it][ot];
+ state->lowpass.y[1] = state->lowpass.y[0];
+ state->lowpass.y[0] = tempsmp;
+ /* Restore signal power by multiplying sample by amount of oversampling */
+ oversample_buffer[it][ot] = tempsmp * 4.0f;
+ }
}
+
+ for(it = 0;it < td;it++)
+ {
+ /* 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(ot = 0;ot < 4;ot++)
+ {
+ ALfloat smp = oversample_buffer[it][ot];
+
+ 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));
+
+ /* Third step, do bandpass filtering of distorted signal */
+ tempsmp = state->bandpass.b[0] / state->bandpass.a[0] * smp +
+ state->bandpass.b[1] / state->bandpass.a[0] * state->bandpass.x[0] +
+ state->bandpass.b[2] / state->bandpass.a[0] * state->bandpass.x[1] -
+ state->bandpass.a[1] / state->bandpass.a[0] * state->bandpass.y[0] -
+ state->bandpass.a[2] / state->bandpass.a[0] * state->bandpass.y[1];
+
+ state->bandpass.x[1] = state->bandpass.x[0];
+ state->bandpass.x[0] = smp;
+ state->bandpass.y[1] = state->bandpass.y[0];
+ state->bandpass.y[0] = tempsmp;
+
+ oversample_buffer[it][ot] = tempsmp;
+ }
+
+ /* Fourth step, final, do attenuation and perform decimation, */
+ /* store only one sample out of 4. */
+ temps[it] = oversample_buffer[it][0] * state->attenuation;
+ }
+
+ for(kt = 0;kt < MaxChannels;kt++)
+ {
+ ALfloat gain = state->Gain[kt];
+ if(!(gain > 0.00001f))
+ continue;
+
+ for(it = 0;it < td;it++)
+ SamplesOut[kt][base+it] += gain * temps[it];
+ }
+
+ base += td;
}
}
diff --git a/Alc/alcEcho.c b/Alc/alcEcho.c
index 1d06e68a..498ebbc7 100644
--- a/Alc/alcEcho.c
+++ b/Alc/alcEcho.c
@@ -133,25 +133,47 @@ static ALvoid EchoProcess(ALeffectState *effect, ALuint SamplesToDo, const ALflo
const ALuint tap2 = state->Tap[1].delay;
ALuint offset = state->Offset;
ALfloat smp;
+ ALuint base;
ALuint i, k;
- for(i = 0;i < SamplesToDo;i++,offset++)
+ for(base = 0;base < SamplesToDo;)
{
- /* First tap */
- smp = state->SampleBuffer[(offset-tap1) & mask];
- for(k = 0;k < MaxChannels;k++)
- SamplesOut[k][i] += smp * state->Gain[0][k];
+ ALfloat temps[64][2];
+ ALuint td = minu(SamplesToDo-base, 64);
+
+ for(i = 0;i < td;i++)
+ {
+ /* First tap */
+ temps[i][0] = state->SampleBuffer[(offset-tap1) & mask];
+ /* Second tap */
+ temps[i][1] = state->SampleBuffer[(offset-tap2) & mask];
+
+ // Apply damping and feedback gain to the second tap, and mix in the
+ // new sample
+ smp = lpFilter2P(&state->iirFilter, 0, temps[i][1]+SamplesIn[i]);
+ state->SampleBuffer[offset&mask] = smp * state->FeedGain;
+ }
- /* Second tap */
- smp = state->SampleBuffer[(offset-tap2) & mask];
for(k = 0;k < MaxChannels;k++)
- SamplesOut[k][i] += smp * state->Gain[1][k];
-
- // Apply damping and feedback gain to the second tap, and mix in the
- // new sample
- smp = lpFilter2P(&state->iirFilter, 0, smp+SamplesIn[i]);
- state->SampleBuffer[offset&mask] = smp * state->FeedGain;
+ {
+ ALfloat gain = state->Gain[0][k];
+ if(gain > 0.00001f)
+ {
+ for(i = 0;i < td;i++)
+ SamplesOut[k][i+base] += temps[i][0] * gain;
+ }
+
+ gain = state->Gain[1][k];
+ if(gain > 0.00001f)
+ {
+ for(i = 0;i < td;i++)
+ SamplesOut[k][i+base] += temps[i][1] * gain;
+ }
+ }
+
+ base += td;
}
+
state->Offset = offset;
}
diff --git a/Alc/alcEqualizer.c b/Alc/alcEqualizer.c
index c10eba2a..d4b4f855 100644
--- a/Alc/alcEqualizer.c
+++ b/Alc/alcEqualizer.c
@@ -162,20 +162,24 @@ static ALvoid EqualizerUpdate(ALeffectState *effect, ALCdevice *Device, const AL
switch(state->bandfilter[it].type)
{
case LOW_SHELF:
- alpha = sinf(w0) / 2.0f *
- sqrtf((gain + 1.0f / gain) * (1.0f / 0.75f - 1.0f) + 2.0f);
+ alpha = sinf(w0) / 2.0f * sqrtf((gain + 1.0f / gain) *
+ (1.0f / 0.75f - 1.0f) + 2.0f);
state->bandfilter[it].b[0] = gain * ((gain + 1.0f) -
- (gain - 1.0f) * cosf(w0) + 2.0f * sqrtf(gain) * alpha);
+ (gain - 1.0f) * cosf(w0) +
+ 2.0f * sqrtf(gain) * alpha);
state->bandfilter[it].b[1] = 2.0f * gain * ((gain - 1.0f) -
- (gain + 1.0f) * cosf(w0));
+ (gain + 1.0f) * cosf(w0));
state->bandfilter[it].b[2] = gain * ((gain + 1.0f) -
- (gain - 1.0f) * cosf(w0) - 2.0f * sqrtf(gain) * alpha);
- state->bandfilter[it].a[0] = (gain + 1.0f) + (gain - 1.0f) *
- cosf(w0) + 2.0f * sqrtf(gain) * alpha;
+ (gain - 1.0f) * cosf(w0) -
+ 2.0f * sqrtf(gain) * alpha);
+ state->bandfilter[it].a[0] = (gain + 1.0f) +
+ (gain - 1.0f) * cosf(w0) +
+ 2.0f * sqrtf(gain) * alpha;
state->bandfilter[it].a[1] = -2.0f * ((gain - 1.0f) +
- (gain + 1.0f) * cosf(w0));
- state->bandfilter[it].a[2] = (gain + 1.0f) + (gain - 1.0f) *
- cosf(w0) - 2.0f * sqrtf(gain) * alpha;
+ (gain + 1.0f) * cosf(w0));
+ state->bandfilter[it].a[2] = (gain + 1.0f) +
+ (gain - 1.0f) * cosf(w0) -
+ 2.0f * sqrtf(gain) * alpha;
break;
case HIGH_SHELF:
alpha = sinf(w0) / 2.0f * sqrtf((gain + 1.0f / gain) *
@@ -214,32 +218,52 @@ static ALvoid EqualizerUpdate(ALeffectState *effect, ALCdevice *Device, const AL
static ALvoid EqualizerProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
{
ALequalizerState *state = GET_PARENT_TYPE(ALequalizerState, ALeffectState, effect);
+ ALuint base;
ALuint it;
ALuint kt;
ALuint ft;
- for (it = 0; it < SamplesToDo; it++)
+ for(base = 0;base < SamplesToDo;)
{
- ALfloat tempsmp;
- ALfloat smp = SamplesIn[it];
+ ALfloat temps[64];
+ ALuint td = minu(SamplesToDo-base, 64);
- for(ft = 0;ft < 4;ft++)
+ for(it = 0;it < td;it++)
{
- tempsmp = state->bandfilter[ft].b[0] / state->bandfilter[ft].a[0] * smp +
- state->bandfilter[ft].b[1] / state->bandfilter[ft].a[0] * state->bandfilter[ft].x[0] +
- state->bandfilter[ft].b[2] / state->bandfilter[ft].a[0] * state->bandfilter[ft].x[1] -
- state->bandfilter[ft].a[1] / state->bandfilter[ft].a[0] * state->bandfilter[ft].y[0] -
- state->bandfilter[ft].a[2] / state->bandfilter[ft].a[0] * state->bandfilter[ft].y[1];
-
- state->bandfilter[ft].x[1] = state->bandfilter[ft].x[0];
- state->bandfilter[ft].x[0] = smp;
- state->bandfilter[ft].y[1] = state->bandfilter[ft].y[0];
- state->bandfilter[ft].y[0] = tempsmp;
- smp = tempsmp;
+ ALfloat smp = SamplesIn[base+it];
+ ALfloat tempsmp;
+
+ for(ft = 0;ft < 4;ft++)
+ {
+ ALEQFilter *filter = &state->bandfilter[ft];
+
+ tempsmp = filter->b[0] / filter->a[0] * smp +
+ filter->b[1] / filter->a[0] * filter->x[0] +
+ filter->b[2] / filter->a[0] * filter->x[1] -
+ filter->a[1] / filter->a[0] * filter->y[0] -
+ filter->a[2] / filter->a[0] * filter->y[1];
+
+ filter->x[1] = filter->x[0];
+ filter->x[0] = smp;
+ filter->y[1] = filter->y[0];
+ filter->y[0] = tempsmp;
+ smp = tempsmp;
+ }
+
+ temps[it] = smp;
}
for(kt = 0;kt < MaxChannels;kt++)
- SamplesOut[kt][it] += state->Gain[kt] * smp;
+ {
+ ALfloat gain = state->Gain[kt];
+ if(!(gain > 0.00001f))
+ continue;
+
+ for(it = 0;it < td;it++)
+ SamplesOut[kt][base+it] += gain * temps[it];
+ }
+
+ base += td;
}
}
diff --git a/Alc/alcModulator.c b/Alc/alcModulator.c
index d33811ba..c9f1edf4 100644
--- a/Alc/alcModulator.c
+++ b/Alc/alcModulator.c
@@ -88,20 +88,36 @@ static void Process##func(ALmodulatorState *state, ALuint SamplesToDo, \
{ \
const ALuint step = state->step; \
ALuint index = state->index; \
- ALfloat samp; \
- ALuint i, k; \
+ ALuint base; \
\
- for(i = 0;i < SamplesToDo;i++) \
+ for(base = 0;base < SamplesToDo;) \
{ \
- samp = SamplesIn[i]; \
- samp = hpFilter1P(&state->iirFilter, 0, samp); \
+ ALfloat temps[64]; \
+ ALuint td = minu(SamplesToDo-base, 64); \
+ ALuint i, k; \
\
- index += step; \
- index &= WAVEFORM_FRACMASK; \
- samp *= func(index); \
+ for(i = 0;i < td;i++) \
+ { \
+ ALfloat samp; \
+ samp = SamplesIn[base+i]; \
+ samp = hpFilter1P(&state->iirFilter, 0, samp); \
+ \
+ index += step; \
+ index &= WAVEFORM_FRACMASK; \
+ temps[i] = samp * func(index); \
+ } \
\
for(k = 0;k < MaxChannels;k++) \
- SamplesOut[k][i] += state->Gain[k] * samp; \
+ { \
+ ALfloat gain = state->Gain[k]; \
+ if(!(gain > 0.00001f)) \
+ continue; \
+ \
+ for(i = 0;i < td;i++) \
+ SamplesOut[k][base+i] += gain * temps[i]; \
+ } \
+ \
+ base += td; \
} \
state->index = index; \
}