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  srate(srate),
77  bufs(nullptr),
78  decoder(nullptr),
79  in_count(0),
80  out_count(0),
81  processed(true),
82  processed_size(0),
83  surround_mode(smode),
84  latency_frames(0),
85  channels(0)
86 {
87  LOG(VB_AUDIO, LOG_DEBUG,
88  QString("FreeSurround::FreeSurround rate %1 moviemode %2")
89  .arg(srate).arg(moviemode));
90 
91  if (moviemode)
92  {
93  params.phasemode = 1;
94  params.center_width = 25;
95  params.dimension = 0.5;
96  }
97  else
98  {
99  params.center_width = 65;
100  params.dimension = 0.3;
101  }
102  switch (surround_mode)
103  {
105  params.steering = 0;
106  break;
108  params.steering = 1;
110  break;
111  default:
112  break;
113  }
114 
115  bufs = new buffers(block_size/2);
116  open();
117 #ifdef SPEAKERTEST
118  channel_select++;
119  if (channel_select>=6)
120  channel_select = 0;
121  LOG(VB_AUDIO, LOG_DEBUG,
122  QString("FreeSurround::FreeSurround channel_select %1")
123  .arg(channel_select));
124 #endif
125  LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::FreeSurround done"));
126 }
127 
129 {
130  if (decoder)
131  {
136  }
137 }
138 
140  int32_t dimension) :
141  center_width(center_width),
142  dimension(dimension),
143  coeff_a(0.8165),coeff_b(0.5774),
144  phasemode(0),
145  steering(1),
146  front_sep(100),
147  rear_sep(100)
148 {
149 }
150 
152 {
153  LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::~FreeSurround"));
154  close();
155  delete bufs;
156  bufs = nullptr;
157  LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::~FreeSurround done"));
158 }
159 
160 uint FreeSurround::putFrames(void* buffer, uint numFrames, uint numChannels)
161 {
162  uint i = 0;
163  int ic = in_count;
164  int bs = block_size/2;
165  bool process = true;
166  auto *samples = (float *)buffer;
167  // demultiplex
168 
169  float **inputs = decoder->getInputBuffers();
170  float *lt = &inputs[0][ic];
171  float *rt = &inputs[1][ic];
172 
173  if ((surround_mode != SurroundModePassive) && (ic+numFrames > bs))
174  {
175  numFrames = bs - ic;
176  }
177 
178  switch (numChannels)
179  {
180  case 1:
181  switch (surround_mode)
182  {
183  case SurroundModePassive:
185  for (i = 0; i < numFrames && ic < bs; i++,ic++)
186  {
187  // should be -7dB to keep power level the same
188  // but we bump the level a tad.
189  bufs->m_c[ic] = bufs->m_l[ic] = bufs->m_r[ic] = samples[i] * m6db;
190  bufs->m_ls[ic] = bufs->m_rs[ic] = bufs->m_c[ic];
191  }
192  process = false;
193  break;
194  default:
195  for (i=0; i<numFrames; i++)
196  *lt++ = *rt++ = *samples++;
197  process = true;
198  break;
199  }
200  channels = 6;
201  break;
202 
203  case 2:
204  switch (surround_mode)
205  {
206  case SurroundModePassive:
207  for (i = 0; i < numFrames && ic < bs; i++,ic++)
208  {
209  float lt = *samples++;
210  float rt = *samples++;
211  bufs->m_l[ic] = lt;
212  bufs->m_lfe[ic] = bufs->m_c[ic] = (lt+rt) * m3db;
213  bufs->m_r[ic] = rt;
214  // surround channels receive out-of-phase
215  bufs->m_ls[ic] = (rt-lt) * 0.5;
216  bufs->m_rs[ic] = (lt-rt) * 0.5;
217  }
218  process = false;
219  break;
221  for (i = 0; i < numFrames && ic < bs; i++,ic++)
222  {
223  float lt = *samples++;
224  float rt = *samples++;
225  bufs->m_l[ic] = lt * m3db;
226  bufs->m_lfe[ic] = bufs->m_c[ic] = (lt+rt) * m3db;
227  bufs->m_r[ic] = rt * m3db;
228  bufs->m_ls[ic] = bufs->m_l[ic];
229  bufs->m_rs[ic] = bufs->m_r[ic];
230  }
231  process = false;
232  break;
233  default:
234  for (i=0; i<numFrames; i++)
235  {
236  *lt++ = *samples++;
237  *rt++ = *samples++;
238  }
239  process = true;
240  break;
241  }
242  channels = 6;
243  break;
244 
245  case 5:
246  for (i = 0; i < numFrames && ic < bs; i++,ic++)
247  {
248  float lt = *samples++;
249  float rt = *samples++;
250  float c = *samples++;
251  float ls = *samples++;
252  float rs = *samples++;
253  bufs->m_l[ic] = lt;
254  bufs->m_lfe[ic] = 0.0F;
255  bufs->m_c[ic] = c;
256  bufs->m_r[ic] = rt;
257  bufs->m_ls[ic] = ls;
258  bufs->m_rs[ic] = rs;
259  }
260  process = false;
261  channels = 6;
262  break;
263 
264  case 7:
265  for (i = 0; i < numFrames && ic < bs; i++,ic++)
266  {
267  // 3F3R-LFE L R C LFE BC LS RS
268  float lt = *samples++;
269  float rt = *samples++;
270  float c = *samples++;
271  float lfe = *samples++;
272  float cs = *samples++;
273  float ls = *samples++;
274  float rs = *samples++;
275  bufs->m_l[ic] = lt;
276  bufs->m_lfe[ic] = lfe;
277  bufs->m_c[ic] = c;
278  bufs->m_r[ic] = rt;
279  bufs->m_ls[ic] = ls;
280  bufs->m_rs[ic] = rs;
281  bufs->m_rls[ic] = bufs->m_rrs[ic] = cs * m3db;
282  }
283  process = false;
284  channels = 8;
285  break;
286  default:
287  break;
288  }
289  if (process)
290  {
291  ic += numFrames;
292  if (ic != bs)
293  {
294  // dont modify unless no processing is to be done
295  // for audiotime consistency
296  in_count = ic;
297  }
298  else
299  {
300  processed = process;
301  // process_block takes some time so dont update in and out count
302  // before its finished so that Audiotime is correctly calculated
303  process_block();
304  in_count = 0;
305  out_count = bs;
306  processed_size = bs;
308  }
309  }
310  else
311  {
312  in_count = 0;
313  out_count = processed_size = ic;
314  processed = false;
315  latency_frames = 0;
316  }
317 
318  LOG(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
319  QString("FreeSurround::putFrames %1 #ch %2 used %3 generated %4")
320  .arg(numFrames).arg(numChannels).arg(i).arg(out_count));
321 
322  return i;
323 }
324 
325 uint FreeSurround::receiveFrames(void *buffer, uint maxFrames)
326 {
327  uint oc = out_count;
328  if (maxFrames > oc) maxFrames = oc;
329  uint outindex = processed_size - oc;
330  auto *output = (float *)buffer;
331  if (channels == 8)
332  {
333  float *l = &bufs->m_l[outindex];
334  float *c = &bufs->m_c[outindex];
335  float *r = &bufs->m_r[outindex];
336  float *ls = &bufs->m_ls[outindex];
337  float *rs = &bufs->m_rs[outindex];
338  float *lfe = &bufs->m_lfe[outindex];
339  float *rls = &bufs->m_rls[outindex];
340  float *rrs = &bufs->m_rrs[outindex];
341  for (uint i = 0; i < maxFrames; i++)
342  {
343 // printf("1:%f 2:%f 3:%f 4:%f 5:%f 6:%f 7:%f 8:%f\n",
344 // *l, *r, *c, *lfe, *rls, *rrs, *ls, *rs);
345 
346  // 3F4-LFE L R C LFE Rls Rrs LS RS
347  *output++ = *l++;
348  *output++ = *r++;
349  *output++ = *c++;
350  *output++ = *lfe++;
351  *output++ = *rls++;
352  *output++ = *rrs++;
353  *output++ = *ls++;
354  *output++ = *rs++;
355  }
356  oc -= maxFrames;
357  }
358  else // channels == 6
359  {
360  if (processed)
361  {
362  float** outputs = decoder->getOutputBuffers();
363  float *l = &outputs[0][outindex];
364  float *c = &outputs[1][outindex];
365  float *r = &outputs[2][outindex];
366  float *ls = &outputs[3][outindex];
367  float *rs = &outputs[4][outindex];
368  float *lfe = &outputs[5][outindex];
369  for (uint i = 0; i < maxFrames; i++)
370  {
371  *output++ = *l++;
372  *output++ = *r++;
373  *output++ = *c++;
374  *output++ = *lfe++;
375  *output++ = *ls++;
376  *output++ = *rs++;
377  }
378  oc -= maxFrames;
379  }
380  else
381  {
382  float *l = &bufs->m_l[outindex];
383  float *c = &bufs->m_c[outindex];
384  float *r = &bufs->m_r[outindex];
385  float *ls = &bufs->m_ls[outindex];
386  float *rs = &bufs->m_rs[outindex];
387  float *lfe = &bufs->m_lfe[outindex];
388  for (uint i = 0; i < maxFrames; i++)
389  {
390  *output++ = *l++;
391  *output++ = *r++;
392  *output++ = *c++;
393  *output++ = *lfe++;
394  *output++ = *ls++;
395  *output++ = *rs++;
396  }
397  oc -= maxFrames;
398  }
399  }
400  out_count = oc;
401  LOG(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
402  QString("FreeSurround::receiveFrames %1").arg(maxFrames));
403  return maxFrames;
404 }
405 
407 {
408  // process the data
409  try
410  {
411  if (decoder)
412  {
414  }
415  }
416  catch(...)
417  {
418  }
419 }
420 
422 {
423  // returns in usec
424  if (latency_frames == 0)
425  return 0;
426  return decoder ? ((long long)(latency_frames + in_count)*1000000)/(2*srate) : 0;
427 }
428 
430 {
431  if (decoder)
432  decoder->flush();
433  bufs->clear();
434 }
435 
436 // load the lib and initialize the interface
438 {
439  if (!decoder)
440  {
442  decoder->flush();
443  if (bufs)
444  bufs->clear();
446  }
447  SetParams();
448 }
449 
451 {
452  delete decoder;
453  decoder = nullptr;
454 }
455 
457 {
458  return in_count;
459 }
460 
462 {
463  return out_count;
464 }
465 
467 {
468  if (processed)
469  return in_count + out_count + (block_size/2);
470  return in_count + out_count;
471 }
472 
474 {
475  return block_size/2;
476 }
477 
static const float m3db
SurroundMode surround_mode
Definition: freesurround.h:84
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
uint putFrames(void *buffer, uint numFrames, uint numChannels)
static uint64_t samples[4]
Definition: element.c:45
std::vector< float > m_rrs
uint frameLatency()
void process_block()
struct buffers * bufs
Definition: freesurround.h:78
class fsurround_decoder * decoder
Definition: freesurround.h:79
static const float m6db
std::vector< float > m_c
std::vector< float > m_rs
void clear()
std::vector< float > m_rls
uint receiveFrames(void *buffer, uint maxFrames)
unsigned char m_r
Definition: ParseText.cpp:329
unsigned int block_size
void steering_mode(bool mode)
int latency_frames
Definition: freesurround.h:85
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
struct FreeSurround::fsurround_params params
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
fsurround_params(int32_t center_width=100, int32_t dimension=0)
int processed_size
Definition: freesurround.h:83
void sample_rate(unsigned int samplerate)
static uint framesPerBlock()
void resize(unsigned int s)
float ** getOutputBuffers()
#define output