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