MythTV master
freesurround.cpp
Go to the documentation of this file.
1/*
2Copyright (C) 2007 Christian Kothe, Mark Spieth
3Copyright (C) 2010-2011 Jean-Yves Avenard
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18*/
19#include "freesurround.h"
20
21#include <algorithm>
22#include <cstdio>
23#include <cstdlib>
24#include <cerrno>
25#include <cmath>
26
27#include <iostream>
28#include <sstream>
29#include <vector>
30#include <list>
31#include <map>
32
34
35#include <QString>
36
38
39// our default internal block size, in floats
40static 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;
43static const float m3db = 0.7071067811865476F; // 3dB = SQRT(2)
44static const float m6db = 0.5; // 6dB = SQRT(4)
45//static const float m7db = 0.44721359549996; // 7dB = SQRT(5)
46
48
49struct 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
71int channel_select = -1;
72#endif
73
74FreeSurround::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 {
87 }
88 else
89 {
92 }
93 switch (m_surroundMode)
94 {
97 break;
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{
132 LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::~FreeSurround"));
133 close();
134 delete m_bufs;
135 m_bufs = nullptr;
136 LOG(VB_AUDIO, LOG_DEBUG, QString("FreeSurround::~FreeSurround done"));
137}
138
139uint FreeSurround::putFrames(void* buffer, uint numFrames, uint numChannels)
140{
141 uint i = 0;
142 uint ic = m_inCount;
143 uint bs = block_size/2;
144 bool process = true;
145 auto *samples = (float *)buffer;
146 // demultiplex
147
148 if ((m_surroundMode != SurroundModePassive) && (ic+numFrames > bs))
149 {
150 numFrames = bs - ic;
151 }
152
153 switch (numChannels)
154 {
155 case 1:
156 switch (m_surroundMode)
157 {
160 for (i = 0; i < numFrames && ic < bs; i++,ic++)
161 {
162 // should be -7dB to keep power level the same
163 // but we bump the level a tad.
164 m_bufs->m_c[ic] = m_bufs->m_l[ic] = m_bufs->m_r[ic] = samples[i] * m6db;
165 m_bufs->m_ls[ic] = m_bufs->m_rs[ic] = m_bufs->m_c[ic];
166 }
167 process = false;
168 break;
169 default:
170 float **inputs = m_decoder->getInputBuffers();
171 float *lt = &inputs[0][ic];
172 float *rt = &inputs[1][ic];
173 for (i=0; i<numFrames; i++)
174 *lt++ = *rt++ = *samples++;
175 process = true;
176 break;
177 }
178 m_channels = 6;
179 break;
180
181 case 2:
182 switch (m_surroundMode)
183 {
185 for (i = 0; i < numFrames && ic < bs; i++,ic++)
186 {
187 float lt = *samples++;
188 float rt = *samples++;
189 m_bufs->m_l[ic] = lt;
190 m_bufs->m_lfe[ic] = m_bufs->m_c[ic] = (lt+rt) * m3db;
191 m_bufs->m_r[ic] = rt;
192 // surround channels receive out-of-phase
193 m_bufs->m_ls[ic] = (rt-lt) * 0.5F;
194 m_bufs->m_rs[ic] = (lt-rt) * 0.5F;
195 }
196 process = false;
197 break;
199 for (i = 0; i < numFrames && ic < bs; i++,ic++)
200 {
201 float lt = *samples++;
202 float rt = *samples++;
203 m_bufs->m_l[ic] = lt * m3db;
204 m_bufs->m_lfe[ic] = m_bufs->m_c[ic] = (lt+rt) * m3db;
205 m_bufs->m_r[ic] = rt * m3db;
206 m_bufs->m_ls[ic] = m_bufs->m_l[ic];
207 m_bufs->m_rs[ic] = m_bufs->m_r[ic];
208 }
209 process = false;
210 break;
211 default:
212 float **inputs = m_decoder->getInputBuffers();
213 float *lt = &inputs[0][ic];
214 float *rt = &inputs[1][ic];
215 for (i=0; i<numFrames; i++)
216 {
217 *lt++ = *samples++;
218 *rt++ = *samples++;
219 }
220 process = true;
221 break;
222 }
223 m_channels = 6;
224 break;
225
226 case 5:
227 for (i = 0; i < numFrames && ic < bs; i++,ic++)
228 {
229 float lt = *samples++;
230 float rt = *samples++;
231 float c = *samples++;
232 float ls = *samples++;
233 float rs = *samples++;
234 m_bufs->m_l[ic] = lt;
235 m_bufs->m_lfe[ic] = 0.0F;
236 m_bufs->m_c[ic] = c;
237 m_bufs->m_r[ic] = rt;
238 m_bufs->m_ls[ic] = ls;
239 m_bufs->m_rs[ic] = rs;
240 }
241 process = false;
242 m_channels = 6;
243 break;
244
245 case 7:
246 for (i = 0; i < numFrames && ic < bs; i++,ic++)
247 {
248 // 3F3R-LFE L R C LFE BC LS RS
249 float lt = *samples++;
250 float rt = *samples++;
251 float c = *samples++;
252 float lfe = *samples++;
253 float cs = *samples++;
254 float ls = *samples++;
255 float rs = *samples++;
256 m_bufs->m_l[ic] = lt;
257 m_bufs->m_lfe[ic] = lfe;
258 m_bufs->m_c[ic] = c;
259 m_bufs->m_r[ic] = rt;
260 m_bufs->m_ls[ic] = ls;
261 m_bufs->m_rs[ic] = rs;
262 m_bufs->m_rls[ic] = m_bufs->m_rrs[ic] = cs * m3db;
263 }
264 process = false;
265 m_channels = 8;
266 break;
267 default:
268 break;
269 }
270 if (process)
271 {
272 ic += numFrames;
273 if (ic != bs)
274 {
275 // dont modify unless no processing is to be done
276 // for audiotime consistency
277 m_inCount = ic;
278 }
279 else
280 {
281 m_processed = process;
282 // process_block takes some time so dont update in and out count
283 // before its finished so that Audiotime is correctly calculated
285 m_inCount = 0;
286 m_outCount = bs;
287 m_processedSize = bs;
289 }
290 }
291 else
292 {
293 m_inCount = 0;
295 m_processed = false;
296 m_latencyFrames = 0;
297 }
298
299 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
300 QString("FreeSurround::putFrames %1 #ch %2 used %3 generated %4")
301 .arg(numFrames).arg(numChannels).arg(i).arg(m_outCount));
302
303 return i;
304}
305
306uint FreeSurround::receiveFrames(void *buffer, uint maxFrames)
307{
308 uint oc = m_outCount;
309 maxFrames = std::min(maxFrames, oc);
310 uint outindex = m_processedSize - oc;
311 auto *output = (float *)buffer;
312 if (m_channels == 8)
313 {
314 float *l = &m_bufs->m_l[outindex];
315 float *c = &m_bufs->m_c[outindex];
316 float *r = &m_bufs->m_r[outindex];
317 float *ls = &m_bufs->m_ls[outindex];
318 float *rs = &m_bufs->m_rs[outindex];
319 float *lfe = &m_bufs->m_lfe[outindex];
320 float *rls = &m_bufs->m_rls[outindex];
321 float *rrs = &m_bufs->m_rrs[outindex];
322 for (uint i = 0; i < maxFrames; i++)
323 {
324// printf("1:%f 2:%f 3:%f 4:%f 5:%f 6:%f 7:%f 8:%f\n",
325// *l, *r, *c, *lfe, *rls, *rrs, *ls, *rs);
326
327 // 3F4-LFE L R C LFE Rls Rrs LS RS
328 *output++ = *l++;
329 *output++ = *r++;
330 *output++ = *c++;
331 *output++ = *lfe++;
332 *output++ = *rls++;
333 *output++ = *rrs++;
334 *output++ = *ls++;
335 *output++ = *rs++;
336 }
337 oc -= maxFrames;
338 }
339 else // channels == 6
340 {
341 if (m_processed)
342 {
343 float** outputs = m_decoder->getOutputBuffers();
344 float *l = &outputs[0][outindex];
345 float *c = &outputs[1][outindex];
346 float *r = &outputs[2][outindex];
347 float *ls = &outputs[3][outindex];
348 float *rs = &outputs[4][outindex];
349 float *lfe = &outputs[5][outindex];
350 for (uint i = 0; i < maxFrames; i++)
351 {
352 *output++ = *l++;
353 *output++ = *r++;
354 *output++ = *c++;
355 *output++ = *lfe++;
356 *output++ = *ls++;
357 *output++ = *rs++;
358 }
359 oc -= maxFrames;
360 }
361 else
362 {
363 float *l = &m_bufs->m_l[outindex];
364 float *c = &m_bufs->m_c[outindex];
365 float *r = &m_bufs->m_r[outindex];
366 float *ls = &m_bufs->m_ls[outindex];
367 float *rs = &m_bufs->m_rs[outindex];
368 float *lfe = &m_bufs->m_lfe[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 }
381 m_outCount = oc;
382 LOG(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
383 QString("FreeSurround::receiveFrames %1").arg(maxFrames));
384 return maxFrames;
385}
386
388{
389 // process the data
390 try
391 {
392 if (m_decoder)
393 {
395 }
396 }
397 catch(const std::exception& ex)
398 {
399 LOG(VB_AUDIO, LOG_DEBUG,
400 QString("FreeSurround::process_block exception: %1").arg(ex.what()));
401 }
402 catch(...)
403 {
404 LOG(VB_AUDIO, LOG_DEBUG,
405 QString("FreeSurround::process_block exception: unknown"));
406 }
407}
408
410{
411 // returns in usec
412 if (m_latencyFrames == 0)
413 return 0;
414 if (m_decoder == nullptr)
415 return 0;
416 return ((m_latencyFrames + m_inCount) * 1000000LL) / (2LL * m_srate);
417}
418
420{
421 if (m_decoder)
422 m_decoder->flush();
423 m_bufs->clear();
424}
425
426// load the lib and initialize the interface
428{
429 if (!m_decoder)
430 {
432 m_decoder->flush();
433 if (m_bufs)
434 m_bufs->clear();
436 }
437 SetParams();
438}
439
441{
442 delete m_decoder;
443 m_decoder = nullptr;
444}
445
447{
448 return m_inCount;
449}
450
452{
453 return m_outCount;
454}
455
457{
458 if (m_processed)
459 return m_inCount + m_outCount + (block_size/2);
460 return m_inCount + m_outCount;
461}
462
464{
465 return block_size/2;
466}
467
int m_processedSize
Definition: freesurround.h:85
void process_block()
uint frameLatency() const
@ SurroundModeActiveSimple
Definition: freesurround.h:34
@ SurroundModeActiveLinear
Definition: freesurround.h:35
@ SurroundModePassiveHall
Definition: freesurround.h:36
int m_latencyFrames
Definition: freesurround.h:87
uint numFrames() const
static uint framesPerBlock()
SurroundMode m_surroundMode
Definition: freesurround.h:86
struct FreeSurround::fsurround_params m_params
uint receiveFrames(void *buffer, uint maxFrames)
long long getLatency()
struct buffers * m_bufs
Definition: freesurround.h:80
class fsurround_decoder * m_decoder
Definition: freesurround.h:81
FreeSurround(uint srate, bool moviemode, SurroundMode mode)
uint numUnprocessedFrames() const
bool m_processed
Definition: freesurround.h:84
uint putFrames(void *buffer, uint numFrames, uint numChannels)
void steering_mode(bool mode)
void decode(float center_width=1, float dimension=0, float adaption_rate=1)
void separation(float front, float rear)
void surround_coefficients(float a, float b)
void sample_rate(unsigned int samplerate)
void phase_mode(unsigned mode)
static const std::array< const uint64_t, 4 > samples
Definition: element.cpp:46
static const unsigned default_block_size
static const float m3db
unsigned int block_size
static const float m6db
unsigned int uint
Definition: freesurround.h:24
static constexpr uint16_t SURROUND_BUFSIZE
Definition: freesurround.h:26
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
std::vector< float > m_ls
std::vector< float > m_rcs
std::vector< float > m_cs
std::vector< float > m_lfe
std::vector< float > m_c
std::vector< float > m_r
std::vector< float > m_l
std::vector< float > m_rrs
std::vector< float > m_lcs
void clear()
std::vector< float > m_rs
void resize(unsigned int s)
std::vector< float > m_rls
buffers(unsigned int s)
#define output