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 <algorithm>
21 #include <array>
22 #include <cmath>
23 #include <complex>
24 #include <cstdlib>
25 #include <cstring>
26 #include <vector>
27 extern "C" {
28 #include "libavutil/mem.h"
29 #include "libavcodec/avfft.h"
30 }
31 
32 using cfloat = std::complex<float>;
33 using InputBufs = std::array<float*,2>;
34 using OutputBufs = std::array<float*,6>;
35 
36 static const float PI = 3.141592654;
37 static const float epsilon = 0.000001;
38 static const float center_level = 0.5*sqrt(0.5);
39 
40 template <class T>
41 T sqr(T x) { return x*x; }
42 
43 // private implementation of the surround decoder
45 public:
46  // create an instance of the decoder
47  // blocksize is fixed over the lifetime of this object for performance reasons
48  explicit Impl(unsigned blocksize=8192)
49  : m_n(blocksize),
50  m_halfN(blocksize/2),
51  // create lavc fft buffers
52  m_dftL((FFTComplex*)av_malloc(sizeof(FFTComplex) * m_n * 2)),
53  m_dftR((FFTComplex*)av_malloc(sizeof(FFTComplex) * m_n * 2)),
54  // TODO only valid because blocksize is always 8192:
55  // (convert blocksize to log_2 (n) instead since FFmpeg only supports sizes that are powers of 2)
56  m_fftContextForward(av_fft_init(13, 0)),
57  m_fftContextReverse(av_fft_init(13, 1)),
58  m_src((FFTComplex*)av_malloc(sizeof(FFTComplex) * m_n * 2))
59 {
60  // resize our own buffers
61  m_frontR.resize(m_n);
62  m_frontL.resize(m_n);
63  m_avg.resize(m_n);
64  m_surR.resize(m_n);
65  m_surL.resize(m_n);
66  m_trueavg.resize(m_n);
67  m_xFs.resize(m_n);
68  m_yFs.resize(m_n);
69  m_inbuf[0].resize(m_n);
70  m_inbuf[1].resize(m_n);
71  for (unsigned c=0;c<6;c++) {
72  m_outbuf[c].resize(m_n);
73  m_filter[c].resize(m_n);
74  }
75  sample_rate(48000);
76  // generate the window function (square root of hann, b/c it is applied before and after the transform)
77  m_wnd.resize(m_n);
78  for (unsigned k=0;k<m_n;k++)
79  m_wnd[k] = sqrt(0.5F*(1-std::cos(2*PI*k/m_n))/m_n);
80  m_currentBuf = 0;
81  m_inbufs.fill(nullptr);
82  m_outbufs.fill(nullptr);
83  // set the default coefficients
84  surround_coefficients(0.8165,0.5774);
85  phase_mode(0);
86  separation(1,1);
87  steering_mode(true);
88  }
89 
90  // destructor
91  ~Impl() {
92  av_fft_end(m_fftContextForward);
93  av_fft_end(m_fftContextReverse);
94  av_free(m_src);
95  av_free(m_dftR);
96  av_free(m_dftL);
97  }
98 
99  float ** getInputBuffers()
100  {
103  return m_inbufs.data();
104  }
105 
106  float ** getOutputBuffers()
107  {
114  return m_outbufs.data();
115  }
116 
117  // decode a chunk of stereo sound, has to contain exactly blocksize samples
118  // center_width [0..1] distributes the center information towards the front left/right channels, 1=full distribution, 0=no distribution
119  // dimension [0..1] moves the soundfield backwards, 0=front, 1=side
120  // adaption_rate [0..1] determines how fast the steering gets adapted, 1=instantaneous, 0.1 = very slow adaption
121  void decode(float center_width, float dimension, float adaption_rate) {
122  // process first part
123  int index = m_currentBuf*m_halfN;
124  InputBufs in_second {&m_inbuf[0][index],&m_inbuf[1][index]};
125  m_currentBuf ^= 1;
126  index = m_currentBuf*m_halfN;
127  InputBufs in_first {&m_inbuf[0][index],&m_inbuf[1][index]};
128  add_output(in_first,in_second,center_width,dimension,adaption_rate,true);
129  // shift last half of input buffer to the beginning
130  }
131 
132  // flush the internal buffers
133  void flush() {
134  for (unsigned k=0;k<m_n;k++) {
135  for (auto & c : m_outbuf)
136  c[k] = 0;
137  m_inbuf[0][k] = 0;
138  m_inbuf[1][k] = 0;
139  }
140  }
141 
142  // set lfe filter params
143  void sample_rate(unsigned int srate) {
144  // lfe filter is just straight through band limited
145  unsigned int cutoff = (30*m_n)/srate;
146  for (unsigned f=0;f<=m_halfN;f++) {
147  if (f<cutoff)
148  m_filter[5][f] = 0.5*sqrt(0.5);
149  else
150  m_filter[5][f] = 0.0;
151  }
152  }
153 
154  // set the assumed surround mixing coefficients
155  void surround_coefficients(float a, float b) {
156  // calc the simple coefficients
157  m_surroundHigh = a;
158  m_surroundLow = b;
159  m_surroundBalance = (a-b)/(a+b);
160  m_surroundLevel = 1/(a+b);
161  // calc the linear coefficients
162  cfloat i(0,1);
163  cfloat u((a+b)*i);
164  cfloat v((b-a)*i);
165  cfloat n(0.25,0);
166  cfloat o(1,0);
167  m_a = (v-o)*n; m_b = (o-u)*n; m_c = (-o-v)*n; m_d = (o+u)*n;
168  m_e = (o+v)*n; m_f = (o+u)*n; m_g = (o-v)*n; m_h = (o-u)*n;
169  }
170 
171  // set the phase shifting mode
172  void phase_mode(unsigned mode) {
173  const std::array<std::array<float,2>,4> modes {{ {0,0}, {0,PI}, {PI,0}, {-PI/2,PI/2} }};
174  m_phaseOffsetL = modes[mode][0];
175  m_phaseOffsetR = modes[mode][1];
176  }
177 
178  // what steering mode should be chosen
179  void steering_mode(bool mode) { m_linearSteering = mode; }
180 
181  // set front & rear separation controls
182  void separation(float front, float rear) {
183  m_frontSeparation = front;
184  m_rearSeparation = rear;
185  }
186 
187 private:
188  // polar <-> cartesian coodinates conversion
189  static cfloat polar(float a, float p) { return {a*std::cos(p), a*std::sin(p)}; }
190  static float amplitude(FFTComplex z) { return std::hypot(z.re, z.im); }
191  static float phase(FFTComplex z) { return std::atan2(z.im, z.re); }
192 
194  static float clamp_unit_mag(float x) { return std::clamp(x, -1.0F, 1.0F); }
195 
196  // handle the output buffering for overlapped calls of block_decode
197  void add_output(InputBufs input1, InputBufs input2, float center_width, float dimension, float adaption_rate, bool /*result*/=false) {
198  // add the windowed data to the last 1/2 of the output buffer
199  OutputBufs out {m_outbuf[0].data(),m_outbuf[1].data(),m_outbuf[2].data(),m_outbuf[3].data(),m_outbuf[4].data(),m_outbuf[5].data()};
200  block_decode(input1,input2,out,center_width,dimension,adaption_rate);
201  }
202 
203  // CORE FUNCTION: decode a block of data
204  void block_decode(InputBufs input1, InputBufs input2, OutputBufs output, float center_width, float dimension, float adaption_rate) {
205  // 1. scale the input by the window function; this serves a dual purpose:
206  // - first it improves the FFT resolution b/c boundary discontinuities (and their frequencies) get removed
207  // - second it allows for smooth blending of varying filters between the blocks
208 
209  // the window also includes 1.0/sqrt(n) normalization
210  // concatenate copies of input1 and input2 for some undetermined reason
211  // input1 is in the rising half of the window
212  // input2 is in the falling half of the window
213  for (unsigned k = 0; k < m_halfN; k++)
214  {
215  m_dftL[k] = (FFTComplex){ .re = input1[0][k] * m_wnd[k], .im = (FFTSample)0 };
216  m_dftR[k] = (FFTComplex){ .re = input1[1][k] * m_wnd[k], .im = (FFTSample)0 };
217 
218  m_dftL[k + m_halfN] = (FFTComplex){ .re = input2[0][k] * m_wnd[k + m_halfN], .im = (FFTSample)0 };
219  m_dftR[k + m_halfN] = (FFTComplex){ .re = input2[1][k] * m_wnd[k + m_halfN], .im = (FFTSample)0 };
220  }
221 
222  // ... and tranform it into the frequency domain
223  av_fft_permute(m_fftContextForward, m_dftL);
224  av_fft_calc(m_fftContextForward, m_dftL);
225 
226  av_fft_permute(m_fftContextForward, m_dftR);
227  av_fft_calc(m_fftContextForward, m_dftR);
228 
229  // 2. compare amplitude and phase of each DFT bin and produce the X/Y coordinates in the sound field
230  // but dont do DC or N/2 component
231  for (unsigned f=0;f<m_halfN;f++) {
232  // get left/right amplitudes/phases
233  float ampL = amplitude(m_dftL[f]);
234  float ampR = amplitude(m_dftR[f]);
235  float phaseL = phase(m_dftL[f]);
236  float phaseR = phase(m_dftR[f]);
237 // if (ampL+ampR < epsilon)
238 // continue;
239 
240  // calculate the amplitude/phase difference
241  float ampDiff = clamp_unit_mag((ampL+ampR < epsilon) ? 0 : (ampR-ampL) / (ampR+ampL));
242  float phaseDiff = phaseL - phaseR;
243  if (phaseDiff < -PI) phaseDiff += 2*PI;
244  if (phaseDiff > PI) phaseDiff -= 2*PI;
245  phaseDiff = abs(phaseDiff);
246 
247  if (m_linearSteering) {
248  // --- this is the fancy new linear mode ---
249 
250  // get sound field x/y position
251  m_yFs[f] = get_yfs(ampDiff,phaseDiff);
252  m_xFs[f] = get_xfs(ampDiff,m_yFs[f]);
253 
254  // add dimension control
255  m_yFs[f] = clamp_unit_mag(m_yFs[f] - dimension);
256 
257  // add crossfeed control
258  m_xFs[f] = clamp_unit_mag(m_xFs[f] * (m_frontSeparation*(1+m_yFs[f])/2 + m_rearSeparation*(1-m_yFs[f])/2));
259 
260  // 3. generate frequency filters for each output channel
261  float left = (1-m_xFs[f])/2;
262  float right = (1+m_xFs[f])/2;
263  float front = (1+m_yFs[f])/2;
264  float back = (1-m_yFs[f])/2;
265  std::array<float, 5> volume
266  {
267  front * (left * center_width + std::max(0.0F, -m_xFs[f]) * (1.0F - center_width) ), // left
268  front * center_level * ( (1.0F - std::abs(m_xFs[f])) * (1.0F - center_width) ), // center
269  front * (right * center_width + std::max(0.0F, m_xFs[f]) * (1.0F - center_width) ), // right
270  back * m_surroundLevel * left, // left surround
271  back * m_surroundLevel * right // right surround
272  };
273 
274  // adapt the prior filter
275  for (unsigned c=0;c<5;c++)
276  m_filter[c][f] = (1-adaption_rate)*m_filter[c][f] + adaption_rate*volume[c];
277 
278  } else {
279  // --- this is the old & simple steering mode ---
280 
281  // calculate the amplitude/phase difference
282  float ampDiff = clamp_unit_mag((ampL+ampR < epsilon) ? 0 : (ampR-ampL) / (ampR+ampL));
283  float phaseDiff = phaseL - phaseR;
284  if (phaseDiff < -PI) phaseDiff += 2*PI;
285  if (phaseDiff > PI) phaseDiff -= 2*PI;
286  phaseDiff = abs(phaseDiff);
287 
288  // determine sound field x-position
289  m_xFs[f] = ampDiff;
290 
291  // determine preliminary sound field y-position from phase difference
292  m_yFs[f] = 1 - (phaseDiff/PI)*2;
293 
294  if (abs(m_xFs[f]) > m_surroundBalance) {
295  // blend linearly between the surrounds and the fronts if the balance exceeds the surround encoding balance
296  // this is necessary because the sound field is trapezoidal and will be stretched behind the listener
297  float frontness = (abs(m_xFs[f]) - m_surroundBalance)/(1-m_surroundBalance);
298  m_yFs[f] = (1-frontness) * m_yFs[f] + frontness * 1;
299  }
300 
301  // add dimension control
302  m_yFs[f] = clamp_unit_mag(m_yFs[f] - dimension);
303 
304  // add crossfeed control
305  m_xFs[f] = clamp_unit_mag(m_xFs[f] * (m_frontSeparation*(1+m_yFs[f])/2 + m_rearSeparation*(1-m_yFs[f])/2));
306 
307  // 3. generate frequency filters for each output channel, according to the signal position
308  // the sum of all channel volumes must be 1.0
309  float left = (1-m_xFs[f])/2;
310  float right = (1+m_xFs[f])/2;
311  float front = (1+m_yFs[f])/2;
312  float back = (1-m_yFs[f])/2;
313  std::array<float, 5> volume
314  {
315  front * (left * center_width + std::max(0.0F, -m_xFs[f]) * (1.0F-center_width)), // left
316  front * center_level * ( (1.0F - std::abs(m_xFs[f])) * (1.0F - center_width) ), // center
317  front * (right * center_width + std::max(0.0F, m_xFs[f]) * (1.0F-center_width)), // right
318  back * m_surroundLevel * std::clamp( (1.0F - (m_xFs[f] / m_surroundBalance) ) / 2.0F, 0.0F, 1.0F),// left surround
319  back * m_surroundLevel * std::clamp( (1.0F + (m_xFs[f] / m_surroundBalance) ) / 2.0F, 0.0F, 1.0F) // right surround
320  };
321 
322  // adapt the prior filter
323  for (unsigned c=0;c<5;c++)
324  m_filter[c][f] = (1-adaption_rate)*m_filter[c][f] + adaption_rate*volume[c];
325  }
326 
327  // ... and build the signal which we want to position
328  m_frontL[f] = polar(ampL+ampR,phaseL);
329  m_frontR[f] = polar(ampL+ampR,phaseR);
330  m_avg[f] = m_frontL[f] + m_frontR[f];
331  m_surL[f] = polar(ampL+ampR,phaseL+m_phaseOffsetL);
332  m_surR[f] = polar(ampL+ampR,phaseR+m_phaseOffsetR);
333  m_trueavg[f] = cfloat(m_dftL[f].re + m_dftR[f].re, m_dftL[f].im + m_dftR[f].im);
334  }
335 
336  // 4. distribute the unfiltered reference signals over the channels
337  apply_filter((m_frontL).data(), m_filter[0].data(),&output[0][0]); // front left
338  apply_filter((m_avg).data(), m_filter[1].data(),&output[1][0]); // front center
339  apply_filter((m_frontR).data(), m_filter[2].data(),&output[2][0]); // front right
340  apply_filter((m_surL).data(), m_filter[3].data(),&output[3][0]); // surround left
341  apply_filter((m_surR).data(), m_filter[4].data(),&output[4][0]); // surround right
342  apply_filter((m_trueavg).data(),m_filter[5].data(),&output[5][0]); // lfe
343  }
344 
345 #define FASTER_CALC
346  // map from amplitude difference and phase difference to yfs
347  static double get_yfs(double ampDiff, double phaseDiff) {
348  double x = 1-(((1-sqr(ampDiff))*phaseDiff)/M_PI*2);
349 #ifdef FASTER_CALC
350  double tanX = tan(x);
351  return 0.16468622925824683 + (0.5009268347818189*x) - (0.06462757726992101*x*x)
352  + (0.09170680403453149*x*x*x) + (0.2617754892323973*tanX) - (0.04180413533856156*sqr(tanX));
353 #else
354  return 0.16468622925824683 + (0.5009268347818189*x) - (0.06462757726992101*x*x)
355  + (0.09170680403453149*x*x*x) + (0.2617754892323973*tan(x)) - (0.04180413533856156*sqr(tan(x)));
356 #endif
357  }
358 
359  // map from amplitude difference and yfs to xfs
360  static double get_xfs(double ampDiff, double yfs) {
361  double x=ampDiff;
362  double y=yfs;
363 #ifdef FASTER_CALC
364  double tanX = tan(x);
365  double tanY = tan(y);
366  double asinX = asin(x);
367  double sinX = sin(x);
368  double sinY = sin(y);
369  double x3 = x*x*x;
370  double y2 = y*y;
371  double y3 = y*y2;
372  return (2.464833559224702*x) - (423.52131153259404*x*y) +
373  (67.8557858606918*x3*y) + (788.2429425544392*x*y2) -
374  (79.97650354902909*x3*y2) - (513.8966153850349*x*y3) +
375  (35.68117670186306*x3*y3) + (13867.406173420834*y*asinX) -
376  (2075.8237075786396*y2*asinX) - (908.2722068360281*y3*asinX) -
377  (12934.654772878019*asinX*sinY) - (13216.736529661162*y*tanX) +
378  (1288.6463247741938*y2*tanX) + (1384.372969378453*y3*tanX) +
379  (12699.231471126128*sinY*tanX) + (95.37131275594336*sinX*tanY) -
380  (91.21223198407546*tanX*tanY);
381 #else
382  return (2.464833559224702*x) - (423.52131153259404*x*y) +
383  (67.8557858606918*x*x*x*y) + (788.2429425544392*x*y*y) -
384  (79.97650354902909*x*x*x*y*y) - (513.8966153850349*x*y*y*y) +
385  (35.68117670186306*x*x*x*y*y*y) + (13867.406173420834*y*asin(x)) -
386  (2075.8237075786396*y*y*asin(x)) - (908.2722068360281*y*y*y*asin(x)) -
387  (12934.654772878019*asin(x)*sin(y)) - (13216.736529661162*y*tan(x)) +
388  (1288.6463247741938*y*y*tan(x)) + (1384.372969378453*y*y*y*tan(x)) +
389  (12699.231471126128*sin(y)*tan(x)) + (95.37131275594336*sin(x)*tan(y)) -
390  (91.21223198407546*tan(x)*tan(y));
391 #endif
392  }
393 
403  void apply_filter(cfloat *signal, const float *flt, float *target) {
404  // filter the signal
405  for (unsigned f = 0; f <= m_halfN; f++)
406  {
407  m_src[f].re = signal[f].real() * flt[f];
408  m_src[f].im = signal[f].imag() * flt[f];
409  }
410  // enforce odd symmetry
411  for (unsigned f = 1; f < m_halfN; f++)
412  {
413  m_src[m_n - f].re = m_src[f].re;
414  m_src[m_n - f].im = -m_src[f].im; // complex conjugate
415  }
416  av_fft_permute(m_fftContextReverse, m_src);
417  av_fft_calc(m_fftContextReverse, m_src);
418 
419  // add the result to target, windowed
420  for (unsigned int k = 0; k < m_halfN; k++)
421  {
422  // 1st part is overlap add
423  target[(m_currentBuf * m_halfN) + k] += m_src[k].re * m_wnd[k];
424  // 2nd part is set as has no history
425  target[((m_currentBuf ^ 1) * m_halfN) + k] = m_src[m_halfN + k].re * m_wnd[m_halfN + k];
426  }
427  }
428 
429  size_t m_n; // the block size
430  size_t m_halfN; // half block size precalculated
431  FFTContext *m_fftContextForward {nullptr};
432  FFTContext *m_fftContextReverse {nullptr};
433  // FFTs are computed in-place in these buffers on copies of the input
434  FFTComplex *m_dftL {nullptr};
435  FFTComplex *m_dftR {nullptr};
436  FFTComplex *m_src {nullptr};
437  // buffers
438  std::vector<cfloat> m_frontL,m_frontR,m_avg,m_surL,m_surR; // the signal (phase-corrected) in the frequency domain
439  std::vector<cfloat> m_trueavg; // for lfe generation
440  std::vector<float> m_xFs,m_yFs; // the feature space positions for each frequency bin
441  std::vector<float> m_wnd; // the window function, precalculated
442  std::array<std::vector<float>,6> m_filter; // a frequency filter for each output channel
443  std::array<std::vector<float>,2> m_inbuf; // the sliding input buffers
444  std::array<std::vector<float>,6> m_outbuf; // the sliding output buffers
445  // coefficients
446  float m_surroundHigh {0.0F}; // high surround mixing coefficient (e.g. 0.8165/0.5774)
447  float m_surroundLow {0.0F}; // low surround mixing coefficient (e.g. 0.8165/0.5774)
448  float m_surroundBalance {0.0F}; // the xfs balance that follows from the coeffs
449  float m_surroundLevel {0.0F}; // gain for the surround channels (follows from the coeffs
450  float m_phaseOffsetL {0.0F}; // phase shifts to be applied to the rear channels
451  float m_phaseOffsetR {0.0F}; // phase shifts to be applied to the rear channels
452  float m_frontSeparation {0.0F}; // front stereo separation
453  float m_rearSeparation {0.0F}; // rear stereo separation
454  bool m_linearSteering {false}; // whether the steering should be linear or not
455  cfloat m_a,m_b,m_c,m_d,m_e,m_f,m_g,m_h; // coefficients for the linear steering
456  int m_currentBuf; // specifies which buffer is 2nd half of input sliding buffer
457  InputBufs m_inbufs {}; // for passing back to driver
458  OutputBufs m_outbufs {}; // for passing back to driver
459 };
460 
461 
462 // implementation of the shell class
463 
464 fsurround_decoder::fsurround_decoder(unsigned blocksize): m_impl(new Impl(blocksize)) { }
465 
467 
468 void fsurround_decoder::decode(float center_width, float dimension, float adaption_rate) {
469  m_impl->decode(center_width,dimension,adaption_rate);
470 }
471 
473 
475 
476 void fsurround_decoder::phase_mode(unsigned mode) { m_impl->phase_mode(mode); }
477 
479 
480 void fsurround_decoder::separation(float front, float rear) { m_impl->separation(front,rear); }
481 
483 {
484  return m_impl->getInputBuffers();
485 }
486 
488 {
489  return m_impl->getOutputBuffers();
490 }
491 
492 void fsurround_decoder::sample_rate(unsigned int samplerate)
493 {
494  m_impl->sample_rate(samplerate);
495 }
fsurround_decoder::Impl::flush
void flush()
Definition: el_processor.cpp:133
fsurround_decoder::Impl::get_yfs
static double get_yfs(double ampDiff, double phaseDiff)
Definition: el_processor.cpp:347
fsurround_decoder::Impl
Definition: el_processor.cpp:44
fsurround_decoder::Impl::m_surL
std::vector< cfloat > m_surL
Definition: el_processor.cpp:438
fsurround_decoder::sample_rate
void sample_rate(unsigned int samplerate)
Definition: el_processor.cpp:492
fsurround_decoder::Impl::m_c
cfloat m_c
Definition: el_processor.cpp:455
epsilon
static const float epsilon
Definition: el_processor.cpp:37
fsurround_decoder::Impl::sample_rate
void sample_rate(unsigned int srate)
Definition: el_processor.cpp:143
fsurround_decoder::Impl::amplitude
static float amplitude(FFTComplex z)
Definition: el_processor.cpp:190
back
static guint32 * back
Definition: goom_core.cpp:25
fsurround_decoder::Impl::m_dftR
FFTComplex * m_dftR
Definition: el_processor.cpp:435
fsurround_decoder::Impl::m_outbufs
OutputBufs m_outbufs
Definition: el_processor.cpp:458
fsurround_decoder::Impl::m_fftContextForward
FFTContext * m_fftContextForward
Definition: el_processor.cpp:431
fsurround_decoder::~fsurround_decoder
~fsurround_decoder()
Definition: el_processor.cpp:466
fsurround_decoder::Impl::m_trueavg
std::vector< cfloat > m_trueavg
Definition: el_processor.cpp:439
fsurround_decoder::Impl::m_filter
std::array< std::vector< float >, 6 > m_filter
Definition: el_processor.cpp:442
fsurround_decoder::m_impl
Impl * m_impl
Definition: el_processor.h:70
fsurround_decoder::Impl::m_surR
std::vector< cfloat > m_surR
Definition: el_processor.cpp:438
fsurround_decoder::Impl::m_rearSeparation
float m_rearSeparation
Definition: el_processor.cpp:453
cfloat
std::complex< float > cfloat
Definition: el_processor.cpp:32
el_processor.h
fsurround_decoder::Impl::m_inbufs
InputBufs m_inbufs
Definition: el_processor.cpp:457
x3
static int x3
Definition: mythsocket.cpp:52
fsurround_decoder::flush
void flush()
Definition: el_processor.cpp:472
InputBufs
std::array< float *, 2 > InputBufs
Definition: el_processor.cpp:33
fsurround_decoder::decode
void decode(float center_width=1, float dimension=0, float adaption_rate=1)
Definition: el_processor.cpp:468
fsurround_decoder::Impl::m_wnd
std::vector< float > m_wnd
Definition: el_processor.cpp:441
sqr
T sqr(T x)
Definition: el_processor.cpp:41
fsurround_decoder::Impl::m_h
cfloat m_h
Definition: el_processor.cpp:455
fsurround_decoder::separation
void separation(float front, float rear)
Definition: el_processor.cpp:480
fsurround_decoder::Impl::m_linearSteering
bool m_linearSteering
Definition: el_processor.cpp:454
fsurround_decoder::fsurround_decoder
fsurround_decoder(unsigned blocksize=8192)
Definition: el_processor.cpp:464
fsurround_decoder::Impl::add_output
void add_output(InputBufs input1, InputBufs input2, float center_width, float dimension, float adaption_rate, bool=false)
Definition: el_processor.cpp:197
fsurround_decoder::Impl::m_surroundLow
float m_surroundLow
Definition: el_processor.cpp:447
fsurround_decoder::surround_coefficients
void surround_coefficients(float a, float b)
Definition: el_processor.cpp:474
fsurround_decoder::Impl::getInputBuffers
float ** getInputBuffers()
Definition: el_processor.cpp:99
fsurround_decoder::Impl::m_b
cfloat m_b
Definition: el_processor.cpp:455
fsurround_decoder::Impl::Impl
Impl(unsigned blocksize=8192)
Definition: el_processor.cpp:48
fsurround_decoder::Impl::m_g
cfloat m_g
Definition: el_processor.cpp:455
hardwareprofile.config.p
p
Definition: config.py:33
fsurround_decoder::Impl::phase
static float phase(FFTComplex z)
Definition: el_processor.cpp:191
fsurround_decoder::Impl::decode
void decode(float center_width, float dimension, float adaption_rate)
Definition: el_processor.cpp:121
center_level
static const float center_level
Definition: el_processor.cpp:38
fsurround_decoder::Impl::clamp_unit_mag
static float clamp_unit_mag(float x)
Clamp the input to the interval [-1, 1], i.e. clamp the magnitude to the unit interval [0,...
Definition: el_processor.cpp:194
fsurround_decoder::Impl::m_surroundLevel
float m_surroundLevel
Definition: el_processor.cpp:449
fsurround_decoder::Impl::m_surroundBalance
float m_surroundBalance
Definition: el_processor.cpp:448
fsurround_decoder::Impl::polar
static cfloat polar(float a, float p)
Definition: el_processor.cpp:189
fsurround_decoder::Impl::m_yFs
std::vector< float > m_yFs
Definition: el_processor.cpp:440
fsurround_decoder::Impl::m_frontSeparation
float m_frontSeparation
Definition: el_processor.cpp:452
fsurround_decoder::Impl::m_inbuf
std::array< std::vector< float >, 2 > m_inbuf
Definition: el_processor.cpp:443
fsurround_decoder::Impl::~Impl
~Impl()
Definition: el_processor.cpp:91
clamp
static eu8 clamp(eu8 value, eu8 low, eu8 high)
Definition: pxsup2dast.c:204
fsurround_decoder::Impl::phase_mode
void phase_mode(unsigned mode)
Definition: el_processor.cpp:172
fsurround_decoder::Impl::m_surroundHigh
float m_surroundHigh
Definition: el_processor.cpp:446
fsurround_decoder::Impl::get_xfs
static double get_xfs(double ampDiff, double yfs)
Definition: el_processor.cpp:360
fsurround_decoder::Impl::m_frontR
std::vector< cfloat > m_frontR
Definition: el_processor.cpp:438
fsurround_decoder::Impl::steering_mode
void steering_mode(bool mode)
Definition: el_processor.cpp:179
fsurround_decoder::Impl::m_halfN
size_t m_halfN
Definition: el_processor.cpp:430
fsurround_decoder::Impl::m_dftL
FFTComplex * m_dftL
Definition: el_processor.cpp:434
fsurround_decoder::Impl::m_a
cfloat m_a
Definition: el_processor.cpp:455
fsurround_decoder::steering_mode
void steering_mode(bool mode)
Definition: el_processor.cpp:478
fsurround_decoder::Impl::m_phaseOffsetL
float m_phaseOffsetL
Definition: el_processor.cpp:450
fsurround_decoder::phase_mode
void phase_mode(unsigned mode)
Definition: el_processor.cpp:476
fsurround_decoder::Impl::m_f
cfloat m_f
Definition: el_processor.cpp:455
fsurround_decoder::Impl::separation
void separation(float front, float rear)
Definition: el_processor.cpp:182
fsurround_decoder::Impl::m_fftContextReverse
FFTContext * m_fftContextReverse
Definition: el_processor.cpp:432
OutputBufs
std::array< float *, 6 > OutputBufs
Definition: el_processor.cpp:34
fsurround_decoder::Impl::getOutputBuffers
float ** getOutputBuffers()
Definition: el_processor.cpp:106
fsurround_decoder::getOutputBuffers
float ** getOutputBuffers()
Definition: el_processor.cpp:487
fsurround_decoder::Impl::m_currentBuf
int m_currentBuf
Definition: el_processor.cpp:456
fsurround_decoder::Impl::block_decode
void block_decode(InputBufs input1, InputBufs input2, OutputBufs output, float center_width, float dimension, float adaption_rate)
Definition: el_processor.cpp:204
PI
static const float PI
Definition: el_processor.cpp:36
fsurround_decoder::Impl::m_d
cfloat m_d
Definition: el_processor.cpp:455
fsurround_decoder::Impl::m_outbuf
std::array< std::vector< float >, 6 > m_outbuf
Definition: el_processor.cpp:444
fsurround_decoder::Impl::m_n
size_t m_n
Definition: el_processor.cpp:429
fsurround_decoder::Impl::m_xFs
std::vector< float > m_xFs
Definition: el_processor.cpp:440
fsurround_decoder::Impl::m_frontL
std::vector< cfloat > m_frontL
Definition: el_processor.cpp:438
fsurround_decoder::Impl::m_avg
std::vector< cfloat > m_avg
Definition: el_processor.cpp:438
fsurround_decoder::Impl::m_phaseOffsetR
float m_phaseOffsetR
Definition: el_processor.cpp:451
output
#define output
Definition: synaesthesia.cpp:223
fsurround_decoder::Impl::surround_coefficients
void surround_coefficients(float a, float b)
Definition: el_processor.cpp:155
fsurround_decoder::Impl::m_src
FFTComplex * m_src
Used only in apply_filter.
Definition: el_processor.cpp:436
fsurround_decoder::Impl::apply_filter
void apply_filter(cfloat *signal, const float *flt, float *target)
Filter the complex source signal in the frequency domain and add it to the time domain target signal.
Definition: el_processor.cpp:403
M_PI
static constexpr double M_PI
Definition: goom_tools.h:9
fsurround_decoder::getInputBuffers
float ** getInputBuffers()
Definition: el_processor.cpp:482
fsurround_decoder::Impl::m_e
cfloat m_e
Definition: el_processor.cpp:455