MythTV  0.26-pre
el_processor.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2007 Christian Kothe
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00017 */
00018 
00019 #include "el_processor.h"
00020 #include <cstdlib>
00021 #include <cstring>
00022 #include <complex>
00023 #include <cmath>
00024 #include <vector>
00025 #ifdef USE_FFTW3
00026 #include "fftw3.h"
00027 #else
00028 extern "C" {
00029 #include "libavcodec/avfft.h"
00030 #include "libavcodec/fft.h"
00031 }
00032 typedef FFTSample FFTComplexArray[2];
00033 #endif
00034 
00035 
00036 #ifdef USE_FFTW3
00037 #pragma comment (lib,"libfftw3f-3.lib")
00038 #endif
00039 
00040 typedef std::complex<float> cfloat;
00041 
00042 static const float PI = 3.141592654;
00043 static const float epsilon = 0.000001;
00044 static const float center_level = 0.5*sqrt(0.5);
00045 
00046 // private implementation of the surround decoder
00047 class decoder_impl {
00048 public:
00049     // create an instance of the decoder
00050     //  blocksize is fixed over the lifetime of this object for performance reasons
00051     decoder_impl(unsigned blocksize=8192): N(blocksize), halfN(blocksize/2) {
00052 #ifdef USE_FFTW3
00053         // create FFTW buffers
00054         lt = (float*)fftwf_malloc(sizeof(float)*N);
00055         rt = (float*)fftwf_malloc(sizeof(float)*N);
00056         dst = (float*)fftwf_malloc(sizeof(float)*N);
00057         dftL = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*N);
00058         dftR = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*N);
00059         src = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*N);
00060         loadL = fftwf_plan_dft_r2c_1d(N, lt, dftL,FFTW_MEASURE);
00061         loadR = fftwf_plan_dft_r2c_1d(N, rt, dftR,FFTW_MEASURE);
00062         store = fftwf_plan_dft_c2r_1d(N, src, dst,FFTW_MEASURE);    
00063 #else
00064         // create lavc fft buffers
00065         lt = (float*)av_malloc(sizeof(FFTSample)*N);
00066         rt = (float*)av_malloc(sizeof(FFTSample)*N);
00067         dftL = (FFTComplexArray*)av_malloc(sizeof(FFTComplex)*N*2);
00068         dftR = (FFTComplexArray*)av_malloc(sizeof(FFTComplex)*N*2);
00069         src = (FFTComplexArray*)av_malloc(sizeof(FFTComplex)*N*2);
00070         fftContextForward = (FFTContext*)av_malloc(sizeof(FFTContext));
00071         memset(fftContextForward, 0, sizeof(FFTContext));
00072         fftContextReverse = (FFTContext*)av_malloc(sizeof(FFTContext));
00073         memset(fftContextReverse, 0, sizeof(FFTContext));
00074         ff_fft_init(fftContextForward, 13, 0);
00075         ff_fft_init(fftContextReverse, 13, 1);
00076 #endif
00077         // resize our own buffers
00078         frontR.resize(N);
00079         frontL.resize(N);
00080         avg.resize(N);
00081         surR.resize(N);
00082         surL.resize(N);
00083         trueavg.resize(N);
00084         xfs.resize(N);
00085         yfs.resize(N);
00086         inbuf[0].resize(N);
00087         inbuf[1].resize(N);
00088         for (unsigned c=0;c<6;c++) {
00089             outbuf[c].resize(N);
00090             filter[c].resize(N);
00091         }
00092         sample_rate(48000);
00093         // generate the window function (square root of hann, b/c it is applied before and after the transform)
00094         wnd.resize(N);
00095         for (unsigned k=0;k<N;k++)
00096             wnd[k] = sqrt(0.5*(1-cos(2*PI*k/N))/N);
00097         current_buf = 0;
00098         memset(inbufs, 0, sizeof(inbufs));
00099         memset(outbufs, 0, sizeof(outbufs));
00100         // set the default coefficients
00101         surround_coefficients(0.8165,0.5774);
00102         phase_mode(0);
00103         separation(1,1);
00104         steering_mode(1);
00105     }
00106 
00107     // destructor
00108     ~decoder_impl() {
00109 #ifdef USE_FFTW3
00110         // clean up the FFTW stuff
00111         fftwf_destroy_plan(store);
00112         fftwf_destroy_plan(loadR);
00113         fftwf_destroy_plan(loadL);
00114         fftwf_free(src); 
00115         fftwf_free(dftR);
00116         fftwf_free(dftL);
00117         fftwf_free(dst);
00118         fftwf_free(rt);
00119         fftwf_free(lt);
00120 #else
00121         ff_fft_end(fftContextForward);
00122         ff_fft_end(fftContextReverse);
00123         av_free(src); 
00124         av_free(dftR);
00125         av_free(dftL);
00126         av_free(rt);
00127         av_free(lt);
00128         av_free(fftContextForward); 
00129         av_free(fftContextReverse); 
00130 #endif
00131     }
00132 
00133     float ** getInputBuffers()
00134     {
00135         inbufs[0] = &inbuf[0][current_buf*halfN];
00136         inbufs[1] = &inbuf[1][current_buf*halfN];
00137         return inbufs;
00138     }
00139 
00140     float ** getOutputBuffers()
00141     {
00142         outbufs[0] = &outbuf[0][current_buf*halfN];
00143         outbufs[1] = &outbuf[1][current_buf*halfN];
00144         outbufs[2] = &outbuf[2][current_buf*halfN];
00145         outbufs[3] = &outbuf[3][current_buf*halfN];
00146         outbufs[4] = &outbuf[4][current_buf*halfN];
00147         outbufs[5] = &outbuf[5][current_buf*halfN];
00148         return outbufs;
00149     }
00150 
00151     // decode a chunk of stereo sound, has to contain exactly blocksize samples
00152     //  center_width [0..1] distributes the center information towards the front left/right channels, 1=full distribution, 0=no distribution
00153     //  dimension [0..1] moves the soundfield backwards, 0=front, 1=side
00154     //  adaption_rate [0..1] determines how fast the steering gets adapted, 1=instantaneous, 0.1 = very slow adaption
00155     void decode(float center_width, float dimension, float adaption_rate) {
00156         // process first part
00157         int index;
00158         index = current_buf*halfN;
00159         float *in_second[2] = {&inbuf[0][index],&inbuf[1][index]};
00160         current_buf ^= 1;
00161         index = current_buf*halfN;
00162         float *in_first[2] = {&inbuf[0][index],&inbuf[1][index]};
00163         add_output(in_first,in_second,center_width,dimension,adaption_rate,true);
00164         // shift last half of input buffer to the beginning
00165     }
00166     
00167     // flush the internal buffers
00168     void flush() {
00169         for (unsigned k=0;k<N;k++) {
00170             for (unsigned c=0;c<6;c++)
00171                 outbuf[c][k] = 0;
00172             inbuf[0][k] = 0;
00173             inbuf[1][k] = 0;
00174         }
00175     }
00176 
00177     // set lfe filter params
00178     void sample_rate(unsigned int srate) {
00179         // lfe filter is just straight through band limited
00180         unsigned int cutoff = (30*N)/srate;
00181         for (unsigned f=0;f<=halfN;f++) {           
00182             if (f<cutoff)
00183                 filter[5][f] = 0.5*sqrt(0.5);
00184             else
00185                 filter[5][f] = 0.0;
00186         }
00187     }
00188 
00189     // set the assumed surround mixing coefficients
00190     void surround_coefficients(float a, float b) {
00191         // calc the simple coefficients
00192         surround_high = a;
00193         surround_low = b;
00194         surround_balance = (a-b)/(a+b);
00195         surround_level = 1/(a+b);
00196         // calc the linear coefficients
00197         cfloat i(0,1), u((a+b)*i), v((b-a)*i), n(0.25,0),o(1,0);
00198         A = (v-o)*n; B = (o-u)*n; C = (-o-v)*n; D = (o+u)*n;
00199         E = (o+v)*n; F = (o+u)*n; G = (o-v)*n;  H = (o-u)*n;
00200     }
00201 
00202     // set the phase shifting mode
00203     void phase_mode(unsigned mode) {
00204         const float modes[4][2] = {{0,0},{0,PI},{PI,0},{-PI/2,PI/2}};
00205         phase_offsetL = modes[mode][0];
00206         phase_offsetR = modes[mode][1];
00207     }
00208 
00209     // what steering mode should be chosen
00210     void steering_mode(bool mode) { linear_steering = mode; }
00211 
00212     // set front & rear separation controls
00213     void separation(float front, float rear) {
00214         front_separation = front;
00215         rear_separation = rear;
00216     }
00217 
00218 private:
00219     // polar <-> cartesian coodinates conversion
00220     static inline float amplitude(const float cf[2]) { return sqrt(cf[0]*cf[0] + cf[1]*cf[1]); }
00221     static inline float phase(const float cf[2]) { return atan2(cf[1],cf[0]); }
00222     static inline cfloat polar(float a, float p) { return cfloat(a*cos(p),a*sin(p)); }
00223     static inline float sqr(float x) { return x*x; }
00224     // the dreaded min/max
00225     static inline float min(float a, float b) { return a<b?a:b; }
00226     static inline float max(float a, float b) { return a>b?a:b; }
00227     static inline float clamp(float x) { return max(-1,min(1,x)); }
00228 
00229     // handle the output buffering for overlapped calls of block_decode
00230     void add_output(float *input1[2], float *input2[2], float center_width, float dimension, float adaption_rate, bool result=false) {
00231         // add the windowed data to the last 1/2 of the output buffer
00232         float *out[6] = {&outbuf[0][0],&outbuf[1][0],&outbuf[2][0],&outbuf[3][0],&outbuf[4][0],&outbuf[5][0]};
00233         block_decode(input1,input2,out,center_width,dimension,adaption_rate);
00234     }
00235 
00236     // CORE FUNCTION: decode a block of data
00237     void block_decode(float *input1[2], float *input2[2], float *output[6], float center_width, float dimension, float adaption_rate) {
00238         // 1. scale the input by the window function; this serves a dual purpose:
00239         // - first it improves the FFT resolution b/c boundary discontinuities (and their frequencies) get removed
00240         // - second it allows for smooth blending of varying filters between the blocks
00241         {
00242             float* pWnd = &wnd[0];
00243             float* pLt = &lt[0];
00244             float* pRt = &rt[0];
00245             float* pIn0 = input1[0];
00246             float* pIn1 = input1[1];
00247             for (unsigned k=0;k<halfN;k++) {
00248                 *pLt++ = *pIn0++ * *pWnd;
00249                 *pRt++ = *pIn1++ * *pWnd++;
00250             }
00251             pIn0 = input2[0];
00252             pIn1 = input2[1];
00253             for (unsigned k=0;k<halfN;k++) {
00254                 *pLt++ = *pIn0++ * *pWnd;
00255                 *pRt++ = *pIn1++ * *pWnd++;
00256             }
00257         }
00258 
00259 #ifdef USE_FFTW3
00260         // ... and tranform it into the frequency domain
00261         fftwf_execute(loadL);
00262         fftwf_execute(loadR);
00263 #else
00264         ff_fft_permuteRC(fftContextForward, lt, (FFTComplex*)&dftL[0]);
00265         av_fft_calc(fftContextForward, (FFTComplex*)&dftL[0]);
00266 
00267         ff_fft_permuteRC(fftContextForward, rt, (FFTComplex*)&dftR[0]);
00268         av_fft_calc(fftContextForward, (FFTComplex*)&dftR[0]);
00269 #endif
00270 
00271         // 2. compare amplitude and phase of each DFT bin and produce the X/Y coordinates in the sound field
00272         //    but dont do DC or N/2 component
00273         for (unsigned f=0;f<halfN;f++) {           
00274             // get left/right amplitudes/phases
00275             float ampL = amplitude(dftL[f]), ampR = amplitude(dftR[f]);
00276             float phaseL = phase(dftL[f]), phaseR = phase(dftR[f]);
00277 //          if (ampL+ampR < epsilon)
00278 //              continue;       
00279 
00280             // calculate the amplitude/phase difference
00281             float ampDiff = clamp((ampL+ampR < epsilon) ? 0 : (ampR-ampL) / (ampR+ampL));
00282             float phaseDiff = phaseL - phaseR;
00283             if (phaseDiff < -PI) phaseDiff += 2*PI;
00284             if (phaseDiff > PI) phaseDiff -= 2*PI;
00285             phaseDiff = abs(phaseDiff);
00286 
00287             if (linear_steering) {
00288                 // --- this is the fancy new linear mode ---
00289 
00290                 // get sound field x/y position
00291                 yfs[f] = get_yfs(ampDiff,phaseDiff);
00292                 xfs[f] = get_xfs(ampDiff,yfs[f]);
00293 
00294                 // add dimension control
00295                 yfs[f] = clamp(yfs[f] - dimension);
00296 
00297                 // add crossfeed control
00298                 xfs[f] = clamp(xfs[f] * (front_separation*(1+yfs[f])/2 + rear_separation*(1-yfs[f])/2));
00299 
00300                 // 3. generate frequency filters for each output channel
00301                 float left = (1-xfs[f])/2, right = (1+xfs[f])/2;
00302                 float front = (1+yfs[f])/2, back = (1-yfs[f])/2;
00303                 float volume[5] = {
00304                     front * (left * center_width + max(0,-xfs[f]) * (1-center_width)),  // left
00305                     front * center_level*((1-abs(xfs[f])) * (1-center_width)),          // center
00306                     front * (right * center_width + max(0, xfs[f]) * (1-center_width)), // right
00307                     back * surround_level * left,                                       // left surround
00308                     back * surround_level * right                                       // right surround
00309                 };
00310 
00311                 // adapt the prior filter
00312                 for (unsigned c=0;c<5;c++)
00313                     filter[c][f] = (1-adaption_rate)*filter[c][f] + adaption_rate*volume[c];
00314 
00315             } else {
00316                 // --- this is the old & simple steering mode ---
00317 
00318                 // calculate the amplitude/phase difference
00319                 float ampDiff = clamp((ampL+ampR < epsilon) ? 0 : (ampR-ampL) / (ampR+ampL));
00320                 float phaseDiff = phaseL - phaseR;
00321                 if (phaseDiff < -PI) phaseDiff += 2*PI;
00322                 if (phaseDiff > PI) phaseDiff -= 2*PI;
00323                 phaseDiff = abs(phaseDiff);
00324 
00325                 // determine sound field x-position
00326                 xfs[f] = ampDiff;
00327 
00328                 // determine preliminary sound field y-position from phase difference
00329                 yfs[f] = 1 - (phaseDiff/PI)*2;
00330 
00331                 if (abs(xfs[f]) > surround_balance) {
00332                     // blend linearly between the surrounds and the fronts if the balance exceeds the surround encoding balance
00333                     // this is necessary because the sound field is trapezoidal and will be stretched behind the listener
00334                     float frontness = (abs(xfs[f]) - surround_balance)/(1-surround_balance);
00335                     yfs[f]  = (1-frontness) * yfs[f] + frontness * 1; 
00336                 }
00337 
00338                 // add dimension control
00339                 yfs[f] = clamp(yfs[f] - dimension);
00340 
00341                 // add crossfeed control
00342                 xfs[f] = clamp(xfs[f] * (front_separation*(1+yfs[f])/2 + rear_separation*(1-yfs[f])/2));
00343 
00344                 // 3. generate frequency filters for each output channel, according to the signal position
00345                 // the sum of all channel volumes must be 1.0
00346                 float left = (1-xfs[f])/2, right = (1+xfs[f])/2;
00347                 float front = (1+yfs[f])/2, back = (1-yfs[f])/2;
00348                 float volume[5] = {
00349                     front * (left * center_width + max(0,-xfs[f]) * (1-center_width)),      // left
00350                     front * center_level*((1-abs(xfs[f])) * (1-center_width)),              // center
00351                     front * (right * center_width + max(0, xfs[f]) * (1-center_width)),     // right
00352                     back * surround_level*max(0,min(1,((1-(xfs[f]/surround_balance))/2))),  // left surround
00353                     back * surround_level*max(0,min(1,((1+(xfs[f]/surround_balance))/2)))   // right surround
00354                 };
00355 
00356                 // adapt the prior filter
00357                 for (unsigned c=0;c<5;c++)
00358                     filter[c][f] = (1-adaption_rate)*filter[c][f] + adaption_rate*volume[c];
00359             }
00360 
00361             // ... and build the signal which we want to position
00362             frontL[f] = polar(ampL+ampR,phaseL);
00363             frontR[f] = polar(ampL+ampR,phaseR);
00364             avg[f] = frontL[f] + frontR[f];
00365             surL[f] = polar(ampL+ampR,phaseL+phase_offsetL);
00366             surR[f] = polar(ampL+ampR,phaseR+phase_offsetR);
00367             trueavg[f] = cfloat(dftL[f][0] + dftR[f][0], dftL[f][1] + dftR[f][1]);
00368         }
00369 
00370         // 4. distribute the unfiltered reference signals over the channels
00371         apply_filter(&frontL[0],&filter[0][0],&output[0][0]);   // front left
00372         apply_filter(&avg[0], &filter[1][0],&output[1][0]);     // front center
00373         apply_filter(&frontR[0],&filter[2][0],&output[2][0]);   // front right
00374         apply_filter(&surL[0],&filter[3][0],&output[3][0]);     // surround left
00375         apply_filter(&surR[0],&filter[4][0],&output[4][0]);     // surround right
00376         apply_filter(&trueavg[0],&filter[5][0],&output[5][0]);  // lfe
00377     }
00378 
00379 #define FASTER_CALC
00380     // map from amplitude difference and phase difference to yfs
00381     inline double get_yfs(double ampDiff, double phaseDiff) {
00382         double x = 1-(((1-sqr(ampDiff))*phaseDiff)/PI*2);
00383 #ifdef FASTER_CALC
00384         double tanX = tan(x);
00385         return 0.16468622925824683 + 0.5009268347818189*x - 0.06462757726992101*x*x
00386             + 0.09170680403453149*x*x*x + 0.2617754892323973*tanX - 0.04180413533856156*sqr(tanX);
00387 #else
00388         return 0.16468622925824683 + 0.5009268347818189*x - 0.06462757726992101*x*x
00389             + 0.09170680403453149*x*x*x + 0.2617754892323973*tan(x) - 0.04180413533856156*sqr(tan(x));
00390 #endif
00391     }
00392 
00393     // map from amplitude difference and yfs to xfs
00394     inline double get_xfs(double ampDiff, double yfs) {
00395         double x=ampDiff,y=yfs;
00396 #ifdef FASTER_CALC
00397         double tanX = tan(x);
00398         double tanY = tan(y);
00399         double asinX = asin(x);
00400         double sinX = sin(x);
00401         double sinY = sin(y);
00402         double x3 = x*x*x;
00403         double y2 = y*y;
00404         double y3 = y*y2;
00405         return 2.464833559224702*x - 423.52131153259404*x*y + 
00406             67.8557858606918*x3*y + 788.2429425544392*x*y2 - 
00407             79.97650354902909*x3*y2 - 513.8966153850349*x*y3 + 
00408             35.68117670186306*x3*y3 + 13867.406173420834*y*asinX - 
00409             2075.8237075786396*y2*asinX - 908.2722068360281*y3*asinX - 
00410             12934.654772878019*asinX*sinY - 13216.736529661162*y*tanX + 
00411             1288.6463247741938*y2*tanX + 1384.372969378453*y3*tanX + 
00412             12699.231471126128*sinY*tanX + 95.37131275594336*sinX*tanY - 
00413             91.21223198407546*tanX*tanY;
00414 #else
00415         return 2.464833559224702*x - 423.52131153259404*x*y + 
00416             67.8557858606918*x*x*x*y + 788.2429425544392*x*y*y - 
00417             79.97650354902909*x*x*x*y*y - 513.8966153850349*x*y*y*y + 
00418             35.68117670186306*x*x*x*y*y*y + 13867.406173420834*y*asin(x) - 
00419             2075.8237075786396*y*y*asin(x) - 908.2722068360281*y*y*y*asin(x) - 
00420             12934.654772878019*asin(x)*sin(y) - 13216.736529661162*y*tan(x) + 
00421             1288.6463247741938*y*y*tan(x) + 1384.372969378453*y*y*y*tan(x) + 
00422             12699.231471126128*sin(y)*tan(x) + 95.37131275594336*sin(x)*tan(y) - 
00423             91.21223198407546*tan(x)*tan(y);
00424 #endif
00425     }
00426 
00427     // filter the complex source signal and add it to target
00428     void apply_filter(cfloat *signal, float *flt, float *target) {
00429         // filter the signal
00430         unsigned f;
00431         for (f=0;f<=halfN;f++) {
00432             src[f][0] = signal[f].real() * flt[f];
00433             src[f][1] = signal[f].imag() * flt[f];
00434         }
00435 #ifdef USE_FFTW3
00436         // transform into time domain
00437         fftwf_execute(store);
00438 
00439         float* pT1   = &target[current_buf*halfN];
00440         float* pWnd1 = &wnd[0];
00441         float* pDst1 = &dst[0];
00442         float* pT2   = &target[(current_buf^1)*halfN];
00443         float* pWnd2 = &wnd[halfN];
00444         float* pDst2 = &dst[halfN];
00445         // add the result to target, windowed
00446         for (unsigned int k=0;k<halfN;k++)
00447         {
00448             // 1st part is overlap add
00449             *pT1++ += *pWnd1++ * *pDst1++;
00450             // 2nd part is set as has no history
00451             *pT2++  = *pWnd2++ * *pDst2++;
00452         }
00453 #else
00454         // enforce odd symmetry
00455         for (f=1;f<halfN;f++) {
00456             src[N-f][0] = src[f][0];
00457             src[N-f][1] = -src[f][1];   // complex conjugate
00458         }
00459         av_fft_permute(fftContextReverse, (FFTComplex*)&src[0]);
00460         av_fft_calc(fftContextReverse, (FFTComplex*)&src[0]);
00461 
00462         float* pT1   = &target[current_buf*halfN];
00463         float* pWnd1 = &wnd[0];
00464         float* pDst1 = &src[0][0];
00465         float* pT2   = &target[(current_buf^1)*halfN];
00466         float* pWnd2 = &wnd[halfN];
00467         float* pDst2 = &src[halfN][0];
00468         // add the result to target, windowed
00469         for (unsigned int k=0;k<halfN;k++)
00470         {
00471             // 1st part is overlap add
00472             *pT1++ += *pWnd1++ * *pDst1; pDst1 += 2;
00473             // 2nd part is set as has no history
00474             *pT2++  = *pWnd2++ * *pDst2; pDst2 += 2;
00475         }
00476 #endif
00477     }
00478 
00479 #ifndef USE_FFTW3
00480 
00484     void ff_fft_permuteRC(FFTContext *s, FFTSample *r, FFTComplex *z)
00485     {
00486         int j, k, np;
00487         const uint16_t *revtab = s->revtab;
00488 
00489         /* reverse */
00490         np = 1 << s->nbits;
00491         for(j=0;j<np;j++) {
00492             k = revtab[j];
00493             z[k].re = r[j];
00494             z[k].im = 0.0;
00495         }
00496     }
00497 
00503     void ff_fft_permuteCR(FFTContext *s, FFTComplex *z, FFTSample *r)
00504     {
00505         int j, k, np;
00506         FFTComplex tmp;
00507         const uint16_t *revtab = s->revtab;
00508 
00509         /* reverse */
00510         np = 1 << s->nbits;
00511         for(j=0;j<np;j++) {
00512             k = revtab[j];
00513             if (k < j) {
00514                 r[k] = z[j].re;
00515                 r[j] = z[k].re;
00516             }
00517         }
00518     }
00519 #endif
00520 
00521     unsigned int N;                    // the block size
00522     unsigned int halfN;                // half block size precalculated
00523 #ifdef USE_FFTW3
00524     // FFTW data structures
00525     float *lt,*rt,*dst;                // left total, right total (source arrays), destination array
00526     fftwf_complex *dftL,*dftR,*src;    // intermediate arrays (FFTs of lt & rt, processing source)
00527     fftwf_plan loadL,loadR,store;      // plans for loading the data into the intermediate format and back
00528 #else
00529     FFTContext *fftContextForward, *fftContextReverse; 
00530     FFTSample *lt,*rt;                 // left total, right total (source arrays), destination array
00531     FFTComplexArray *dftL,*dftR,*src;  // intermediate arrays (FFTs of lt & rt, processing source)
00532 #endif
00533     // buffers
00534     std::vector<cfloat> frontL,frontR,avg,surL,surR; // the signal (phase-corrected) in the frequency domain
00535     std::vector<cfloat> trueavg;       // for lfe generation
00536     std::vector<float> xfs,yfs;        // the feature space positions for each frequency bin
00537     std::vector<float> wnd;            // the window function, precalculated
00538     std::vector<float> filter[6];      // a frequency filter for each output channel
00539     std::vector<float> inbuf[2];       // the sliding input buffers
00540     std::vector<float> outbuf[6];      // the sliding output buffers
00541     // coefficients
00542     float surround_high,surround_low;  // high and low surround mixing coefficient (e.g. 0.8165/0.5774)
00543     float surround_balance;            // the xfs balance that follows from the coeffs
00544     float surround_level;              // gain for the surround channels (follows from the coeffs
00545     float phase_offsetL, phase_offsetR;// phase shifts to be applied to the rear channels
00546     float front_separation;            // front stereo separation
00547     float rear_separation;             // rear stereo separation
00548     bool linear_steering;              // whether the steering should be linear or not
00549     cfloat A,B,C,D,E,F,G,H;            // coefficients for the linear steering
00550     int current_buf;                   // specifies which buffer is 2nd half of input sliding buffer
00551     float * inbufs[2];                 // for passing back to driver
00552     float * outbufs[6];                // for passing back to driver
00553 
00554     friend class fsurround_decoder;
00555 };
00556 
00557 
00558 // implementation of the shell class
00559 
00560 fsurround_decoder::fsurround_decoder(unsigned blocksize): impl(new decoder_impl(blocksize)) { }
00561 
00562 fsurround_decoder::~fsurround_decoder() { delete impl; }
00563 
00564 void fsurround_decoder::decode(float center_width, float dimension, float adaption_rate) {
00565     impl->decode(center_width,dimension,adaption_rate);
00566 }
00567 
00568 void fsurround_decoder::flush() { impl->flush(); }
00569 
00570 void fsurround_decoder::surround_coefficients(float a, float b) { impl->surround_coefficients(a,b); }
00571 
00572 void fsurround_decoder::phase_mode(unsigned mode) { impl->phase_mode(mode); }
00573 
00574 void fsurround_decoder::steering_mode(bool mode) { impl->steering_mode(mode); }
00575 
00576 void fsurround_decoder::separation(float front, float rear) { impl->separation(front,rear); }
00577 
00578 float ** fsurround_decoder::getInputBuffers()
00579 {
00580     return impl->getInputBuffers();
00581 }
00582 
00583 float ** fsurround_decoder::getOutputBuffers()
00584 {
00585     return impl->getOutputBuffers();
00586 }
00587 
00588 void fsurround_decoder::sample_rate(unsigned int samplerate)
00589 {
00590     impl->sample_rate(samplerate);
00591 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends