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 using namespace std;
31 
32 #include "compat.h"
33 #include "mythlogging.h"
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 = 0.5;
88  }
89  else
90  {
92  m_params.dimension = 0.3;
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  int ic = m_inCount;
151  int 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.5;
203  m_bufs->m_rs[ic] = (lt-rt) * 0.5;
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  return m_decoder ? ((long long)(m_latencyFrames + m_inCount)*1000000)/(2*m_srate) : 0;
414 }
415 
417 {
418  if (m_decoder)
419  m_decoder->flush();
420  m_bufs->clear();
421 }
422 
423 // load the lib and initialize the interface
425 {
426  if (!m_decoder)
427  {
429  m_decoder->flush();
430  if (m_bufs)
431  m_bufs->clear();
433  }
434  SetParams();
435 }
436 
438 {
439  delete m_decoder;
440  m_decoder = nullptr;
441 }
442 
444 {
445  return m_inCount;
446 }
447 
449 {
450  return m_outCount;
451 }
452 
454 {
455  if (m_processed)
456  return m_inCount + m_outCount + (block_size/2);
457  return m_inCount + m_outCount;
458 }
459 
461 {
462  return block_size/2;
463 }
464 
static const float m3db
uint putFrames(void *buffer, uint numFrames, uint numChannels)
static uint64_t samples[4]
Definition: element.c:45
int m_latencyFrames
Definition: freesurround.h:87
std::vector< float > m_rrs
uint frameLatency()
SurroundMode m_surroundMode
Definition: freesurround.h:86
void process_block()
int m_processedSize
Definition: freesurround.h:85
class fsurround_decoder * m_decoder
Definition: freesurround.h:81
static const float m6db
std::vector< float > m_c
std::vector< float > m_rs
struct buffers * m_bufs
Definition: freesurround.h:80
void clear()
std::vector< float > m_rls
uint receiveFrames(void *buffer, uint maxFrames)
unsigned char m_r
Definition: ParseText.cpp:329
bool m_processed
Definition: freesurround.h:84
unsigned int block_size
void steering_mode(bool mode)
buffers(unsigned int s)
static const float m7db
void surround_coefficients(float a, float b)
float ** getInputBuffers()
unsigned int uint
Definition: compat.h:140
std::vector< float > m_ls
FreeSurround(uint srate, bool moviemode, SurroundMode mode)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
long long getLatency()
static const unsigned default_block_size
std::vector< float > m_l
void decode(float center_width=1, float dimension=0, float adaption_rate=1)
std::vector< float > m_r
void separation(float front, float rear)
static const float center_level
uint numUnprocessedFrames()
void phase_mode(unsigned mode)
#define SURROUND_BUFSIZE
Definition: freesurround.h:24
std::vector< float > m_lfe
struct FreeSurround::fsurround_params m_params
fsurround_params(int32_t center_width=100, int32_t dimension=0)
void sample_rate(unsigned int samplerate)
static uint framesPerBlock()
void resize(unsigned int s)
float ** getOutputBuffers()
#define output