diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2012-11-10 06:49:35 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2012-11-10 06:49:35 +0000 |
| commit | cd23fb43bec0151e62fa6b4590d62552c174ed54 (patch) | |
| tree | d5205f4e919f9623f21e0239ef369dcc7ff6acf1 | |
| parent | e0d01d34d9046c32d99868ee2a29dd8da2272ced (diff) | |
| download | qmmp-cd23fb43bec0151e62fa6b4590d62552c174ed54.tar.gz qmmp-cd23fb43bec0151e62fa6b4590d62552c174ed54.tar.bz2 qmmp-cd23fb43bec0151e62fa6b4590d62552c174ed54.zip | |
added 32-bit equalizer (Closes issue 552)
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@2972 90c681e8-e032-0410-971d-27865f9a5e38
| -rw-r--r-- | src/qmmp/equ/iir.h | 1 | ||||
| -rw-r--r-- | src/qmmp/equ/iir_fpu.c | 148 | ||||
| -rw-r--r-- | src/qmmp/output.cpp | 9 |
3 files changed, 156 insertions, 2 deletions
diff --git a/src/qmmp/equ/iir.h b/src/qmmp/equ/iir.h index a85dfc0bf..77a398414 100644 --- a/src/qmmp/equ/iir.h +++ b/src/qmmp/equ/iir.h @@ -58,6 +58,7 @@ void set_preamp(int chn, float val); int iir(void * d, int length, int nch); +int iir32(void * d, int length, int nch); #ifdef ARCH_X86 __inline__ int round_trick(float floatvalue_to_round); diff --git a/src/qmmp/equ/iir_fpu.c b/src/qmmp/equ/iir_fpu.c index 1d79b95a1..6740d3a88 100644 --- a/src/qmmp/equ/iir_fpu.c +++ b/src/qmmp/equ/iir_fpu.c @@ -205,3 +205,151 @@ __inline__ int iir(void * d, int length, int nch) // FTZ_OFF; return length; } + +__inline__ int iir32(void * d, int length, int nch) +{ +// FTZ_ON; + int *data = (int *) d; + /* Indexes for the history arrays + * These have to be kept between calls to this function + * hence they are static */ + static int i = 2, j = 1, k = 0; + + int index, band, channel; + int tempgint, quaterlength; + sample_t out[EQ_CHANNELS], pcm[EQ_CHANNELS]; + + // Load the correct filter table according to the sampling rate if needed + /*if (srate != rate) + { + band_count = eqcfg.band_num; + rate = srate; + iir_cf = get_coeffs(&band_count, rate, eqcfg.use_xmms_original_freqs); + clean_history(); + }*/ + +#ifdef BENCHMARK + start_counter(); +#endif //BENCHMARK + + /** + * IIR filter equation is + * y[n] = 2 * (alpha*(x[n]-x[n-2]) + gamma*y[n-1] - beta*y[n-2]) + * + * NOTE: The 2 factor was introduced in the coefficients to save + * a multiplication + * + * This algorithm cascades two filters to get nice filtering + * at the expense of extra CPU cycles + */ + /* 32bit, 4 bytes per sample, so divide by four the length of + * the buffer (length is in bytes) + */ + quaterlength = (length >> 2); + for (index = 0; index < quaterlength; index+=nch) + { + /* For each channel */ + for (channel = 0; channel < nch; channel++) + { + pcm[channel] = data[index+channel]; + /* Preamp gain */ + pcm[channel] *= preamp[channel]; + + /* add random noise */ + pcm[channel] += dither[di]; + + out[channel] = 0.; + /* For each band */ + for (band = 0; band < band_count; band++) + { + /* Store Xi(n) */ + data_history[band][channel].x[i] = pcm[channel]; + /* Calculate and store Yi(n) */ + data_history[band][channel].y[i] = + ( + /* = alpha * [x(n)-x(n-2)] */ + iir_cf[band].alpha * ( data_history[band][channel].x[i] + - data_history[band][channel].x[k]) + /* + gamma * y(n-1) */ + + iir_cf[band].gamma * data_history[band][channel].y[j] + /* - beta * y(n-2) */ + - iir_cf[band].beta * data_history[band][channel].y[k] + ); + /* + * The multiplication by 2.0 was 'moved' into the coefficients to save + * CPU cycles here */ + /* Apply the gain */ + out[channel] += data_history[band][channel].y[i]*gain[band][channel]; // * 2.0; + } /* For each band */ + + //if (eqcfg.extra_filtering) + { + /* Filter the sample again */ + for (band = 0; band < band_count; band++) + { + /* Store Xi(n) */ + data_history2[band][channel].x[i] = out[channel]; + /* Calculate and store Yi(n) */ + data_history2[band][channel].y[i] = + ( + /* y(n) = alpha * [x(n)-x(n-2)] */ + iir_cf[band].alpha * (data_history2[band][channel].x[i] + - data_history2[band][channel].x[k]) + /* + gamma * y(n-1) */ + + iir_cf[band].gamma * data_history2[band][channel].y[j] + /* - beta * y(n-2) */ + - iir_cf[band].beta * data_history2[band][channel].y[k] + ); + /* Apply the gain */ + out[channel] += data_history2[band][channel].y[i]*gain[band][channel]; + } /* For each band */ + } + + /* Volume stuff + Scale down original PCM sample and add it to the filters + output. This substitutes the multiplication by 0.25 + Go back to use the floating point multiplication before the + conversion to give more dynamic range + */ + out[channel] += pcm[channel]*0.25; + + /* remove random noise */ + out[channel] -= dither[di]*0.25; + + /* Round and convert to integer */ +#ifdef ARCH_PPC + tempgint = round_ppc(out[channel]); +#else +#ifdef ARCH_X86 + tempgint = round_trick(out[channel]); +#else + tempgint = (int)out[channel]; +#endif +#endif + data[index+channel] = tempgint; + } /* For each channel */ + + /* Wrap around the indexes */ + i = (i+1)%3; + j = (j+1)%3; + k = (k+1)%3; + /* random noise index */ + di = (di + 1) % 256; + + }/* For each pair of samples */ + +#ifdef BENCHMARK + timex += get_counter(); + blength += length; + if (count++ == 1024) + { + printf("FLOATING POINT: %f %d\n",timex/1024.0, blength/1024); + blength = 0; + timex = 0.; + count = 0; + } +#endif // BENCHMARK + +// FTZ_OFF; + return length; +} diff --git a/src/qmmp/output.cpp b/src/qmmp/output.cpp index 84f51610b..876d5a652 100644 --- a/src/qmmp/output.cpp +++ b/src/qmmp/output.cpp @@ -309,7 +309,12 @@ void Output::run() if (b) { if (m_useEq) - iir((void*) b->data, b->nbytes, m_channels); + { + if(m_format == Qmmp::PCM_S16LE) + iir((void*) b->data, b->nbytes, m_channels); + else if(m_format == Qmmp::PCM_S32LE || m_format == Qmmp::PCM_S24LE) + iir32((void*) b->data, b->nbytes, m_channels); + } dispatchVisual(b); if (SoftwareVolume::instance()) SoftwareVolume::instance()->changeVolume(b, m_channels, m_format); @@ -394,7 +399,7 @@ void Output::updateEqSettings() set_gain(i,1, 0.03*value+0.000999999*value*value); } if(isRunning()) - m_useEq = m_eqEnabled && m_format == Qmmp::PCM_S16LE; + m_useEq = m_eqEnabled;// && m_format == Qmmp::PCM_S16LE; mutex()->unlock(); } |
