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  buffers(unsigned int s):
53  l(s),r(s),c(s),ls(s),rs(s),lfe(s), rls(s), rrs(s) { }
54  void resize(unsigned int s)
55  {
56  l.resize(s); r.resize(s); lfe.resize(s);
57  ls.resize(s); rs.resize(s); c.resize(s);
58  rls.resize(s); rrs.resize(s);
59  }
60  void clear()
61  {
62  l.clear(); r.clear(); lfe.clear();
63  ls.clear(); rs.clear(); c.clear();
64  rls.clear(); rrs.clear();
65  }
66  std::vector<float> l,r,c,ls,rs,lfe,cs,lcs,rcs,
67  rls, 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  float *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->c[ic] = bufs->l[ic] = bufs->r[ic] = samples[i] * m6db;
190  bufs->ls[ic] = bufs->rs[ic] = bufs->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->l[ic] = lt;
212  bufs->lfe[ic] = bufs->c[ic] = (lt+rt) * m3db;
213  bufs->r[ic] = rt;
214  // surround channels receive out-of-phase
215  bufs->ls[ic] = (rt-lt) * 0.5;
216  bufs->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->l[ic] = lt * m3db;
226  bufs->lfe[ic] = bufs->c[ic] = (lt+rt) * m3db;
227  bufs->r[ic] = rt * m3db;
228  bufs->ls[ic] = bufs->l[ic];
229  bufs->rs[ic] = bufs->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->l[ic] = lt;
254  bufs->lfe[ic] = 0.0F;
255  bufs->c[ic] = c;
256  bufs->r[ic] = rt;
257  bufs->ls[ic] = ls;
258  bufs->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->l[ic] = lt;
276  bufs->lfe[ic] = lfe;
277  bufs->c[ic] = c;
278  bufs->r[ic] = rt;
279  bufs->ls[ic] = ls;
280  bufs->rs[ic] = rs;
281  bufs->rls[ic] = bufs->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 i;
328  uint oc = out_count;
329  if (maxFrames > oc) maxFrames = oc;
330  uint outindex = processed_size - oc;
331  float *output = (float *)buffer;
332  if (channels == 8)
333  {
334  float *l = &bufs->l[outindex];
335  float *c = &bufs->c[outindex];
336  float *r = &bufs->r[outindex];
337  float *ls = &bufs->ls[outindex];
338  float *rs = &bufs->rs[outindex];
339  float *lfe = &bufs->lfe[outindex];
340  float *rls = &bufs->rls[outindex];
341  float *rrs = &bufs->rrs[outindex];
342  for (i = 0; i < maxFrames; i++)
343  {
344 // printf("1:%f 2:%f 3:%f 4:%f 5:%f 6:%f 7:%f 8:%f\n",
345 // *l, *r, *c, *lfe, *rls, *rrs, *ls, *rs);
346 
347  // 3F4-LFE L R C LFE Rls Rrs LS RS
348  *output++ = *l++;
349  *output++ = *r++;
350  *output++ = *c++;
351  *output++ = *lfe++;
352  *output++ = *rls++;
353  *output++ = *rrs++;
354  *output++ = *ls++;
355  *output++ = *rs++;
356  }
357  oc -= maxFrames;
358  }
359  else // channels == 6
360  {
361  if (processed)
362  {
363  float** outputs = decoder->getOutputBuffers();
364  float *l = &outputs[0][outindex];
365  float *c = &outputs[1][outindex];
366  float *r = &outputs[2][outindex];
367  float *ls = &outputs[3][outindex];
368  float *rs = &outputs[4][outindex];
369  float *lfe = &outputs[5][outindex];
370  for (i = 0; i < maxFrames; i++)
371  {
372  *output++ = *l++;
373  *output++ = *r++;
374  *output++ = *c++;
375  *output++ = *lfe++;
376  *output++ = *ls++;
377  *output++ = *rs++;
378  }
379  oc -= maxFrames;
380  }
381  else
382  {
383  float *l = &bufs->l[outindex];
384  float *c = &bufs->c[outindex];
385  float *r = &bufs->r[outindex];
386  float *ls = &bufs->ls[outindex];
387  float *rs = &bufs->rs[outindex];
388  float *lfe = &bufs->lfe[outindex];
389  for (i = 0; i < maxFrames; i++)
390  {
391  *output++ = *l++;
392  *output++ = *r++;
393  *output++ = *c++;
394  *output++ = *lfe++;
395  *output++ = *ls++;
396  *output++ = *rs++;
397  }
398  oc -= maxFrames;
399  }
400  }
401  out_count = oc;
402  LOG(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
403  QString("FreeSurround::receiveFrames %1").arg(maxFrames));
404  return maxFrames;
405 }
406 
408 {
409  // process the data
410  try
411  {
412  if (decoder)
413  {
415  }
416  }
417  catch(...)
418  {
419  }
420 }
421 
423 {
424  // returns in usec
425  if (latency_frames == 0)
426  return 0;
427  return decoder ? ((long long)(latency_frames + in_count)*1000000)/(2*srate) : 0;
428 }
429 
431 {
432  if (decoder)
433  decoder->flush();
434  bufs->clear();
435 }
436 
437 // load the lib and initialize the interface
439 {
440  if (!decoder)
441  {
443  decoder->flush();
444  if (bufs)
445  bufs->clear();
447  }
448  SetParams();
449 }
450 
452 {
453  delete decoder;
454  decoder = nullptr;
455 }
456 
458 {
459  return in_count;
460 }
461 
463 {
464  return out_count;
465 }
466 
468 {
469  if (processed)
470  return in_count + out_count + (block_size/2);
471  return in_count + out_count;
472 }
473 
475 {
476  return block_size/2;
477 }
478 
std::vector< float > rls
static const float m3db
SurroundMode surround_mode
Definition: freesurround.h:84
std::vector< float > rrs
uint putFrames(void *buffer, uint numFrames, uint numChannels)
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
static uint64_t samples[4]
Definition: element.c:45
std::vector< float > c
std::vector< float > rs
uint frameLatency()
void process_block()
struct buffers * bufs
Definition: freesurround.h:78
unsigned int uint
Definition: compat.h:140
std::vector< float > r
class fsurround_decoder * decoder
Definition: freesurround.h:79
unsigned char r
Definition: ParseText.cpp:329
static const float m6db
void clear()
uint receiveFrames(void *buffer, uint maxFrames)
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()
std::vector< float > lfe
std::vector< float > l
std::vector< float > 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
void decode(float center_width=1, float dimension=0, float adaption_rate=1)
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
fsurround_params(int32_t center_width=100, int32_t dimension=0)
int processed_size
Definition: freesurround.h:83
void sample_rate(unsigned int samplerate)
uint framesPerBlock()
void resize(unsigned int s)
float ** getOutputBuffers()
#define output