/* * * postfish * * Copyright (C) 2002-2005 Monty and Xiph.Org * * Postfish 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, or (at your option) * any later version. * * Postfish 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ /* arbitrary reconstruction filter. Postfish uses this for declipping. Many thanks to Johnathan Richard Shewchuk and his excellent paper 'An Introduction to the Conjugate Gradient Method Without the Agonizing Pain' for the additional understanding needed to make the n^3 -> n^2 log n jump possible. Google for it, you'll find it. */ #include #include #include #include "reconstruct.h" /* fftw3 requires this kind of static setup */ static fftwf_plan fftwf_qf; static fftwf_plan fftwf_qb; static fftwf_plan fftwf_sf; static fftwf_plan fftwf_sb; static float *q; static float *s; static int blocksize=0; void reconstruct_init(int minblock,int maxblock){ int i; q=fftwf_malloc((maxblock+2)*sizeof(*q)); s=fftwf_malloc((maxblock+2)*sizeof(*s)); /* fftw priming trick; run it thorugh the paces and prime a plan for every size we may need. fftw will cache the information and not need to re-measure later */ for(i=minblock;i<=maxblock;i<<=1){ fftwf_qf=fftwf_plan_dft_r2c_1d(i,q,(fftwf_complex *)q,FFTW_MEASURE); fftwf_qb=fftwf_plan_dft_c2r_1d(i,(fftwf_complex *)q,q,FFTW_MEASURE); fftwf_destroy_plan(fftwf_qf); fftwf_destroy_plan(fftwf_qb); } } void reconstruct_reinit(int n){ if(blocksize!=n){ if(blocksize){ fftwf_destroy_plan(fftwf_qf); fftwf_destroy_plan(fftwf_qb); fftwf_destroy_plan(fftwf_sf); fftwf_destroy_plan(fftwf_sb); fftwf_free(q); fftwf_free(s); } blocksize=n; q=fftwf_malloc((n+2)*sizeof(*q)); s=fftwf_malloc((n+2)*sizeof(*s)); fftwf_qf=fftwf_plan_dft_r2c_1d(n,q,(fftwf_complex *)q,FFTW_MEASURE); fftwf_qb=fftwf_plan_dft_c2r_1d(n,(fftwf_complex *)q,q,FFTW_MEASURE); fftwf_sf=fftwf_plan_dft_r2c_1d(n,s,(fftwf_complex *)s,FFTW_MEASURE); fftwf_sb=fftwf_plan_dft_c2r_1d(n,(fftwf_complex *)s,s,FFTW_MEASURE); } } static void AtWA(float *w,int n){ int i; fftwf_execute(fftwf_qf); for(i=0;ie;i++){ AtWA(w,n); alpha=phi_new/inner_product(d,q,n); for(j=0;j