📄 hxeqengine.c
字号:
eq->echoPtr[i] = eq->eqhist; for (chan = 0; chan < EQ_MAXCHANS; chan++) { eq->echoFiltState[chan][i] = 0.0f; } } eq->gain = 0.0f; eq->reverb = 0; eq->roomsize = 0; eq->timer = 0L; eq->echoFiltCoeff = echoFiltCoeff_tab[ratecode];#ifdef _EQ_X86_WINDOWS // Initialize the limiter eq->limState = LimiterInit(samprate, nchans, EQ_FIXED_HEADROOM_BITS); init_codecutil();#endif return eq;}static voidAddReverb(EQPTR eq, short *inpcm, int nsamps){ // apply reverb int echo; // the current echo number being processed int chan; // the current chan being processed int samps; // samps processed between echo pointer shifts float *fhistPtr; // working pointer into the eq->eqhist buffer short *inpcmPtr; // working pointer to the input pcm data int bufflength; // length of the eq->eqhist buffer float *loop_echoPtr[REVERB_NUM_ECHOS]; float loop_eFiltState[EQ_MAXCHANS][REVERB_NUM_ECHOS]; register float fres; // storage for new reverb'ed samples register float ftmp; register float c = 1.0f - eq->echoFiltCoeff; register float loop_gain; register float *loop_eFiltStatePtr; eq->timer += nsamps * 1000 / (ratetab[eq->ratecode] * eq->nchans); bufflength = eq->eqhist_end-eq->eqhist; eq->eqhist_start = eq->eqhist_head; // convert input pcm to floats and fill history inpcmPtr = inpcm; fhistPtr = eq->eqhist_head; while (inpcmPtr < inpcm + nsamps) { *(eq->eqhist_head) = (float)(*inpcmPtr); inpcmPtr++; eq->eqhist_head++; if (eq->eqhist_head == eq->eqhist_end) eq->eqhist_head = eq->eqhist; } // fill the buffer extension if ((eq->eqhist_head <= eq->eqhist + EQ_MAXSAMPS * eq->nchans) || (eq->eqhist_start <= eq->eqhist + EQ_MAXSAMPS * eq->nchans)) { memcpy(eq->eqhist_end,eq->eqhist,EQ_MAXSAMPS * eq->nchans * sizeof(float)); } if (eq->reverb == 0) return; // add echos to the history loop_gain = eq->gain * eq->echoFiltCoeff; for (echo = 0; echo < REVERB_NUM_ECHOS; echo++) { loop_echoPtr[echo] = eq->echoPtr[echo]; for (chan = 0; chan < eq->nchans; chan++) { loop_eFiltState[chan][echo] = eq->echoFiltState[chan][echo]; } } samps = 1; nsamps /= REVERB_NUM_ECHOS; echo = 0; while (1) { loop_eFiltStatePtr = &(loop_eFiltState[0][0]); for (chan = 0; chan < eq->nchans; chan++) { fres = (*fhistPtr);#define PROCESS_ECHO_UP(e) \ ftmp = (loop_gain*(*(loop_echoPtr[(e)])++)) + c*loop_eFiltStatePtr[(e)]; \ loop_eFiltStatePtr[(e)] = ftmp; \ fres += ftmp#define PROCESS_ECHO_DOWN(e) \ ftmp = (loop_gain*(*(loop_echoPtr[(e)])++)) + c*loop_eFiltStatePtr[(e)]; \ loop_eFiltStatePtr[(e)] = ftmp; \ fres -= ftmp PROCESS_ECHO_UP(0); PROCESS_ECHO_DOWN(1); PROCESS_ECHO_UP(2); PROCESS_ECHO_DOWN(3); PROCESS_ECHO_UP(4); PROCESS_ECHO_DOWN(5); PROCESS_ECHO_UP(6); PROCESS_ECHO_DOWN(7); PROCESS_ECHO_UP(8); PROCESS_ECHO_DOWN(9); // remove mean from reverb eq->mean[chan] = (1.0f - 0.01f) * eq->mean[chan] + 0.01f * fres; fres -= eq->mean[chan]; *fhistPtr++ = fres; loop_eFiltStatePtr += REVERB_NUM_ECHOS; samps++; } if (fhistPtr >= eq->eqhist_end) fhistPtr -= bufflength; if (fhistPtr == eq->eqhist_head) break;#ifdef MOVE_FEEDBACK_DELAYS // Move echo pointers a little to prevent resonance effects // NOTE: This is currently not compiled in since, as implemented, // it seem to be causing some flanging effects. if (samps > nsamps) { (loop_echoPtr[echo]) += ((((int)(eq->timer) & 1023) < 512) ? (1 - 2 * (echo & 1)) : (2 * (echo & 1) - 1))*(eq->nchans); echo++; samps = 1; }#endif } // store the echo locations for (echo = 0; echo < REVERB_NUM_ECHOS; echo++) { if (loop_echoPtr[echo] >= eq->eqhist_end) eq->echoPtr[echo] = loop_echoPtr[echo] - bufflength; else eq->echoPtr[echo] = loop_echoPtr[echo]; for (chan = 0; chan < eq->nchans; chan++) { eq->echoFiltState[chan][echo] = loop_eFiltState[chan][echo]; } } inpcmPtr = inpcm; fhistPtr = eq->eqhist_start;}/* * Process a single block of samples. * * Requires nsamps <= EQ_MAXSAMPS * nchans * Requires chan = 0 for mono, 0/1 for stereo. * * Returns the count of clipped outputs. */static voidProcessBlock(EQPTR eq, int nsamps, int chan){ float *iptr, *optr, *ihptr, *ohptr; const float *cptr; float *iptrend; float alpha, beta, gamma, accum; float ibuf1, ibuf2, obuf1, obuf2; float ftmp; int band, n; iptr = eq->iflt; optr = eq->oflt; cptr = eq->eqhist_start + chan; /* if stereo, de-interleave */ for (n = chan; n < nsamps; n += eq->nchans) { ftmp = *cptr; *iptr++ = ftmp; *optr++ = ftmp; cptr += eq->nchans; if (cptr >= eq->eqhist_end) cptr -= (eq->eqhist_end - eq->eqhist); } iptrend = iptr; /* one past last input */ /* add the filter output from each band */ cptr = eq->coeff; ihptr = eq->ihist[chan]; ohptr = eq->ohist[chan]; for (band = 0; band < eq->nbands; band++) { /* load band filter coeffs */ alpha = cptr[0] * eq->filtgain[band]; /* premult filtgain into alpha */ gamma = cptr[1]; beta = cptr[2]; cptr += 3; /* fast-path zero-gain case */ if (eq->filtgain[band] > 0.25f || eq->filtgain[band] < -0.25f) { /* restore band history */ ibuf2 = ihptr[0]; /* iptr[-2] */ ibuf1 = ihptr[1]; /* iptr[-1] */ obuf2 = ohptr[0]; /* optr[-2] */ obuf1 = ohptr[1]; /* optr[-1] */ /* * The following code is an optimized implementation of: * y[n] = alpha * (x[n] - x[n-2]) + beta * y[n-2] + gamma * y[n-1]; * out[n] += y[n]; */ iptr = eq->iflt; optr = eq->oflt; accum = obuf1; /* filter, unrolled by 4 */ for (; iptr < iptrend-3; ) { accum *= gamma; /* gamma * y[n-1] */ accum += (iptr[0] - ibuf2) * alpha; /* alpha * (x[n] - x[n-2]) */ ibuf2 = iptr[0]; /* flip ibuf */ accum += obuf2 * beta; /* beta * y[n-2] */ optr[0] += accum; /* out[n] += y[n] */ obuf2 = accum; /* flip obuf */ accum *= gamma; accum += (iptr[1] - ibuf1) * alpha; ibuf1 = iptr[1]; accum += obuf1 * beta; optr[1] += accum; obuf1 = accum; accum *= gamma; accum += (iptr[2] - ibuf2) * alpha; ibuf2 = iptr[2]; accum += obuf2 * beta; optr[2] += accum; obuf2 = accum; accum *= gamma; accum += (iptr[3] - ibuf1) * alpha; ibuf1 = iptr[3]; accum += obuf1 * beta; optr[3] += accum; obuf1 = accum; iptr += 4; optr += 4; } /* filter the remainder */ for (; iptr < iptrend; ) { accum *= gamma; /* gamma * y[n-1] */ accum += (*iptr - ibuf2) * alpha; /* alpha * (x[n] - x[n-2]) */ ibuf2 = ibuf1; /* shift ibuf */ ibuf1 = *iptr++; /* shift ibuf */ accum += obuf2 * beta; /* beta * y[n-2] */ obuf2 = obuf1; /* shift obuf */ obuf1 = accum; /* shift obuf */ *optr++ += accum; /* out[n] += y[n] */ } /* save band output history */ ohptr[0] = obuf2; ohptr[1] = obuf1; ohptr += 2; } else { /* save band output history */ ohptr[0] = 0; ohptr[1] = 0; ohptr += 2; ibuf2 = iptrend[-2]; /* iptr[-2] */ ibuf1 = iptrend[-1]; /* iptr[-1] */ } } /* save input history */ ihptr[0] = ibuf2; ihptr[1] = ibuf1; /* Re-interleave samples */ iptr = eq->oflt; optr = eq->itlbuf + chan; for (n = chan; n < nsamps; n += eq->nchans) { *optr = *iptr++; optr += eq->nchans; }}#ifdef _EQ_X86_WINDOWS#define PWR_NOISE_THRESH (512.f*512.f)#define PWR_LOW_THRESH (4096.f*4096.f)#define PWR_HIGH_THRESH (8192.f*8192.f*2.f)voidApplyGain(EQPTR eq, int nsamps){ int n, chan, settings_change = 0; float *optr; float pwr, chan_pwr[EQ_MAXCHANS]; float prev_pregain, ftmp; if (eq->autopregain == 0) { if (eq->pregain < 0.90 || eq->pregain > 1.1) { /* Apply fixed pregain */ optr = eq->itlbuf; for (n = 0; n < nsamps; n++) { ftmp = *optr; ftmp *= eq->pregain; *optr = ftmp; optr ++; } } } else { prev_pregain = eq->pregain; /* measure the power in each channel */ for (chan = 0; chan < eq->nchans; chan++) { pwr = 0; optr = eq->itlbuf + chan; for (n = 0; n < nsamps; n += eq->nchans) { ftmp = *optr; ftmp *= prev_pregain; ftmp *= ftmp; pwr += ftmp; optr += eq->nchans; } chan_pwr[chan] = pwr/(float)(nsamps/eq->nchans); } /* find the largest power in all channels */ pwr = 0; for (chan = 0; chan < eq->nchans; chan++) { if (chan_pwr[chan] > pwr) pwr = chan_pwr[chan]; } if (pwr > PWR_NOISE_THRESH) { if (pwr > eq->pwrLevelMeasure) eq->pwrLevelMeasure = (1.0f - 0.1f) * eq->pwrLevelMeasure + (0.1f) * pwr; else eq->pwrLevelMeasure = (1.0f - 0.01f) * eq->pwrLevelMeasure + (0.01f) * pwr; /* now adjust desired pregain given the pwr */ if (eq->pwrLevelMeasure < PWR_LOW_THRESH) { eq->pregain *= 1.001f; } else if (eq->pwrLevelMeasure > PWR_HIGH_THRESH) { eq->pregain *= 0.99f; } /* bound the pregain to +/-18 dB */ if (eq->pregain > powertab[EQ_MAXGAIN-EQ_MINGAIN]) eq->pregain = powertab[EQ_MAXGAIN-EQ_MINGAIN]; else if (eq->pregain < powertab[0]) eq->pregain = powertab[0]; eq->pwrLevelMeasure *= (eq->pregain/prev_pregain); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -