|
MythTV
0.26-pre
|
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 = <[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 }
1.7.6.1