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