MythTV  0.27pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
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 // stupidity countermeasure...
51 template<class T> T pop_back(std::list<T> &l)
52 {
53  T result(l.back());
54  l.pop_back();
55  return result;
56 }
57 
58 // a pool, where the DSP can throw its objects at after it got deleted and
59 // get them back when it is recreated...
61 {
62 public:
63  typedef void* (*callback)();
64  // initialize
65  object_pool(callback cbf):construct(cbf) { }
67  {
68  for (std::map<void*,void*>::iterator i=pool.begin(),e=pool.end();
69  i != e; i++)
70  delete i->second;
71  for (std::list<void*>::iterator i=freelist.begin(),e=freelist.end();
72  i != e; i++)
73  delete *i;
74  }
75  // (re)acquire an object
76  void *acquire(void *who)
77  {
78  std::map<void*,void*>::iterator i(pool.find(who));
79  if (i != pool.end())
80  return i->second;
81  else
82  if (!freelist.empty())
83  return pool.insert(std::make_pair(who,pop_back(freelist)))
84  .first->second;
85  else
86  return pool.insert(std::make_pair(who,construct()))
87  .first->second;
88  }
89  // release an object into the wild
90  void release(void *who)
91  {
92  std::map<void*,void*>::iterator i(pool.find(who));
93  if (i != pool.end()) {
94  freelist.push_back(i->second);
95  pool.erase(i);
96  }
97  }
98 public:
99  callback construct; // object constructor callback
100  std::list<void*> freelist; // list of available objects
101  std::map<void*,void*> pool; // pool of used objects, by class
102 };
103 
104 // buffers which we usually need (and want to share between plugin lifespans)
105 struct buffers
106 {
107  buffers(unsigned int s):
108  l(s),r(s),c(s),ls(s),rs(s),lfe(s), rls(s), rrs(s) { }
109  void resize(unsigned int s)
110  {
111  l.resize(s); r.resize(s); lfe.resize(s);
112  ls.resize(s); rs.resize(s); c.resize(s);
113  rls.resize(s); rrs.resize(s);
114  }
115  void clear()
116  {
117  l.clear(); r.clear(); lfe.clear();
118  ls.clear(); rs.clear(); c.clear();
119  rls.clear(); rrs.clear();
120  }
121  std::vector<float> l,r,c,ls,rs,lfe,cs,lcs,rcs,
122  rls, rrs; // for demultiplexing
123 };
124 
125 // construction methods
126 void *new_decoder() { return new fsurround_decoder(block_size); }
127 void *new_buffers() { return new buffers(block_size/2); }
128 
131 
132 //#define SPEAKERTEST
133 #ifdef SPEAKERTEST
134 int channel_select = -1;
135 #endif
136 
137 FreeSurround::FreeSurround(uint srate, bool moviemode, SurroundMode smode) :
138  srate(srate),
139  open_(false),
140  initialized_(false),
141  bufs(NULL),
142  decoder(0),
143  in_count(0),
144  out_count(0),
145  processed(true),
146  processed_size(0),
147  surround_mode(smode),
148  latency_frames(0)
149 {
150  LOG(VB_AUDIO, LOG_DEBUG,
151  QString("FreeSurround::FreeSurround rate %1 moviemode %2")
152  .arg(srate).arg(moviemode));
153 
154  if (moviemode)
155  {
156  params.phasemode = 1;
157  params.center_width = 25;
158  params.dimension = 0.5;
159  }
160  else
161  {
162  params.center_width = 65;
163  params.dimension = 0.3;
164  }
165  switch (surround_mode)
166  {
168  params.steering = 0;
169  break;
171  params.steering = 1;
173  break;
174  default:
175  break;
176  }
177 
178  bufs = (buffers*)bp.acquire((void*)1);
179  open();
180 #ifdef SPEAKERTEST
181  channel_select++;
182  if (channel_select>=6)
183  channel_select = 0;
184  LOG(VB_AUDIO, LOG_DEBUG,
185  QString("FreeSurround::FreeSurround channel_select %1")
186  .arg(channel_select));
187 #endif
188  LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::FreeSurround done"));
189 }
190 
192 {
193  if (decoder)
194  {
195  decoder->steering_mode(params.steering);
196  decoder->phase_mode(params.phasemode);
197  decoder->surround_coefficients(params.coeff_a, params.coeff_b);
198  decoder->separation(params.front_sep/100.0,params.rear_sep/100.0);
199  }
200 }
201 
203  int32_t dimension) :
204  center_width(center_width),
205  dimension(dimension),
206  coeff_a(0.8165),coeff_b(0.5774),
207  phasemode(0),
208  steering(1),
209  front_sep(100),
210  rear_sep(100)
211 {
212 }
213 
215 {
216  LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::~FreeSurround"));
217  close();
218  if (bufs)
219  {
220  bp.release((void*)1);
221  bufs = NULL;
222  }
223  LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::~FreeSurround done"));
224 }
225 
227 {
228  int i = 0;
229  int ic = in_count;
230  int bs = block_size/2;
231  bool process = true;
232  float *samples = (float *)buffer;
233  // demultiplex
234 
235  float **inputs = decoder->getInputBuffers();
236  float *lt = &inputs[0][ic];
237  float *rt = &inputs[1][ic];
238 
239  if ((surround_mode != SurroundModePassive) && (ic+numFrames > bs))
240  {
241  numFrames = bs - ic;
242  }
243 
244  switch (numChannels)
245  {
246  case 1:
247  switch (surround_mode)
248  {
249  case SurroundModePassive:
251  for (i = 0; i < numFrames && ic < bs; i++,ic++)
252  {
253  // should be -7dB to keep power level the same
254  // but we bump the level a tad.
255  bufs->c[ic] = bufs->l[ic] = bufs->r[ic] = samples[i] * m6db;
256  bufs->ls[ic] = bufs->rs[ic] = bufs->c[ic];
257  }
258  process = false;
259  break;
260  default:
261  for (i=0; i<numFrames; i++)
262  *lt++ = *rt++ = *samples++;
263  process = true;
264  break;
265  }
266  channels = 6;
267  break;
268 
269  case 2:
270  switch (surround_mode)
271  {
272  case SurroundModePassive:
273  for (i = 0; i < numFrames && ic < bs; i++,ic++)
274  {
275  float lt = *samples++;
276  float rt = *samples++;
277  bufs->l[ic] = lt;
278  bufs->lfe[ic] = bufs->c[ic] = (lt+rt) * m3db;
279  bufs->r[ic] = rt;
280  // surround channels receive out-of-phase
281  bufs->ls[ic] = (rt-lt) * 0.5;
282  bufs->rs[ic] = (lt-rt) * 0.5;
283  }
284  process = false;
285  break;
287  for (i = 0; i < numFrames && ic < bs; i++,ic++)
288  {
289  float lt = *samples++;
290  float rt = *samples++;
291  bufs->l[ic] = lt * m3db;
292  bufs->lfe[ic] = bufs->c[ic] = (lt+rt) * m3db;
293  bufs->r[ic] = rt * m3db;
294  bufs->ls[ic] = bufs->l[ic];
295  bufs->rs[ic] = bufs->r[ic];
296  }
297  process = false;
298  break;
299  default:
300  for (i=0; i<numFrames; i++)
301  {
302  *lt++ = *samples++;
303  *rt++ = *samples++;
304  }
305  process = true;
306  break;
307  }
308  channels = 6;
309  break;
310 
311  case 5:
312  for (i = 0; i < numFrames && ic < bs; i++,ic++)
313  {
314  float lt = *samples++;
315  float rt = *samples++;
316  float c = *samples++;
317  float ls = *samples++;
318  float rs = *samples++;
319  bufs->l[ic] = lt;
320  bufs->lfe[ic] = 0.0f;
321  bufs->c[ic] = c;
322  bufs->r[ic] = rt;
323  bufs->ls[ic] = ls;
324  bufs->rs[ic] = rs;
325  }
326  process = false;
327  channels = 6;
328  break;
329 
330  case 7:
331  for (i = 0; i < numFrames && ic < bs; i++,ic++)
332  {
333  // 3F3R-LFE L R C LFE BC LS RS
334  float lt = *samples++;
335  float rt = *samples++;
336  float c = *samples++;
337  float lfe = *samples++;
338  float cs = *samples++;
339  float ls = *samples++;
340  float rs = *samples++;
341  bufs->l[ic] = lt;
342  bufs->lfe[ic] = lfe;
343  bufs->c[ic] = c;
344  bufs->r[ic] = rt;
345  bufs->ls[ic] = ls;
346  bufs->rs[ic] = rs;
347  bufs->rls[ic] = bufs->rrs[ic] = cs * m3db;
348  }
349  process = false;
350  channels = 8;
351  break;
352  default:
353  break;
354  }
355  if (process)
356  {
357  ic += numFrames;
358  if (ic != bs)
359  {
360  // dont modify unless no processing is to be done
361  // for audiotime consistency
362  in_count = ic;
363  }
364  else
365  {
366  processed = process;
367  // process_block takes some time so dont update in and out count
368  // before its finished so that Audiotime is correctly calculated
369  process_block();
370  in_count = 0;
371  out_count = bs;
372  processed_size = bs;
374  }
375  }
376  else
377  {
378  in_count = 0;
379  out_count = processed_size = ic;
380  processed = false;
381  latency_frames = 0;
382  }
383 
384  LOG(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
385  QString("FreeSurround::putFrames %1 #ch %2 used %3 generated %4")
386  .arg(numFrames).arg(numChannels).arg(i).arg(out_count));
387 
388  return i;
389 }
390 
392 {
393  uint i;
394  uint oc = out_count;
395  if (maxFrames > oc) maxFrames = oc;
396  uint outindex = processed_size - oc;
397  float *output = (float *)buffer;
398  if (channels == 8)
399  {
400  float *l = &bufs->l[outindex];
401  float *c = &bufs->c[outindex];
402  float *r = &bufs->r[outindex];
403  float *ls = &bufs->ls[outindex];
404  float *rs = &bufs->rs[outindex];
405  float *lfe = &bufs->lfe[outindex];
406  float *rls = &bufs->rls[outindex];
407  float *rrs = &bufs->rrs[outindex];
408  for (i = 0; i < maxFrames; i++)
409  {
410 // printf("1:%f 2:%f 3:%f 4:%f 5:%f 6:%f 7:%f 8:%f\n",
411 // *l, *r, *c, *lfe, *rls, *rrs, *ls, *rs);
412 
413  // 3F4-LFE L R C LFE Rls Rrs LS RS
414  *output++ = *l++;
415  *output++ = *r++;
416  *output++ = *c++;
417  *output++ = *lfe++;
418  *output++ = *rls++;
419  *output++ = *rrs++;
420  *output++ = *ls++;
421  *output++ = *rs++;
422  }
423  oc -= maxFrames;
424  outindex += maxFrames;
425  }
426  else // channels == 6
427  {
428  if (processed)
429  {
430  float** outputs = decoder->getOutputBuffers();
431  float *l = &outputs[0][outindex];
432  float *c = &outputs[1][outindex];
433  float *r = &outputs[2][outindex];
434  float *ls = &outputs[3][outindex];
435  float *rs = &outputs[4][outindex];
436  float *lfe = &outputs[5][outindex];
437  for (i = 0; i < maxFrames; i++)
438  {
439  *output++ = *l++;
440  *output++ = *r++;
441  *output++ = *c++;
442  *output++ = *lfe++;
443  *output++ = *ls++;
444  *output++ = *rs++;
445  }
446  oc -= maxFrames;
447  outindex += maxFrames;
448  }
449  else
450  {
451  float *l = &bufs->l[outindex];
452  float *c = &bufs->c[outindex];
453  float *r = &bufs->r[outindex];
454  float *ls = &bufs->ls[outindex];
455  float *rs = &bufs->rs[outindex];
456  float *lfe = &bufs->lfe[outindex];
457  for (i = 0; i < maxFrames; i++)
458  {
459  *output++ = *l++;
460  *output++ = *r++;
461  *output++ = *c++;
462  *output++ = *lfe++;
463  *output++ = *ls++;
464  *output++ = *rs++;
465  }
466  oc -= maxFrames;
467  outindex += maxFrames;
468  }
469  }
470  out_count = oc;
471  LOG(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
472  QString("FreeSurround::receiveFrames %1").arg(maxFrames));
473  return maxFrames;
474 }
475 
477 {
478  // process the data
479  try
480  {
481  if (decoder)
482  {
483  decoder->decode(params.center_width/100.0,params.dimension/100.0);
484  }
485  }
486  catch(...)
487  {
488  }
489 }
490 
492 {
493  // returns in usec
494  if (latency_frames == 0)
495  return 0;
496  return decoder ? ((latency_frames + in_count)*1000000)/(2*srate) : 0;
497 }
498 
500 {
501  if (decoder)
502  decoder->flush();
503  bufs->clear();
504 }
505 
506 // load the lib and initialize the interface
508 {
509  if (!decoder)
510  {
511  decoder = (fsurround_decoder*)dp.acquire((void*)1);
512  decoder->flush();
513  if (bufs)
514  bufs->clear();
516  }
517  SetParams();
518 }
519 
521 {
522  if (decoder)
523  {
524  dp.release(this);
525  decoder = 0;
526  }
527 }
528 
530 {
531  return in_count;
532 }
533 
535 {
536  return out_count;
537 }
538 
540 {
541  if (processed)
542  return in_count + out_count + (block_size/2);
543  else
544  return in_count + out_count;
545 }
546 
548 {
549  return block_size/2;
550 }
551