Skip to content

Commit d701cc0

Browse files
committed
Allow 5.0 audio playback on hardware not supporting it.
ALSA doesn't support 5.0 audio and myth could only upmix mono and stereo. Extend upmixer to work with 5.0 audio. Based on a patch by Mark Spieth Fixes #9989 Backport SHA1:909b444
1 parent c3d7f46 commit d701cc0

File tree

3 files changed

+85
-27
lines changed

3 files changed

+85
-27
lines changed

mythtv/libs/libmyth/audiooutputbase.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
#define QUALITY_MEDIUM 1
3434
#define QUALITY_HIGH 2
3535

36+
// 1,2 and 5 channels are currently valid for upmixing if required
37+
#define UPMIX_CHANNEL_MASK ((1<<1)|(1<<2)|(1<<5))
38+
#define IS_VALID_UPMIX_CHANNEL(ch) ((1 << (ch)) & UPMIX_CHANNEL_MASK)
39+
3640
static const char *quality_string(int q)
3741
{
3842
switch(q) {
@@ -459,13 +463,15 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
459463
}
460464
else
461465
{
462-
// if source was mono, and hardware doesn't support it
463-
// we will upmix it to stereo (can safely assume hardware supports
464-
// stereo)
465-
if (lsource_channels == 1 &&
466-
!output_settings->IsSupportedChannels(1))
466+
// if source was mono or 5.0, and hardware doesn't support it
467+
// we will upmix it respectively to stereo or 5.1
468+
// (can safely assume hardware supports stereo)
469+
// Ideally we should be able to upmix any channels configuration
470+
if ((lsource_channels == 1 || lsource_channels == 5) &&
471+
!output_settings->IsSupportedChannels(lsource_channels))
467472
{
468-
configured_channels = 2;
473+
// 1 => 2, 5 => 6
474+
configured_channels = lsource_channels + 1;
469475
}
470476
else
471477
configured_channels = (upmix_default && lsource_channels == 2) ?
@@ -480,8 +486,8 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
480486
lreenc = true;
481487
}
482488

483-
// Enough channels? Upmix if not, but only from mono/stereo to 5.1
484-
if (settings.channels <= 2 && settings.channels < configured_channels)
489+
// Enough channels? Upmix if not, but only from mono/stereo/5.0 to 5.1
490+
if (IS_VALID_UPMIX_CHANNEL(settings.channels) && settings.channels < configured_channels)
485491
{
486492
int conf_channels = (configured_channels > 6) ?
487493
6 : configured_channels;
@@ -736,8 +742,10 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
736742
VolumeBase::SyncVolume();
737743
VolumeBase::UpdateVolume();
738744

739-
// Upmix Stereo to 5.1
740-
if (needs_upmix && source_channels == 2 && configured_channels > 2)
745+
// Upmix Stereo or 5.0 to 5.1
746+
if (needs_upmix &&
747+
(source_channels == 2 || source_channels == 5) &&
748+
configured_channels > 2)
741749
{
742750
surround_mode = gCoreContext->GetNumSetting("AudioUpmixType", QUALITY_HIGH);
743751
if ((upmixer = new FreeSurround(samplerate, source == AUDIOOUTPUT_VIDEO,

mythtv/libs/libmythfreesurround/freesurround.cpp

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ FreeSurround::FreeSurround(uint srate, bool moviemode, SurroundMode smode) :
137137
out_count(0),
138138
processed(true),
139139
processed_size(0),
140-
surround_mode(smode)
140+
surround_mode(smode),
141+
latency_frames(0)
141142
{
142143
VERBOSE(VB_AUDIO+VB_EXTRA,
143144
QString("FreeSurround::FreeSurround rate %1 moviemode %2")
@@ -161,6 +162,7 @@ FreeSurround::FreeSurround(uint srate, bool moviemode, SurroundMode smode) :
161162
break;
162163
case SurroundModeActiveLinear:
163164
params.steering = 1;
165+
latency_frames = block_size/2;
164166
break;
165167
default:
166168
break;
@@ -243,10 +245,28 @@ uint FreeSurround::putFrames(void* buffer, uint numFrames, uint numChannels)
243245
bufs->ls[ic] = bufs->rs[ic] = (lt-rt) * center_level;
244246
}
245247
break;
248+
case 5:
249+
for (i = 0; i < numFrames && ic < bs; i++,ic++)
250+
{
251+
float lt = *samples++;
252+
float rt = *samples++;
253+
float c = *samples++;
254+
float lfe = (lt+rt) * center_level;
255+
float ls = *samples++;
256+
float rs = *samples++;
257+
bufs->l[ic] = lt;
258+
bufs->lfe[ic] = lfe;
259+
bufs->c[ic] = c;
260+
bufs->r[ic] = rt;
261+
bufs->ls[ic] = ls;
262+
bufs->rs[ic] = rs;
263+
}
264+
break;
246265
}
247266
in_count = 0;
248267
out_count = processed_size = ic;
249268
processed = false;
269+
latency_frames = 0;
250270
break;
251271

252272
default:
@@ -268,23 +288,52 @@ uint FreeSurround::putFrames(void* buffer, uint numFrames, uint numChannels)
268288
*rt++ = *samples++;
269289
}
270290
break;
291+
case 5:
292+
// 5 ch is always passive mode,
293+
for (i = 0; i < numFrames && ic < bs; i++,ic++)
294+
{
295+
float l = *samples++;
296+
float r = *samples++;
297+
float c = *samples++;
298+
float lfe = (l+r) * center_level;
299+
float ls = *samples++;
300+
float rs = *samples++;
301+
bufs->l[ic] = l;
302+
bufs->lfe[ic] = lfe;
303+
bufs->c[ic] = c;
304+
bufs->r[ic] = r;
305+
bufs->ls[ic] = ls;
306+
bufs->rs[ic] = rs;
307+
}
308+
process = false;
309+
break;
271310
}
272-
ic += numFrames;
273-
processed = process;
274-
if (ic != bs)
275-
{
276-
// dont modify unless no processing is to be done
277-
// for audiotime consistency
278-
in_count = ic;
279-
break;
280-
}
281-
// process_block takes some time so dont update in and out count
282-
// before its finished so that Audiotime is correctly calculated
283311
if (process)
312+
{
313+
ic += numFrames;
314+
if (ic != bs)
315+
{
316+
// dont modify unless no processing is to be done
317+
// for audiotime consistency
318+
in_count = ic;
319+
break;
320+
}
321+
processed = process;
322+
// process_block takes some time so dont update in and out count
323+
// before its finished so that Audiotime is correctly calculated
284324
process_block();
285-
in_count = 0;
286-
out_count = bs;
287-
processed_size = bs;
325+
in_count = 0;
326+
out_count = bs;
327+
processed_size = bs;
328+
latency_frames = block_size/2;
329+
}
330+
else
331+
{
332+
in_count = 0;
333+
out_count = processed_size = ic;
334+
processed = false;
335+
latency_frames = 0;
336+
}
288337
break;
289338
}
290339

@@ -386,9 +435,9 @@ void FreeSurround::process_block()
386435
long long FreeSurround::getLatency()
387436
{
388437
// returns in usec
389-
if (surround_mode == SurroundModePassive)
438+
if (latency_frames = 0)
390439
return 0;
391-
return decoder ? ((block_size/2 + in_count)*1000000)/(2*srate) : 0;
440+
return decoder ? ((latency_frames + in_count)*1000000)/(2*srate) : 0;
392441
}
393442

394443
void FreeSurround::flush()

mythtv/libs/libmythfreesurround/freesurround.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class FreeSurround
8585
bool processed; // whether processing is enabled for latency calc
8686
int processed_size; // amount processed
8787
SurroundMode surround_mode; // 1 of 3 surround modes supported
88+
int latency_frames; // number of frames of incurred latency
8889
};
8990

9091
#endif

0 commit comments

Comments
 (0)