MythTV  master
freesurround.cpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 2007 Christian Kothe, Mark Spieth
3 Copyright (C) 2010-2011 Jean-Yves Avenard
4 
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 
20 #include <cstdio>
21 #include <cstdlib>
22 #include <cerrno>
23 #include <cmath>
24 
25 #include <iostream>
26 #include <sstream>
27 #include <vector>
28 #include <list>
29 #include <map>
30 
31 #include "libmythbase/compat.h"
33 
34 #include "freesurround.h"
35 #include "el_processor.h"
36 
37 #include <QString>
38 #include <QDateTime>
39 
40 // our default internal block size, in floats
41 static const unsigned default_block_size = SURROUND_BUFSIZE;
42 // Gain of center and lfe channels in passive mode (sqrt 0.5)
43 //static const float center_level = 0.707107;
44 static const float m3db = 0.7071067811865476F; // 3dB = SQRT(2)
45 static const float m6db = 0.5; // 6dB = SQRT(4)
46 //static const float m7db = 0.44721359549996; // 7dB = SQRT(5)
47 
49 
50 struct buffers
51 {
52  explicit buffers(unsigned int s):
53  m_l(s),m_r(s),m_c(s),m_ls(s),m_rs(s),m_lfe(s), m_rls(s), m_rrs(s) { }
54  void resize(unsigned int s)
55  {
56  m_l.resize(s); m_r.resize(s); m_lfe.resize(s);
57  m_ls.resize(s); m_rs.resize(s); m_c.resize(s);
58  m_rls.resize(s); m_rrs.resize(s);
59  }
60  void clear()
61  {
62  m_l.clear(); m_r.clear(); m_lfe.clear();
63  m_ls.clear(); m_rs.clear(); m_c.clear();
64  m_rls.clear(); m_rrs.clear();
65  }
66  std::vector<float> m_l,m_r,m_c,m_ls,m_rs,m_lfe,m_cs,m_lcs,m_rcs,
67  m_rls, m_rrs; // for demultiplexing
68 };
69 
70 //#define SPEAKERTEST
71 #ifdef SPEAKERTEST
72 int channel_select = -1;
73 #endif
74 
75 FreeSurround::FreeSurround(uint srate, bool moviemode, SurroundMode smode) :
76  m_srate(srate),
77  m_surroundMode(smode)
78 {
79  LOG(VB_AUDIO, LOG_DEBUG,
80  QString("FreeSurround::FreeSurround rate %1 moviemode %2")
81  .arg(srate).arg(moviemode));
82 
83  if (moviemode)
84  {
85  m_params.phasemode = 1;
87  m_params.dimension = 50;
88  }
89  else
90  {
92  m_params.dimension = 30;
93  }
94  switch (m_surroundMode)
95  {
97  m_params.steering = 0;
98  break;
100  m_params.steering = 1;
102  break;
103  default:
104  break;
105  }
106 
107  m_bufs = new buffers(block_size/2);
108  open();
109 #ifdef SPEAKERTEST
110  channel_select++;
111  if (channel_select>=6)
112  channel_select = 0;
113  LOG(VB_AUDIO, LOG_DEBUG,
114  QString("FreeSurround::FreeSurround channel_select %1")
115  .arg(channel_select));
116 #endif
117  LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::FreeSurround done"));
118 }
119 
121 {
122  if (m_decoder)
123  {
128  }
129 }
130 
132  int32_t dimension) :
133  center_width(center_width),
134  dimension(dimension)
135 {
136 }
137 
139 {
140  LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::~FreeSurround"));
141  close();
142  delete m_bufs;
143  m_bufs = nullptr;
144  LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::~FreeSurround done"));
145 }
146 
147 uint FreeSurround::putFrames(void* buffer, uint numFrames, uint numChannels)
148 {
149  uint i = 0;
150  uint ic = m_inCount;
151  uint bs = block_size/2;
152  bool process = true;
153  auto *samples = (float *)buffer;
154  // demultiplex
155 
156  float **inputs = m_decoder->getInputBuffers();
157  float *lt = &inputs[0][ic];
158  float *rt = &inputs[1][ic];
159 
160  if ((m_surroundMode != SurroundModePassive) && (ic+numFrames > bs))
161  {
162  numFrames = bs - ic;
163  }
164 
165  switch (numChannels)
166  {
167  case 1:
168  switch (m_surroundMode)
169  {
170  case SurroundModePassive:
172  for (i = 0; i < numFrames && ic < bs; i++,ic++)
173  {
174  // should be -7dB to keep power level the same
175  // but we bump the level a tad.
176  m_bufs->m_c[ic] = m_bufs->m_l[ic] = m_bufs->m_r[ic] = samples[i] * m6db;
177  m_bufs->m_ls[ic] = m_bufs->m_rs[ic] = m_bufs->m_c[ic];
178  }
179  process = false;
180  break;
181  default:
182  for (i=0; i<numFrames; i++)
183  *lt++ = *rt++ = *samples++;
184  process = true;
185  break;
186  }
187  m_channels = 6;
188  break;
189 
190  case 2:
191  switch (m_surroundMode)
192  {
193  case SurroundModePassive:
194  for (i = 0; i < numFrames && ic < bs; i++,ic++)
195  {
196  float lt = *samples++;
197  float rt = *samples++;
198  m_bufs->m_l[ic] = lt;
199  m_bufs->m_lfe[ic] = m_bufs->m_c[ic] = (lt+rt) * m3db;
200  m_bufs->m_r[ic] = rt;
201  // surround channels receive out-of-phase
202  m_bufs->m_ls[ic] = (rt-lt) * 0.5F;
203  m_bufs->m_rs[ic] = (lt-rt) * 0.5F;
204  }
205  process = false;
206  break;
208  for (i = 0; i < numFrames && ic < bs; i++,ic++)
209  {
210  float lt = *samples++;
211  float rt = *samples++;
212  m_bufs->m_l[ic] = lt * m3db;
213  m_bufs->m_lfe[ic] = m_bufs->m_c[ic] = (lt+rt) * m3db;
214  m_bufs->m_r[ic] = rt * m3db;
215  m_bufs->m_ls[ic] = m_bufs->m_l[ic];
216  m_bufs->m_rs[ic] = m_bufs->m_r[ic];
217  }
218  process = false;
219  break;
220  default:
221  for (i=0; i<numFrames; i++)
222  {
223  *lt++ = *samples++;
224  *rt++ = *samples++;
225  }
226  process = true;
227  break;
228  }
229  m_channels = 6;
230  break;
231 
232  case 5:
233  for (i = 0; i < numFrames && ic < bs; i++,ic++)
234  {
235  float lt = *samples++;
236  float rt = *samples++;
237  float c = *samples++;
238  float ls = *samples++;
239  float rs = *samples++;
240  m_bufs->m_l[ic] = lt;
241  m_bufs->m_lfe[ic] = 0.0F;
242  m_bufs->m_c[ic] = c;
243  m_bufs->m_r[ic] = rt;
244  m_bufs->m_ls[ic] = ls;
245  m_bufs->m_rs[ic] = rs;
246  }
247  process = false;
248  m_channels = 6;
249  break;
250 
251  case 7:
252  for (i = 0; i < numFrames && ic < bs; i++,ic++)
253  {
254  // 3F3R-LFE L R C LFE BC LS RS
255  float lt = *samples++;
256  float rt = *samples++;
257  float c = *samples++;
258  float lfe = *samples++;
259  float cs = *samples++;
260  float ls = *samples++;
261  float rs = *samples++;
262  m_bufs->m_l[ic] = lt;
263  m_bufs->m_lfe[ic] = lfe;
264  m_bufs->m_c[ic] = c;
265  m_bufs->m_r[ic] = rt;
266  m_bufs->m_ls[ic] = ls;
267  m_bufs->m_rs[ic] = rs;
268  m_bufs->m_rls[ic] = m_bufs->m_rrs[ic] = cs * m3db;
269  }
270  process = false;
271  m_channels = 8;
272  break;
273  default:
274  break;
275  }
276  if (process)
277  {
278  ic += numFrames;
279  if (ic != bs)
280  {
281  // dont modify unless no processing is to be done
282  // for audiotime consistency
283  m_inCount = ic;
284  }
285  else
286  {
287  m_processed = process;
288  // process_block takes some time so dont update in and out count
289  // before its finished so that Audiotime is correctly calculated
290  process_block();
291  m_inCount = 0;
292  m_outCount = bs;
293  m_processedSize = bs;
295  }
296  }
297  else
298  {
299  m_inCount = 0;
301  m_processed = false;
302  m_latencyFrames = 0;
303  }
304 
305  LOG(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
306  QString("FreeSurround::putFrames %1 #ch %2 used %3 generated %4")
307  .arg(numFrames).arg(numChannels).arg(i).arg(m_outCount));
308 
309  return i;
310 }
311 
312 uint FreeSurround::receiveFrames(void *buffer, uint maxFrames)
313 {
314  uint oc = m_outCount;
315  if (maxFrames > oc) maxFrames = oc;
316  uint outindex = m_processedSize - oc;
317  auto *output = (float *)buffer;
318  if (m_channels == 8)
319  {
320  float *l = &m_bufs->m_l[outindex];
321  float *c = &m_bufs->m_c[outindex];
322  float *r = &m_bufs->m_r[outindex];
323  float *ls = &m_bufs->m_ls[outindex];
324  float *rs = &m_bufs->m_rs[outindex];
325  float *lfe = &m_bufs->m_lfe[outindex];
326  float *rls = &m_bufs->m_rls[outindex];
327  float *rrs = &m_bufs->m_rrs[outindex];
328  for (uint i = 0; i < maxFrames; i++)
329  {
330 // printf("1:%f 2:%f 3:%f 4:%f 5:%f 6:%f 7:%f 8:%f\n",
331 // *l, *r, *c, *lfe, *rls, *rrs, *ls, *rs);
332 
333  // 3F4-LFE L R C LFE Rls Rrs LS RS
334  *output++ = *l++;
335  *output++ = *r++;
336  *output++ = *c++;
337  *output++ = *lfe++;
338  *output++ = *rls++;
339  *output++ = *rrs++;
340  *output++ = *ls++;
341  *output++ = *rs++;
342  }
343  oc -= maxFrames;
344  }
345  else // channels == 6
346  {
347  if (m_processed)
348  {
349  float** outputs = m_decoder->getOutputBuffers();
350  float *l = &outputs[0][outindex];
351  float *c = &outputs[1][outindex];
352  float *r = &outputs[2][outindex];
353  float *ls = &outputs[3][outindex];
354  float *rs = &outputs[4][outindex];
355  float *lfe = &outputs[5][outindex];
356  for (uint i = 0; i < maxFrames; i++)
357  {
358  *output++ = *l++;
359  *output++ = *r++;
360  *output++ = *c++;
361  *output++ = *lfe++;
362  *output++ = *ls++;
363  *output++ = *rs++;
364  }
365  oc -= maxFrames;
366  }
367  else
368  {
369  float *l = &m_bufs->m_l[outindex];
370  float *c = &m_bufs->m_c[outindex];
371  float *r = &m_bufs->m_r[outindex];
372  float *ls = &m_bufs->m_ls[outindex];
373  float *rs = &m_bufs->m_rs[outindex];
374  float *lfe = &m_bufs->m_lfe[outindex];
375  for (uint i = 0; i < maxFrames; i++)
376  {
377  *output++ = *l++;
378  *output++ = *r++;
379  *output++ = *c++;
380  *output++ = *lfe++;
381  *output++ = *ls++;
382  *output++ = *rs++;
383  }
384  oc -= maxFrames;
385  }
386  }
387  m_outCount = oc;
388  LOG(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
389  QString("FreeSurround::receiveFrames %1").arg(maxFrames));
390  return maxFrames;
391 }
392 
394 {
395  // process the data
396  try
397  {
398  if (m_decoder)
399  {
401  }
402  }
403  catch(...)
404  {
405  }
406 }
407 
409 {
410  // returns in usec
411  if (m_latencyFrames == 0)
412  return 0;
413  if (m_decoder == nullptr)
414  return 0;
415  return ((m_latencyFrames + m_inCount) * 1000000LL) / (2LL * m_srate);
416 }
417 
419 {
420  if (m_decoder)
421  m_decoder->flush();
422  m_bufs->clear();
423 }
424 
425 // load the lib and initialize the interface
427 {
428  if (!m_decoder)
429  {
431  m_decoder->flush();
432  if (m_bufs)
433  m_bufs->clear();
435  }
436  SetParams();
437 }
438 
440 {
441  delete m_decoder;
442  m_decoder = nullptr;
443 }
444 
446 {
447  return m_inCount;
448 }
449 
451 {
452  return m_outCount;
453 }
454 
456 {
457  if (m_processed)
458  return m_inCount + m_outCount + (block_size/2);
459  return m_inCount + m_outCount;
460 }
461 
463 {
464  return block_size/2;
465 }
466 
FreeSurround::SurroundModeActiveLinear
@ SurroundModeActiveLinear
Definition: freesurround.h:33
fsurround_decoder::sample_rate
void sample_rate(unsigned int samplerate)
Definition: el_processor.cpp:489
FreeSurround::fsurround_params::coeff_a
float coeff_a
Definition: freesurround.h:66
FreeSurround::fsurround_params::dimension
int32_t dimension
Definition: freesurround.h:65
FreeSurround::SetParams
void SetParams()
Definition: freesurround.cpp:120
FreeSurround::SurroundMode
SurroundMode
Definition: freesurround.h:29
buffers::m_l
std::vector< float > m_l
Definition: freesurround.cpp:66
buffers::buffers
buffers(unsigned int s)
Definition: freesurround.cpp:52
FreeSurround::fsurround_params::steering
int32_t steering
Definition: freesurround.h:69
buffers::m_rcs
std::vector< float > m_rcs
Definition: freesurround.cpp:66
buffers::m_rs
std::vector< float > m_rs
Definition: freesurround.cpp:66
FreeSurround::m_decoder
class fsurround_decoder * m_decoder
Definition: freesurround.h:81
FreeSurround::getLatency
long long getLatency()
Definition: freesurround.cpp:408
FreeSurround::SurroundModeActiveSimple
@ SurroundModeActiveSimple
Definition: freesurround.h:32
FreeSurround::fsurround_params::phasemode
int32_t phasemode
Definition: freesurround.h:68
buffers::m_lfe
std::vector< float > m_lfe
Definition: freesurround.cpp:66
FreeSurround::close
void close()
Definition: freesurround.cpp:439
FreeSurround::numFrames
uint numFrames() const
Definition: freesurround.cpp:450
FreeSurround::open
void open()
Definition: freesurround.cpp:426
FreeSurround::SurroundModePassiveHall
@ SurroundModePassiveHall
Definition: freesurround.h:34
el_processor.h
fsurround_decoder::flush
void flush()
Definition: el_processor.cpp:469
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
SURROUND_BUFSIZE
static constexpr uint16_t SURROUND_BUFSIZE
Definition: freesurround.h:24
buffers::m_c
std::vector< float > m_c
Definition: freesurround.cpp:66
fsurround_decoder::decode
void decode(float center_width=1, float dimension=0, float adaption_rate=1)
Definition: el_processor.cpp:465
freesurround.h
FreeSurround::fsurround_params::front_sep
int32_t front_sep
Definition: freesurround.h:70
FreeSurround::putFrames
uint putFrames(void *buffer, uint numFrames, uint numChannels)
Definition: freesurround.cpp:147
FreeSurround::numUnprocessedFrames
uint numUnprocessedFrames() const
Definition: freesurround.cpp:445
buffers::m_r
std::vector< float > m_r
Definition: freesurround.cpp:66
fsurround_decoder::separation
void separation(float front, float rear)
Definition: el_processor.cpp:477
FreeSurround::m_surroundMode
SurroundMode m_surroundMode
Definition: freesurround.h:86
FreeSurround::process_block
void process_block()
Definition: freesurround.cpp:393
fsurround_decoder::surround_coefficients
void surround_coefficients(float a, float b)
Definition: el_processor.cpp:471
FreeSurround::fsurround_params::rear_sep
int32_t rear_sep
Definition: freesurround.h:71
mythlogging.h
FreeSurround::SurroundModePassive
@ SurroundModePassive
Definition: freesurround.h:31
buffers::m_rls
std::vector< float > m_rls
Definition: freesurround.cpp:67
FreeSurround::fsurround_params::center_width
int32_t center_width
Definition: freesurround.h:64
buffers::m_rrs
std::vector< float > m_rrs
Definition: freesurround.cpp:67
compat.h
FreeSurround::fsurround_params::fsurround_params
fsurround_params(int32_t center_width=100, int32_t dimension=0)
Definition: freesurround.cpp:131
FreeSurround::framesPerBlock
static uint framesPerBlock()
Definition: freesurround.cpp:462
m6db
static const float m6db
Definition: freesurround.cpp:45
FreeSurround::frameLatency
uint frameLatency() const
Definition: freesurround.cpp:455
buffers::clear
void clear()
Definition: freesurround.cpp:60
buffers::m_lcs
std::vector< float > m_lcs
Definition: freesurround.cpp:66
FreeSurround::m_outCount
int m_outCount
Definition: freesurround.h:83
default_block_size
static const unsigned default_block_size
Definition: freesurround.cpp:41
FreeSurround::flush
void flush()
Definition: freesurround.cpp:418
uint
unsigned int uint
Definition: compat.h:81
FreeSurround::m_processed
bool m_processed
Definition: freesurround.h:84
FreeSurround::m_channels
int m_channels
Definition: freesurround.h:88
fsurround_decoder
Definition: el_processor.h:23
buffers
Definition: freesurround.cpp:50
block_size
unsigned int block_size
Definition: freesurround.cpp:48
fsurround_decoder::steering_mode
void steering_mode(bool mode)
Definition: el_processor.cpp:475
buffers::resize
void resize(unsigned int s)
Definition: freesurround.cpp:54
m3db
static const float m3db
Definition: freesurround.cpp:44
fsurround_decoder::phase_mode
void phase_mode(unsigned mode)
Definition: el_processor.cpp:473
FreeSurround::fsurround_params::coeff_b
float coeff_b
Definition: freesurround.h:67
FreeSurround::m_srate
uint m_srate
Definition: freesurround.h:77
FreeSurround::m_inCount
int m_inCount
Definition: freesurround.h:82
fsurround_decoder::getOutputBuffers
float ** getOutputBuffers()
Definition: el_processor.cpp:484
FreeSurround::m_processedSize
int m_processedSize
Definition: freesurround.h:85
FreeSurround::FreeSurround
FreeSurround(uint srate, bool moviemode, SurroundMode mode)
Definition: freesurround.cpp:75
FreeSurround::m_bufs
struct buffers * m_bufs
Definition: freesurround.h:80
buffers::m_ls
std::vector< float > m_ls
Definition: freesurround.cpp:66
FreeSurround::m_latencyFrames
int m_latencyFrames
Definition: freesurround.h:87
output
#define output
Definition: synaesthesia.cpp:220
FreeSurround::receiveFrames
uint receiveFrames(void *buffer, uint maxFrames)
Definition: freesurround.cpp:312
samples
static const std::array< const uint64_t, 4 > samples
Definition: element.cpp:46
fsurround_decoder::getInputBuffers
float ** getInputBuffers()
Definition: el_processor.cpp:479
FreeSurround::~FreeSurround
~FreeSurround()
Definition: freesurround.cpp:138
FreeSurround::m_params
struct FreeSurround::fsurround_params m_params
buffers::m_cs
std::vector< float > m_cs
Definition: freesurround.cpp:66