/* * PCM time-domain equalizer * * Copyright (C) 2002-2006 Felipe Rivera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: iir_sse.c,v 1.7 2006/01/15 00:26:32 liebremx Exp $ */ #include #include "iir.h" #include "iir_sse.h" #ifdef BENCHMARK #include #include "benchmark.h" #endif /* Volume gain * values should be between 0.0 and 1.0 * Use the preamp from XMMS for now * */ /* Gain for each band * values should be between -0.2 and 1.0 */ union f4vector gain[MAX_SSE_VECTORS][EQ_CHANNELS]; static sSupport support; static sHistory history[EQ_CHANNELS]; static sPtrs ptrs; static int sse_loop_num; static void setup_gain(int count_start); static void load_coeffs(int bands); void set_gain(int index, int chn, float val) { gain[index/4][chn].f[index%4] = val; } void clean_history() { int i; sse_loop_num = ceil((float)band_count/4.); load_coeffs(band_count); setup_gain(band_count); /* Zero the history arrays */ memset(history, 0, sizeof(history)); /* Init pointers */ for (i=0; if[3] = data[index+channel]; ptrs.p_sse_X_n[channel]->f[3] *= preamp[channel]; ptrs.p_sse_X_n[channel]->f[0] = ptrs.p_sse_X_n[channel]->f[1] = ptrs.p_sse_X_n[channel]->f[2] = ptrs.p_sse_X_n[channel]->f[3]; /* For each band */ for (band = 0; band < sse_loop_num; band++) { ptrs.p_sse_Y_n[channel][band].v = (ptrs.p_sse_X_n[channel]->v-ptrs.p_sse_X_n2[channel]->v) * support.sse_iir_cf_alpha[band].v + ptrs.p_sse_Y_n1[channel][band].v * support.sse_iir_cf_gamma[band].v - ptrs.p_sse_Y_n2[channel][band].v * support.sse_iir_cf_beta[band].v; support.sse_acc.v += ptrs.p_sse_Y_n[channel][band].v*gain[band][channel].v; } /* For each band */ support.sse_acc.v = support.sse_acc.v + support.sse_acc.v; if (extra_filtering) { ptrs.p_sse_X2_n[channel]->f[0] = ptrs.p_sse_X2_n[channel]->f[1] = ptrs.p_sse_X2_n[channel]->f[2] = ptrs.p_sse_X2_n[channel]->f[3] = support.sse_acc.f[0] + support.sse_acc.f[1] + support.sse_acc.f[2] + support.sse_acc.f[3]; for (band = 0; band < sse_loop_num; band++) { ptrs.p_sse_Y2_n[channel][band].v = (ptrs.p_sse_X2_n[channel]->v-ptrs.p_sse_X2_n2[channel]->v) * support.sse_iir_cf_alpha[band].v + ptrs.p_sse_Y2_n1[channel][band].v * support.sse_iir_cf_gamma[band].v - ptrs.p_sse_Y2_n2[channel][band].v * support.sse_iir_cf_beta[band].v; support.sse_acc.v += ptrs.p_sse_Y2_n[channel][band].v*gain[band][channel].v; } /* For each band */ } /* Round and convert to integer */ tempint = support.sse_acc.f[0] + support.sse_acc.f[1] + support.sse_acc.f[2] + support.sse_acc.f[3] + ptrs.p_sse_X_n[channel]->f[0]*0.25; /* Limit the output */ if (tempint < -32768) data[index+channel] = -32768; else if (tempint > 32767) data[index+channel] = 32767; else data[index+channel] = tempint; ptrs.p_sse_tmp = ptrs.p_sse_Y_n2[channel]; ptrs.p_sse_Y_n2[channel] = ptrs.p_sse_Y_n1[channel]; ptrs.p_sse_Y_n1[channel] = ptrs.p_sse_Y_n[channel]; ptrs.p_sse_Y_n[channel] = ptrs.p_sse_tmp; ptrs.p_sse_tmp = ptrs.p_sse_X_n2[channel]; ptrs.p_sse_X_n2[channel] = ptrs.p_sse_X_n1[channel]; ptrs.p_sse_X_n1[channel] = ptrs.p_sse_X_n[channel]; ptrs.p_sse_X_n[channel] = ptrs.p_sse_tmp; ptrs.p_sse_tmp = ptrs.p_sse_Y2_n2[channel]; ptrs.p_sse_Y2_n2[channel] = ptrs.p_sse_Y2_n1[channel]; ptrs.p_sse_Y2_n1[channel] = ptrs.p_sse_Y2_n[channel]; ptrs.p_sse_Y2_n[channel] = ptrs.p_sse_tmp; ptrs.p_sse_tmp = ptrs.p_sse_X2_n2[channel]; ptrs.p_sse_X2_n2[channel] = ptrs.p_sse_X2_n1[channel]; ptrs.p_sse_X2_n1[channel] = ptrs.p_sse_X2_n[channel]; ptrs.p_sse_X2_n[channel] = ptrs.p_sse_tmp; } }/* 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 */ /* Turn OFF Flush-to-zero mode to avoid exceptions on underflow */ FTZ_OFF; return length; }