MythTV
master
libs
libmythfreesurround
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
31
#include "
compat.h
"
32
#include "
mythlogging.h
"
33
#include "
freesurround.h
"
34
#include "
el_processor.h
"
35
36
#include <QString>
37
#include <QDateTime>
38
39
// our default internal block size, in floats
40
static
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;
43
static
const
float
m3db
= 0.7071067811865476F;
// 3dB = SQRT(2)
44
static
const
float
m6db
= 0.5;
// 6dB = SQRT(4)
45
//static const float m7db = 0.44721359549996; // 7dB = SQRT(5)
46
47
unsigned
int
block_size
=
default_block_size
;
48
49
struct
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
71
int
channel_select = -1;
72
#endif
73
74
FreeSurround::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
{
84
m_params
.
phasemode
= 1;
85
m_params
.
center_width
= 25;
86
m_params
.
dimension
= 50;
87
}
88
else
89
{
90
m_params
.
center_width
= 65;
91
m_params
.
dimension
= 30;
92
}
93
switch
(
m_surroundMode
)
94
{
95
case
SurroundModeActiveSimple
:
96
m_params
.
steering
= 0;
97
break
;
98
case
SurroundModeActiveLinear
:
99
m_params
.
steering
= 1;
100
m_latencyFrames
=
block_size
/2;
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
119
void
FreeSurround::SetParams
()
120
{
121
if
(
m_decoder
)
122
{
123
m_decoder
->
steering_mode
(
m_params
.
steering
!= 0);
124
m_decoder
->
phase_mode
(
m_params
.
phasemode
);
125
m_decoder
->
surround_coefficients
(
m_params
.
coeff_a
,
m_params
.
coeff_b
);
126
m_decoder
->
separation
(
m_params
.
front_sep
/100.0,
m_params
.
rear_sep
/100.0);
127
}
128
}
129
130
FreeSurround::fsurround_params::fsurround_params
(int32_t center_width,
131
int32_t dimension) :
132
center_width(center_width),
133
dimension(dimension)
134
{
135
}
136
137
FreeSurround::~FreeSurround
()
138
{
139
LOG
(VB_AUDIO, LOG_DEBUG, QString(
"FreeSurround::~FreeSurround"
));
140
close
();
141
delete
m_bufs
;
142
m_bufs
=
nullptr
;
143
LOG
(VB_AUDIO, LOG_DEBUG, QString(
"FreeSurround::~FreeSurround done"
));
144
}
145
146
uint
FreeSurround::putFrames
(
void
* buffer,
uint
numFrames
,
uint
numChannels)
147
{
148
uint
i = 0;
149
uint
ic =
m_inCount
;
150
uint
bs =
block_size
/2;
151
bool
process =
true
;
152
auto
*
samples
= (
float
*)buffer;
153
// demultiplex
154
155
float
**inputs =
m_decoder
->
getInputBuffers
();
156
float
*lt = &inputs[0][ic];
157
float
*rt = &inputs[1][ic];
158
159
if
((
m_surroundMode
!=
SurroundModePassive
) && (ic+
numFrames
> bs))
160
{
161
numFrames
= bs - ic;
162
}
163
164
switch
(numChannels)
165
{
166
case
1:
167
switch
(
m_surroundMode
)
168
{
169
case
SurroundModePassive
:
170
case
SurroundModePassiveHall
:
171
for
(i = 0; i <
numFrames
&& ic < bs; i++,ic++)
172
{
173
// should be -7dB to keep power level the same
174
// but we bump the level a tad.
175
m_bufs
->
m_c
[ic] =
m_bufs
->
m_l
[ic] =
m_bufs
->
m_r
[ic] =
samples
[i] *
m6db
;
176
m_bufs
->
m_ls
[ic] =
m_bufs
->
m_rs
[ic] =
m_bufs
->
m_c
[ic];
177
}
178
process =
false
;
179
break
;
180
default
:
181
for
(i=0; i<
numFrames
; i++)
182
*lt++ = *rt++ = *
samples
++;
183
process =
true
;
184
break
;
185
}
186
m_channels
= 6;
187
break
;
188
189
case
2:
190
switch
(
m_surroundMode
)
191
{
192
case
SurroundModePassive
:
193
for
(i = 0; i <
numFrames
&& ic < bs; i++,ic++)
194
{
195
float
lt = *
samples
++;
196
float
rt = *
samples
++;
197
m_bufs
->
m_l
[ic] = lt;
198
m_bufs
->
m_lfe
[ic] =
m_bufs
->
m_c
[ic] = (lt+rt) *
m3db
;
199
m_bufs
->
m_r
[ic] = rt;
200
// surround channels receive out-of-phase
201
m_bufs
->
m_ls
[ic] = (rt-lt) * 0.5;
202
m_bufs
->
m_rs
[ic] = (lt-rt) * 0.5;
203
}
204
process =
false
;
205
break
;
206
case
SurroundModePassiveHall
:
207
for
(i = 0; i <
numFrames
&& ic < bs; i++,ic++)
208
{
209
float
lt = *
samples
++;
210
float
rt = *
samples
++;
211
m_bufs
->
m_l
[ic] = lt *
m3db
;
212
m_bufs
->
m_lfe
[ic] =
m_bufs
->
m_c
[ic] = (lt+rt) *
m3db
;
213
m_bufs
->
m_r
[ic] = rt *
m3db
;
214
m_bufs
->
m_ls
[ic] =
m_bufs
->
m_l
[ic];
215
m_bufs
->
m_rs
[ic] =
m_bufs
->
m_r
[ic];
216
}
217
process =
false
;
218
break
;
219
default
:
220
for
(i=0; i<
numFrames
; i++)
221
{
222
*lt++ = *
samples
++;
223
*rt++ = *
samples
++;
224
}
225
process =
true
;
226
break
;
227
}
228
m_channels
= 6;
229
break
;
230
231
case
5:
232
for
(i = 0; i <
numFrames
&& ic < bs; i++,ic++)
233
{
234
float
lt = *
samples
++;
235
float
rt = *
samples
++;
236
float
c = *
samples
++;
237
float
ls = *
samples
++;
238
float
rs = *
samples
++;
239
m_bufs
->
m_l
[ic] = lt;
240
m_bufs
->
m_lfe
[ic] = 0.0F;
241
m_bufs
->
m_c
[ic] = c;
242
m_bufs
->
m_r
[ic] = rt;
243
m_bufs
->
m_ls
[ic] = ls;
244
m_bufs
->
m_rs
[ic] = rs;
245
}
246
process =
false
;
247
m_channels
= 6;
248
break
;
249
250
case
7:
251
for
(i = 0; i <
numFrames
&& ic < bs; i++,ic++)
252
{
253
// 3F3R-LFE L R C LFE BC LS RS
254
float
lt = *
samples
++;
255
float
rt = *
samples
++;
256
float
c = *
samples
++;
257
float
lfe = *
samples
++;
258
float
cs = *
samples
++;
259
float
ls = *
samples
++;
260
float
rs = *
samples
++;
261
m_bufs
->
m_l
[ic] = lt;
262
m_bufs
->
m_lfe
[ic] = lfe;
263
m_bufs
->
m_c
[ic] = c;
264
m_bufs
->
m_r
[ic] = rt;
265
m_bufs
->
m_ls
[ic] = ls;
266
m_bufs
->
m_rs
[ic] = rs;
267
m_bufs
->
m_rls
[ic] =
m_bufs
->
m_rrs
[ic] = cs *
m3db
;
268
}
269
process =
false
;
270
m_channels
= 8;
271
break
;
272
default
:
273
break
;
274
}
275
if
(process)
276
{
277
ic +=
numFrames
;
278
if
(ic != bs)
279
{
280
// dont modify unless no processing is to be done
281
// for audiotime consistency
282
m_inCount
= ic;
283
}
284
else
285
{
286
m_processed
= process;
287
// process_block takes some time so dont update in and out count
288
// before its finished so that Audiotime is correctly calculated
289
process_block
();
290
m_inCount
= 0;
291
m_outCount
= bs;
292
m_processedSize
= bs;
293
m_latencyFrames
=
block_size
/2;
294
}
295
}
296
else
297
{
298
m_inCount
= 0;
299
m_outCount
=
m_processedSize
= ic;
300
m_processed
=
false
;
301
m_latencyFrames
= 0;
302
}
303
304
LOG
(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
305
QString(
"FreeSurround::putFrames %1 #ch %2 used %3 generated %4"
)
306
.
arg
(
numFrames
).
arg
(numChannels).
arg
(i).
arg
(
m_outCount
));
307
308
return
i;
309
}
310
311
uint
FreeSurround::receiveFrames
(
void
*buffer,
uint
maxFrames)
312
{
313
uint
oc =
m_outCount
;
314
if
(maxFrames > oc) maxFrames = oc;
315
uint
outindex =
m_processedSize
- oc;
316
auto
*
output
= (
float
*)buffer;
317
if
(
m_channels
== 8)
318
{
319
float
*l = &
m_bufs
->
m_l
[outindex];
320
float
*c = &
m_bufs
->
m_c
[outindex];
321
float
*r = &
m_bufs
->
m_r
[outindex];
322
float
*ls = &
m_bufs
->
m_ls
[outindex];
323
float
*rs = &
m_bufs
->
m_rs
[outindex];
324
float
*lfe = &
m_bufs
->
m_lfe
[outindex];
325
float
*rls = &
m_bufs
->
m_rls
[outindex];
326
float
*rrs = &
m_bufs
->
m_rrs
[outindex];
327
for
(
uint
i = 0; i < maxFrames; i++)
328
{
329
// printf("1:%f 2:%f 3:%f 4:%f 5:%f 6:%f 7:%f 8:%f\n",
330
// *l, *r, *c, *lfe, *rls, *rrs, *ls, *rs);
331
332
// 3F4-LFE L R C LFE Rls Rrs LS RS
333
*
output
++ = *l++;
334
*
output
++ = *r++;
335
*
output
++ = *c++;
336
*
output
++ = *lfe++;
337
*
output
++ = *rls++;
338
*
output
++ = *rrs++;
339
*
output
++ = *ls++;
340
*
output
++ = *rs++;
341
}
342
oc -= maxFrames;
343
}
344
else
// channels == 6
345
{
346
if
(
m_processed
)
347
{
348
float
** outputs =
m_decoder
->
getOutputBuffers
();
349
float
*l = &outputs[0][outindex];
350
float
*c = &outputs[1][outindex];
351
float
*r = &outputs[2][outindex];
352
float
*ls = &outputs[3][outindex];
353
float
*rs = &outputs[4][outindex];
354
float
*lfe = &outputs[5][outindex];
355
for
(
uint
i = 0; i < maxFrames; i++)
356
{
357
*
output
++ = *l++;
358
*
output
++ = *r++;
359
*
output
++ = *c++;
360
*
output
++ = *lfe++;
361
*
output
++ = *ls++;
362
*
output
++ = *rs++;
363
}
364
oc -= maxFrames;
365
}
366
else
367
{
368
float
*l = &
m_bufs
->
m_l
[outindex];
369
float
*c = &
m_bufs
->
m_c
[outindex];
370
float
*r = &
m_bufs
->
m_r
[outindex];
371
float
*ls = &
m_bufs
->
m_ls
[outindex];
372
float
*rs = &
m_bufs
->
m_rs
[outindex];
373
float
*lfe = &
m_bufs
->
m_lfe
[outindex];
374
for
(
uint
i = 0; i < maxFrames; i++)
375
{
376
*
output
++ = *l++;
377
*
output
++ = *r++;
378
*
output
++ = *c++;
379
*
output
++ = *lfe++;
380
*
output
++ = *ls++;
381
*
output
++ = *rs++;
382
}
383
oc -= maxFrames;
384
}
385
}
386
m_outCount
= oc;
387
LOG
(VB_AUDIO | VB_TIMESTAMP, LOG_DEBUG,
388
QString(
"FreeSurround::receiveFrames %1"
).
arg
(maxFrames));
389
return
maxFrames;
390
}
391
392
void
FreeSurround::process_block
()
393
{
394
// process the data
395
try
396
{
397
if
(
m_decoder
)
398
{
399
m_decoder
->
decode
(
m_params
.
center_width
/100.0,
m_params
.
dimension
/100.0);
400
}
401
}
402
catch
(...)
403
{
404
}
405
}
406
407
long
long
FreeSurround::getLatency
()
408
{
409
// returns in usec
410
if
(
m_latencyFrames
== 0)
411
return
0;
412
return
m_decoder
? ((
long
long
)(
m_latencyFrames
+
m_inCount
)*1000000)/(2*
m_srate
) : 0;
413
}
414
415
void
FreeSurround::flush
()
416
{
417
if
(
m_decoder
)
418
m_decoder
->
flush
();
419
m_bufs
->
clear
();
420
}
421
422
// load the lib and initialize the interface
423
void
FreeSurround::open
()
424
{
425
if
(!
m_decoder
)
426
{
427
m_decoder
=
new
fsurround_decoder
(
block_size
);
428
m_decoder
->
flush
();
429
if
(
m_bufs
)
430
m_bufs
->
clear
();
431
m_decoder
->
sample_rate
(
m_srate
);
432
}
433
SetParams
();
434
}
435
436
void
FreeSurround::close
()
437
{
438
delete
m_decoder
;
439
m_decoder
=
nullptr
;
440
}
441
442
uint
FreeSurround::numUnprocessedFrames
()
const
443
{
444
return
m_inCount
;
445
}
446
447
uint
FreeSurround::numFrames
()
const
448
{
449
return
m_outCount
;
450
}
451
452
uint
FreeSurround::frameLatency
()
const
453
{
454
if
(
m_processed
)
455
return
m_inCount
+
m_outCount
+ (
block_size
/2);
456
return
m_inCount
+
m_outCount
;
457
}
458
459
uint
FreeSurround::framesPerBlock
()
460
{
461
return
block_size
/2;
462
}
463
FreeSurround::SurroundModeActiveLinear
@ SurroundModeActiveLinear
Definition:
freesurround.h:33
fsurround_decoder::sample_rate
void sample_rate(unsigned int samplerate)
Definition:
el_processor.cpp:601
FreeSurround::fsurround_params::coeff_a
float coeff_a
Definition:
freesurround.h:66
FreeSurround::fsurround_params::dimension
int32_t dimension
Definition:
freesurround.h:65
FreeSurround::SetParams
void SetParams()
Definition:
freesurround.cpp:119
FreeSurround::SurroundMode
SurroundMode
Definition:
freesurround.h:29
buffers::m_l
std::vector< float > m_l
Definition:
freesurround.cpp:65
buffers::buffers
buffers(unsigned int s)
Definition:
freesurround.cpp:51
FreeSurround::fsurround_params::steering
int32_t steering
Definition:
freesurround.h:69
buffers::m_rcs
std::vector< float > m_rcs
Definition:
freesurround.cpp:65
buffers::m_rs
std::vector< float > m_rs
Definition:
freesurround.cpp:65
SURROUND_BUFSIZE
#define SURROUND_BUFSIZE
Definition:
freesurround.h:24
FreeSurround::m_decoder
class fsurround_decoder * m_decoder
Definition:
freesurround.h:81
FreeSurround::getLatency
long long getLatency()
Definition:
freesurround.cpp:407
FreeSurround::SurroundModeActiveSimple
@ SurroundModeActiveSimple
Definition:
freesurround.h:32
FreeSurround::fsurround_params::phasemode
int32_t phasemode
Definition:
freesurround.h:68
buffers::m_lfe
std::vector< float > m_lfe
Definition:
freesurround.cpp:65
FreeSurround::close
void close()
Definition:
freesurround.cpp:436
FreeSurround::numFrames
uint numFrames() const
Definition:
freesurround.cpp:447
FreeSurround::open
void open()
Definition:
freesurround.cpp:423
FreeSurround::SurroundModePassiveHall
@ SurroundModePassiveHall
Definition:
freesurround.h:34
el_processor.h
arg
arg(title).arg(filename).arg(doDelete))
fsurround_decoder::flush
void flush()
Definition:
el_processor.cpp:581
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition:
mythlogging.h:23
buffers::m_c
std::vector< float > m_c
Definition:
freesurround.cpp:65
fsurround_decoder::decode
void decode(float center_width=1, float dimension=0, float adaption_rate=1)
Definition:
el_processor.cpp:577
freesurround.h
FreeSurround::fsurround_params::front_sep
int32_t front_sep
Definition:
freesurround.h:70
FreeSurround::putFrames
uint putFrames(void *buffer, uint numFrames, uint numChannels)
Definition:
freesurround.cpp:146
FreeSurround::numUnprocessedFrames
uint numUnprocessedFrames() const
Definition:
freesurround.cpp:442
buffers::m_r
std::vector< float > m_r
Definition:
freesurround.cpp:65
fsurround_decoder::separation
void separation(float front, float rear)
Definition:
el_processor.cpp:589
FreeSurround::m_surroundMode
SurroundMode m_surroundMode
Definition:
freesurround.h:86
FreeSurround::process_block
void process_block()
Definition:
freesurround.cpp:392
fsurround_decoder::surround_coefficients
void surround_coefficients(float a, float b)
Definition:
el_processor.cpp:583
FreeSurround::fsurround_params::rear_sep
int32_t rear_sep
Definition:
freesurround.h:71
mythlogging.h
FreeSurround::SurroundModePassive
@ SurroundModePassive
Definition:
freesurround.h:31
buffers::m_rls
std::vector< float > m_rls
Definition:
freesurround.cpp:66
FreeSurround::fsurround_params::center_width
int32_t center_width
Definition:
freesurround.h:64
buffers::m_rrs
std::vector< float > m_rrs
Definition:
freesurround.cpp:66
compat.h
FreeSurround::fsurround_params::fsurround_params
fsurround_params(int32_t center_width=100, int32_t dimension=0)
Definition:
freesurround.cpp:130
FreeSurround::framesPerBlock
static uint framesPerBlock()
Definition:
freesurround.cpp:459
m6db
static const float m6db
Definition:
freesurround.cpp:44
FreeSurround::frameLatency
uint frameLatency() const
Definition:
freesurround.cpp:452
buffers::clear
void clear()
Definition:
freesurround.cpp:59
hardwareprofile.smolt.long
long
Definition:
smolt.py:76
buffers::m_lcs
std::vector< float > m_lcs
Definition:
freesurround.cpp:65
FreeSurround::m_outCount
int m_outCount
Definition:
freesurround.h:83
default_block_size
static const unsigned default_block_size
Definition:
freesurround.cpp:40
FreeSurround::flush
void flush()
Definition:
freesurround.cpp:415
uint
unsigned int uint
Definition:
compat.h:141
FreeSurround::m_processed
bool m_processed
Definition:
freesurround.h:84
FreeSurround::m_channels
int m_channels
Definition:
freesurround.h:88
fsurround_decoder
Definition:
el_processor.h:23
buffers
Definition:
freesurround.cpp:49
block_size
unsigned int block_size
Definition:
freesurround.cpp:47
fsurround_decoder::steering_mode
void steering_mode(bool mode)
Definition:
el_processor.cpp:587
buffers::resize
void resize(unsigned int s)
Definition:
freesurround.cpp:53
m3db
static const float m3db
Definition:
freesurround.cpp:43
fsurround_decoder::phase_mode
void phase_mode(unsigned mode)
Definition:
el_processor.cpp:585
FreeSurround::fsurround_params::coeff_b
float coeff_b
Definition:
freesurround.h:67
FreeSurround::m_srate
uint m_srate
Definition:
freesurround.h:77
FreeSurround::m_inCount
int m_inCount
Definition:
freesurround.h:82
fsurround_decoder::getOutputBuffers
float ** getOutputBuffers()
Definition:
el_processor.cpp:596
FreeSurround::m_processedSize
int m_processedSize
Definition:
freesurround.h:85
FreeSurround::FreeSurround
FreeSurround(uint srate, bool moviemode, SurroundMode mode)
Definition:
freesurround.cpp:74
FreeSurround::m_bufs
struct buffers * m_bufs
Definition:
freesurround.h:80
buffers::m_ls
std::vector< float > m_ls
Definition:
freesurround.cpp:65
FreeSurround::m_latencyFrames
int m_latencyFrames
Definition:
freesurround.h:87
output
#define output
Definition:
synaesthesia.cpp:220
FreeSurround::receiveFrames
uint receiveFrames(void *buffer, uint maxFrames)
Definition:
freesurround.cpp:311
samples
static const std::array< const uint64_t, 4 > samples
Definition:
element.cpp:46
fsurround_decoder::getInputBuffers
float ** getInputBuffers()
Definition:
el_processor.cpp:591
FreeSurround::~FreeSurround
~FreeSurround()
Definition:
freesurround.cpp:137
FreeSurround::m_params
struct FreeSurround::fsurround_params m_params
buffers::m_cs
std::vector< float > m_cs
Definition:
freesurround.cpp:65
Generated on Sun Jan 24 2021 03:17:04 for MythTV by
1.8.17