MythTV  master
el_processor.cpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 2007 Christian Kothe
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18 
19 #include "el_processor.h"
20 #include <cmath>
21 #include <complex>
22 #include <cstdlib>
23 #include <cstring>
24 #include <vector>
25 #ifdef USE_FFTW3
26 #include "fftw3.h"
27 #else
28 extern "C" {
29 #include "libavcodec/avfft.h"
30 #include "libavcodec/fft.h"
31 }
32 typedef FFTSample FFTComplexArray[2];
33 #endif
34 
35 
36 #ifdef USE_FFTW3
37 #pragma comment (lib,"libfftw3f-3.lib")
38 #endif
39 
40 typedef std::complex<float> cfloat;
41 
42 static const float PI = 3.141592654;
43 static const float epsilon = 0.000001;
44 static const float center_level = 0.5*sqrt(0.5);
45 
46 // private implementation of the surround decoder
47 class decoder_impl {
48 public:
49  // create an instance of the decoder
50  // blocksize is fixed over the lifetime of this object for performance reasons
51  decoder_impl(unsigned blocksize=8192): N(blocksize), halfN(blocksize/2) {
52 #ifdef USE_FFTW3
53  // create FFTW buffers
54  lt = (float*)fftwf_malloc(sizeof(float)*N);
55  rt = (float*)fftwf_malloc(sizeof(float)*N);
56  dst = (float*)fftwf_malloc(sizeof(float)*N);
57  dftL = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*N);
58  dftR = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*N);
59  src = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex)*N);
60  loadL = fftwf_plan_dft_r2c_1d(N, lt, dftL,FFTW_MEASURE);
61  loadR = fftwf_plan_dft_r2c_1d(N, rt, dftR,FFTW_MEASURE);
62  store = fftwf_plan_dft_c2r_1d(N, src, dst,FFTW_MEASURE);
63 #else
64  // create lavc fft buffers
65  lt = (float*)av_malloc(sizeof(FFTSample)*N);
66  rt = (float*)av_malloc(sizeof(FFTSample)*N);
67  dftL = (FFTComplexArray*)av_malloc(sizeof(FFTComplex)*N*2);
68  dftR = (FFTComplexArray*)av_malloc(sizeof(FFTComplex)*N*2);
69  src = (FFTComplexArray*)av_malloc(sizeof(FFTComplex)*N*2);
70  fftContextForward = (FFTContext*)av_malloc(sizeof(FFTContext));
71  memset(fftContextForward, 0, sizeof(FFTContext));
72  fftContextReverse = (FFTContext*)av_malloc(sizeof(FFTContext));
73  memset(fftContextReverse, 0, sizeof(FFTContext));
74  ff_fft_init(fftContextForward, 13, 0);
75  ff_fft_init(fftContextReverse, 13, 1);
76 #endif
77  // resize our own buffers
78  frontR.resize(N);
79  frontL.resize(N);
80  avg.resize(N);
81  surR.resize(N);
82  surL.resize(N);
83  trueavg.resize(N);
84  xfs.resize(N);
85  yfs.resize(N);
86  inbuf[0].resize(N);
87  inbuf[1].resize(N);
88  for (unsigned c=0;c<6;c++) {
89  outbuf[c].resize(N);
90  filter[c].resize(N);
91  }
92  sample_rate(48000);
93  // generate the window function (square root of hann, b/c it is applied before and after the transform)
94  wnd.resize(N);
95  for (unsigned k=0;k<N;k++)
96  wnd[k] = sqrt(0.5*(1-std::cos(2*PI*k/N))/N);
97  current_buf = 0;
98  memset(inbufs, 0, sizeof(inbufs));
99  memset(outbufs, 0, sizeof(outbufs));
100  // set the default coefficients
101  surround_coefficients(0.8165,0.5774);
102  phase_mode(0);
103  separation(1,1);
104  steering_mode(true);
105  }
106 
107  // destructor
109 #ifdef USE_FFTW3
110  // clean up the FFTW stuff
111  fftwf_destroy_plan(store);
112  fftwf_destroy_plan(loadR);
113  fftwf_destroy_plan(loadL);
114  fftwf_free(src);
115  fftwf_free(dftR);
116  fftwf_free(dftL);
117  fftwf_free(dst);
118  fftwf_free(rt);
119  fftwf_free(lt);
120 #else
121  ff_fft_end(fftContextForward);
122  ff_fft_end(fftContextReverse);
123  av_free(src);
124  av_free(dftR);
125  av_free(dftL);
126  av_free(rt);
127  av_free(lt);
130 #endif
131  }
132 
133  float ** getInputBuffers()
134  {
135  inbufs[0] = &inbuf[0][current_buf*halfN];
136  inbufs[1] = &inbuf[1][current_buf*halfN];
137  return inbufs;
138  }
139 
140  float ** getOutputBuffers()
141  {
142  outbufs[0] = &outbuf[0][current_buf*halfN];
143  outbufs[1] = &outbuf[1][current_buf*halfN];
144  outbufs[2] = &outbuf[2][current_buf*halfN];
145  outbufs[3] = &outbuf[3][current_buf*halfN];
146  outbufs[4] = &outbuf[4][current_buf*halfN];
147  outbufs[5] = &outbuf[5][current_buf*halfN];
148  return outbufs;
149  }
150 
151  // decode a chunk of stereo sound, has to contain exactly blocksize samples
152  // center_width [0..1] distributes the center information towards the front left/right channels, 1=full distribution, 0=no distribution
153  // dimension [0..1] moves the soundfield backwards, 0=front, 1=side
154  // adaption_rate [0..1] determines how fast the steering gets adapted, 1=instantaneous, 0.1 = very slow adaption
155  void decode(float center_width, float dimension, float adaption_rate) {
156  // process first part
157  int index;
158  index = current_buf*halfN;
159  float *in_second[2] = {&inbuf[0][index],&inbuf[1][index]};
160  current_buf ^= 1;
161  index = current_buf*halfN;
162  float *in_first[2] = {&inbuf[0][index],&inbuf[1][index]};
163  add_output(in_first,in_second,center_width,dimension,adaption_rate,true);
164  // shift last half of input buffer to the beginning
165  }
166 
167  // flush the internal buffers
168  void flush() {
169  for (unsigned k=0;k<N;k++) {
170  for (unsigned c=0;c<6;c++)
171  outbuf[c][k] = 0;
172  inbuf[0][k] = 0;
173  inbuf[1][k] = 0;
174  }
175  }
176 
177  // set lfe filter params
178  void sample_rate(unsigned int srate) {
179  // lfe filter is just straight through band limited
180  unsigned int cutoff = (30*N)/srate;
181  for (unsigned f=0;f<=halfN;f++) {
182  if (f<cutoff)
183  filter[5][f] = 0.5*sqrt(0.5);
184  else
185  filter[5][f] = 0.0;
186  }
187  }
188 
189  // set the assumed surround mixing coefficients
190  void surround_coefficients(float a, float b) {
191  // calc the simple coefficients
192  surround_high = a;
193  surround_low = b;
194  surround_balance = (a-b)/(a+b);
195  surround_level = 1/(a+b);
196  // calc the linear coefficients
197  cfloat i(0,1), u((a+b)*i), v((b-a)*i), n(0.25,0),o(1,0);
198  A = (v-o)*n; B = (o-u)*n; C = (-o-v)*n; D = (o+u)*n;
199  E = (o+v)*n; F = (o+u)*n; G = (o-v)*n; H = (o-u)*n;
200  }
201 
202  // set the phase shifting mode
203  void phase_mode(unsigned mode) {
204  const float modes[4][2] = {{0,0},{0,PI},{PI,0},{-PI/2,PI/2}};
205  phase_offsetL = modes[mode][0];
206  phase_offsetR = modes[mode][1];
207  }
208 
209  // what steering mode should be chosen
210  void steering_mode(bool mode) { linear_steering = mode; }
211 
212  // set front & rear separation controls
213  void separation(float front, float rear) {
214  front_separation = front;
215  rear_separation = rear;
216  }
217 
218 private:
219  // polar <-> cartesian coodinates conversion
220  static inline float amplitude(const float cf[2]) { return std::sqrt(cf[0]*cf[0] + cf[1]*cf[1]); }
221  static inline float phase(const float cf[2]) { return std::atan2(cf[1],cf[0]); }
222  static inline cfloat polar(float a, float p) { return {static_cast<float>(a*std::cos(p)),static_cast<float>(a*std::sin(p))}; }
223  static inline float sqr(float x) { return x*x; }
224  // the dreaded min/max
225  static inline float min(float a, float b) { return a<b?a:b; }
226  static inline float max(float a, float b) { return a>b?a:b; }
227  static inline float clamp(float x) { return max(-1,min(1,x)); }
228 
229  // handle the output buffering for overlapped calls of block_decode
230  void add_output(float *input1[2], float *input2[2], float center_width, float dimension, float adaption_rate, bool /*result*/=false) {
231  // add the windowed data to the last 1/2 of the output buffer
232  float *out[6] = {&outbuf[0][0],&outbuf[1][0],&outbuf[2][0],&outbuf[3][0],&outbuf[4][0],&outbuf[5][0]};
233  block_decode(input1,input2,out,center_width,dimension,adaption_rate);
234  }
235 
236  // CORE FUNCTION: decode a block of data
237  void block_decode(float *input1[2], float *input2[2], float *output[6], float center_width, float dimension, float adaption_rate) {
238  // 1. scale the input by the window function; this serves a dual purpose:
239  // - first it improves the FFT resolution b/c boundary discontinuities (and their frequencies) get removed
240  // - second it allows for smooth blending of varying filters between the blocks
241  {
242  float* pWnd = &wnd[0];
243  float* pLt = &lt[0];
244  float* pRt = &rt[0];
245  float* pIn0 = input1[0];
246  float* pIn1 = input1[1];
247  for (unsigned k=0;k<halfN;k++) {
248  *pLt++ = *pIn0++ * *pWnd;
249  *pRt++ = *pIn1++ * *pWnd++;
250  }
251  pIn0 = input2[0];
252  pIn1 = input2[1];
253  for (unsigned k=0;k<halfN;k++) {
254  *pLt++ = *pIn0++ * *pWnd;
255  *pRt++ = *pIn1++ * *pWnd++;
256  }
257  }
258 
259 #ifdef USE_FFTW3
260  // ... and tranform it into the frequency domain
261  fftwf_execute(loadL);
262  fftwf_execute(loadR);
263 #else
264  ff_fft_permuteRC(fftContextForward, lt, (FFTComplex*)&dftL[0]);
265  av_fft_calc(fftContextForward, (FFTComplex*)&dftL[0]);
266 
267  ff_fft_permuteRC(fftContextForward, rt, (FFTComplex*)&dftR[0]);
268  av_fft_calc(fftContextForward, (FFTComplex*)&dftR[0]);
269 #endif
270 
271  // 2. compare amplitude and phase of each DFT bin and produce the X/Y coordinates in the sound field
272  // but dont do DC or N/2 component
273  for (unsigned f=0;f<halfN;f++) {
274  // get left/right amplitudes/phases
275  float ampL = amplitude(dftL[f]), ampR = amplitude(dftR[f]);
276  float phaseL = phase(dftL[f]), phaseR = phase(dftR[f]);
277 // if (ampL+ampR < epsilon)
278 // continue;
279 
280  // calculate the amplitude/phase difference
281  float ampDiff = clamp((ampL+ampR < epsilon) ? 0 : (ampR-ampL) / (ampR+ampL));
282  float phaseDiff = phaseL - phaseR;
283  if (phaseDiff < -PI) phaseDiff += 2*PI;
284  if (phaseDiff > PI) phaseDiff -= 2*PI;
285  phaseDiff = abs(phaseDiff);
286 
287  if (linear_steering) {
288  // --- this is the fancy new linear mode ---
289 
290  // get sound field x/y position
291  yfs[f] = get_yfs(ampDiff,phaseDiff);
292  xfs[f] = get_xfs(ampDiff,yfs[f]);
293 
294  // add dimension control
295  yfs[f] = clamp(yfs[f] - dimension);
296 
297  // add crossfeed control
298  xfs[f] = clamp(xfs[f] * (front_separation*(1+yfs[f])/2 + rear_separation*(1-yfs[f])/2));
299 
300  // 3. generate frequency filters for each output channel
301  float left = (1-xfs[f])/2, right = (1+xfs[f])/2;
302  float front = (1+yfs[f])/2, back = (1-yfs[f])/2;
303  float volume[5] = {
304  front * (left * center_width + max(0,-xfs[f]) * (1-center_width)), // left
305  front * center_level*((1-abs(xfs[f])) * (1-center_width)), // center
306  front * (right * center_width + max(0, xfs[f]) * (1-center_width)), // right
307  back * surround_level * left, // left surround
308  back * surround_level * right // right surround
309  };
310 
311  // adapt the prior filter
312  for (unsigned c=0;c<5;c++)
313  filter[c][f] = (1-adaption_rate)*filter[c][f] + adaption_rate*volume[c];
314 
315  } else {
316  // --- this is the old & simple steering mode ---
317 
318  // calculate the amplitude/phase difference
319  float ampDiff = clamp((ampL+ampR < epsilon) ? 0 : (ampR-ampL) / (ampR+ampL));
320  float phaseDiff = phaseL - phaseR;
321  if (phaseDiff < -PI) phaseDiff += 2*PI;
322  if (phaseDiff > PI) phaseDiff -= 2*PI;
323  phaseDiff = abs(phaseDiff);
324 
325  // determine sound field x-position
326  xfs[f] = ampDiff;
327 
328  // determine preliminary sound field y-position from phase difference
329  yfs[f] = 1 - (phaseDiff/PI)*2;
330 
331  if (abs(xfs[f]) > surround_balance) {
332  // blend linearly between the surrounds and the fronts if the balance exceeds the surround encoding balance
333  // this is necessary because the sound field is trapezoidal and will be stretched behind the listener
334  float frontness = (abs(xfs[f]) - surround_balance)/(1-surround_balance);
335  yfs[f] = (1-frontness) * yfs[f] + frontness * 1;
336  }
337 
338  // add dimension control
339  yfs[f] = clamp(yfs[f] - dimension);
340 
341  // add crossfeed control
342  xfs[f] = clamp(xfs[f] * (front_separation*(1+yfs[f])/2 + rear_separation*(1-yfs[f])/2));
343 
344  // 3. generate frequency filters for each output channel, according to the signal position
345  // the sum of all channel volumes must be 1.0
346  float left = (1-xfs[f])/2, right = (1+xfs[f])/2;
347  float front = (1+yfs[f])/2, back = (1-yfs[f])/2;
348  float volume[5] = {
349  front * (left * center_width + max(0,-xfs[f]) * (1-center_width)), // left
350  front * center_level*((1-abs(xfs[f])) * (1-center_width)), // center
351  front * (right * center_width + max(0, xfs[f]) * (1-center_width)), // right
352  back * surround_level*max(0,min(1,((1-(xfs[f]/surround_balance))/2))), // left surround
353  back * surround_level*max(0,min(1,((1+(xfs[f]/surround_balance))/2))) // right surround
354  };
355 
356  // adapt the prior filter
357  for (unsigned c=0;c<5;c++)
358  filter[c][f] = (1-adaption_rate)*filter[c][f] + adaption_rate*volume[c];
359  }
360 
361  // ... and build the signal which we want to position
362  frontL[f] = polar(ampL+ampR,phaseL);
363  frontR[f] = polar(ampL+ampR,phaseR);
364  avg[f] = frontL[f] + frontR[f];
365  surL[f] = polar(ampL+ampR,phaseL+phase_offsetL);
366  surR[f] = polar(ampL+ampR,phaseR+phase_offsetR);
367  trueavg[f] = cfloat(dftL[f][0] + dftR[f][0], dftL[f][1] + dftR[f][1]);
368  }
369 
370  // 4. distribute the unfiltered reference signals over the channels
371  apply_filter(&frontL[0],&filter[0][0],&output[0][0]); // front left
372  apply_filter(&avg[0], &filter[1][0],&output[1][0]); // front center
373  apply_filter(&frontR[0],&filter[2][0],&output[2][0]); // front right
374  apply_filter(&surL[0],&filter[3][0],&output[3][0]); // surround left
375  apply_filter(&surR[0],&filter[4][0],&output[4][0]); // surround right
376  apply_filter(&trueavg[0],&filter[5][0],&output[5][0]); // lfe
377  }
378 
379 #define FASTER_CALC
380  // map from amplitude difference and phase difference to yfs
381  inline double get_yfs(double ampDiff, double phaseDiff) {
382  double x = 1-(((1-sqr(ampDiff))*phaseDiff)/PI*2);
383 #ifdef FASTER_CALC
384  double tanX = tan(x);
385  return 0.16468622925824683 + 0.5009268347818189*x - 0.06462757726992101*x*x
386  + 0.09170680403453149*x*x*x + 0.2617754892323973*tanX - 0.04180413533856156*sqr(tanX);
387 #else
388  return 0.16468622925824683 + 0.5009268347818189*x - 0.06462757726992101*x*x
389  + 0.09170680403453149*x*x*x + 0.2617754892323973*tan(x) - 0.04180413533856156*sqr(tan(x));
390 #endif
391  }
392 
393  // map from amplitude difference and yfs to xfs
394  inline double get_xfs(double ampDiff, double yfs) {
395  double x=ampDiff,y=yfs;
396 #ifdef FASTER_CALC
397  double tanX = tan(x);
398  double tanY = tan(y);
399  double asinX = asin(x);
400  double sinX = sin(x);
401  double sinY = sin(y);
402  double x3 = x*x*x;
403  double y2 = y*y;
404  double y3 = y*y2;
405  return 2.464833559224702*x - 423.52131153259404*x*y +
406  67.8557858606918*x3*y + 788.2429425544392*x*y2 -
407  79.97650354902909*x3*y2 - 513.8966153850349*x*y3 +
408  35.68117670186306*x3*y3 + 13867.406173420834*y*asinX -
409  2075.8237075786396*y2*asinX - 908.2722068360281*y3*asinX -
410  12934.654772878019*asinX*sinY - 13216.736529661162*y*tanX +
411  1288.6463247741938*y2*tanX + 1384.372969378453*y3*tanX +
412  12699.231471126128*sinY*tanX + 95.37131275594336*sinX*tanY -
413  91.21223198407546*tanX*tanY;
414 #else
415  return 2.464833559224702*x - 423.52131153259404*x*y +
416  67.8557858606918*x*x*x*y + 788.2429425544392*x*y*y -
417  79.97650354902909*x*x*x*y*y - 513.8966153850349*x*y*y*y +
418  35.68117670186306*x*x*x*y*y*y + 13867.406173420834*y*asin(x) -
419  2075.8237075786396*y*y*asin(x) - 908.2722068360281*y*y*y*asin(x) -
420  12934.654772878019*asin(x)*sin(y) - 13216.736529661162*y*tan(x) +
421  1288.6463247741938*y*y*tan(x) + 1384.372969378453*y*y*y*tan(x) +
422  12699.231471126128*sin(y)*tan(x) + 95.37131275594336*sin(x)*tan(y) -
423  91.21223198407546*tan(x)*tan(y);
424 #endif
425  }
426 
427  // filter the complex source signal and add it to target
428  void apply_filter(cfloat *signal, const float *flt, float *target) {
429  // filter the signal
430  unsigned f;
431  for (f=0;f<=halfN;f++) {
432  src[f][0] = signal[f].real() * flt[f];
433  src[f][1] = signal[f].imag() * flt[f];
434  }
435 #ifdef USE_FFTW3
436  // transform into time domain
437  fftwf_execute(store);
438 
439  float* pT1 = &target[current_buf*halfN];
440  float* pWnd1 = &wnd[0];
441  float* pDst1 = &dst[0];
442  float* pT2 = &target[(current_buf^1)*halfN];
443  float* pWnd2 = &wnd[halfN];
444  float* pDst2 = &dst[halfN];
445  // add the result to target, windowed
446  for (unsigned int k=0;k<halfN;k++)
447  {
448  // 1st part is overlap add
449  *pT1++ += *pWnd1++ * *pDst1++;
450  // 2nd part is set as has no history
451  *pT2++ = *pWnd2++ * *pDst2++;
452  }
453 #else
454  // enforce odd symmetry
455  for (f=1;f<halfN;f++) {
456  src[N-f][0] = src[f][0];
457  src[N-f][1] = -src[f][1]; // complex conjugate
458  }
459  av_fft_permute(fftContextReverse, (FFTComplex*)&src[0]);
460  av_fft_calc(fftContextReverse, (FFTComplex*)&src[0]);
461 
462  float* pT1 = &target[current_buf*halfN];
463  float* pWnd1 = &wnd[0];
464  float* pDst1 = &src[0][0];
465  float* pT2 = &target[(current_buf^1)*halfN];
466  float* pWnd2 = &wnd[halfN];
467  float* pDst2 = &src[halfN][0];
468  // add the result to target, windowed
469  for (unsigned int k=0;k<halfN;k++)
470  {
471  // 1st part is overlap add
472  *pT1++ += *pWnd1++ * *pDst1; pDst1 += 2;
473  // 2nd part is set as has no history
474  *pT2++ = *pWnd2++ * *pDst2; pDst2 += 2;
475  }
476 #endif
477  }
478 
479 #ifndef USE_FFTW3
480 
484  void ff_fft_permuteRC(FFTContext *s, FFTSample *r, FFTComplex *z)
485  {
486  int j, k, np;
487  const uint16_t *revtab = s->revtab;
488 
489  /* reverse */
490  np = 1 << s->nbits;
491  for(j=0;j<np;j++) {
492  k = revtab[j];
493  z[k].re = r[j];
494  z[k].im = 0.0;
495  }
496  }
497 
503  void ff_fft_permuteCR(FFTContext *s, FFTComplex *z, FFTSample *r)
504  {
505  int j, k, np;
506  const uint16_t *revtab = s->revtab;
507 
508  /* reverse */
509  np = 1 << s->nbits;
510  for(j=0;j<np;j++) {
511  k = revtab[j];
512  if (k < j) {
513  r[k] = z[j].re;
514  r[j] = z[k].re;
515  }
516  }
517  }
518 #endif
519 
520  unsigned int N; // the block size
521  unsigned int halfN; // half block size precalculated
522 #ifdef USE_FFTW3
523  // FFTW data structures
524  float *lt,*rt,*dst; // left total, right total (source arrays), destination array
525  fftwf_complex *dftL,*dftR,*src; // intermediate arrays (FFTs of lt & rt, processing source)
526  fftwf_plan loadL,loadR,store; // plans for loading the data into the intermediate format and back
527 #else
529  FFTSample *lt,*rt; // left total, right total (source arrays), destination array
530  FFTComplexArray *dftL,*dftR,*src; // intermediate arrays (FFTs of lt & rt, processing source)
531 #endif
532  // buffers
533  std::vector<cfloat> frontL,frontR,avg,surL,surR; // the signal (phase-corrected) in the frequency domain
534  std::vector<cfloat> trueavg; // for lfe generation
535  std::vector<float> xfs,yfs; // the feature space positions for each frequency bin
536  std::vector<float> wnd; // the window function, precalculated
537  std::vector<float> filter[6]; // a frequency filter for each output channel
538  std::vector<float> inbuf[2]; // the sliding input buffers
539  std::vector<float> outbuf[6]; // the sliding output buffers
540  // coefficients
541  float surround_high,surround_low; // high and low surround mixing coefficient (e.g. 0.8165/0.5774)
542  float surround_balance; // the xfs balance that follows from the coeffs
543  float surround_level; // gain for the surround channels (follows from the coeffs
544  float phase_offsetL, phase_offsetR;// phase shifts to be applied to the rear channels
545  float front_separation; // front stereo separation
546  float rear_separation; // rear stereo separation
547  bool linear_steering; // whether the steering should be linear or not
548  cfloat A,B,C,D,E,F,G,H; // coefficients for the linear steering
549  int current_buf; // specifies which buffer is 2nd half of input sliding buffer
550  float * inbufs[2]; // for passing back to driver
551  float * outbufs[6]; // for passing back to driver
552 
553  friend class fsurround_decoder;
554 };
555 
556 
557 // implementation of the shell class
558 
559 fsurround_decoder::fsurround_decoder(unsigned blocksize): impl(new decoder_impl(blocksize)) { }
560 
562 
563 void fsurround_decoder::decode(float center_width, float dimension, float adaption_rate) {
564  impl->decode(center_width,dimension,adaption_rate);
565 }
566 
568 
570 
571 void fsurround_decoder::phase_mode(unsigned mode) { impl->phase_mode(mode); }
572 
574 
575 void fsurround_decoder::separation(float front, float rear) { impl->separation(front,rear); }
576 
578 {
579  return impl->getInputBuffers();
580 }
581 
583 {
584  return impl->getOutputBuffers();
585 }
586 
587 void fsurround_decoder::sample_rate(unsigned int samplerate)
588 {
589  impl->sample_rate(samplerate);
590 }
static float phase(const float cf[2])
void surround_coefficients(float a, float b)
float * inbufs[2]
void decode(float center_width, float dimension, float adaption_rate)
std::vector< cfloat > surR
FFTSample * rt
float rear_separation
static float clamp(float x)
void separation(float front, float rear)
FFTContext * fftContextForward
void ff_fft_permuteCR(FFTContext *s, FFTComplex *z, FFTSample *r)
std::vector< float > wnd
void steering_mode(bool mode)
void sample_rate(unsigned int srate)
void apply_filter(cfloat *signal, const float *flt, float *target)
std::complex< float > cfloat
void ff_fft_permuteRC(FFTContext *s, FFTSample *r, FFTComplex *z)
FFTSample FFTComplexArray[2]
static float amplitude(const float cf[2])
unsigned int N
unsigned char r
Definition: ParseText.cpp:329
unsigned char b
Definition: ParseText.cpp:329
std::vector< cfloat > frontR
static cfloat polar(float a, float p)
static float max(float a, float b)
FFTSample * lt
void add_output(float *input1[2], float *input2[2], float center_width, float dimension, float adaption_rate, bool=false)
std::vector< cfloat > surL
FFTComplexArray * dftR
float * outbufs[6]
void block_decode(float *input1[2], float *input2[2], float *output[6], float center_width, float dimension, float adaption_rate)
decoder_impl(unsigned blocksize=8192)
void steering_mode(bool mode)
class decoder_impl * impl
Definition: el_processor.h:70
FFTComplexArray * src
std::vector< float > outbuf[6]
void surround_coefficients(float a, float b)
unsigned short uint16_t
Definition: iso6937tables.h:1
float ** getInputBuffers()
std::vector< cfloat > avg
fsurround_decoder(unsigned blocksize=8192)
void phase_mode(unsigned mode)
std::vector< float > yfs
double get_xfs(double ampDiff, double yfs)
void * av_malloc(unsigned int size)
float ** getInputBuffers()
FFTContext * fftContextReverse
std::vector< float > xfs
std::vector< cfloat > trueavg
static const float PI
std::vector< float > inbuf[2]
static float sqr(float x)
static const float center_level
void decode(float center_width=1, float dimension=0, float adaption_rate=1)
void separation(float front, float rear)
float front_separation
float ** getOutputBuffers()
void av_free(void *ptr)
void phase_mode(unsigned mode)
static float min(float a, float b)
double get_yfs(double ampDiff, double phaseDiff)
unsigned int halfN
static guint32 * back
Definition: goom_core.c:34
std::vector< float > filter[6]
float surround_level
static const float epsilon
std::vector< cfloat > frontL
void sample_rate(unsigned int samplerate)
static int x3
Definition: mythsocket.cpp:62
float surround_balance
float ** getOutputBuffers()
#define output
FFTComplexArray * dftL