Permalink
Browse files

Merge temp/newaudiosettings branch.

In short:
- Add new configuration screen, with testing screen
- No need to press Scan Audio Device anymore
- DTS-HD MA, E-AC3 and TrueHD passthrough
  • Loading branch information...
jyavenard committed Dec 14, 2010
2 parents 7504555 + aa7298c commit b2a86a2ad29cef7b7d8c19cc5929510be30c94fa
Showing with 2,148 additions and 1,265 deletions.
  1. +2 −2 mythtv/libs/libmyth/audio/audiooutput.cpp
  2. +4 −1 mythtv/libs/libmyth/audio/audiooutput.h
  3. +20 −25 mythtv/libs/libmyth/audio/audiooutputalsa.cpp
  4. +0 −2 mythtv/libs/libmyth/audio/audiooutputalsa.h
  5. +88 −22 mythtv/libs/libmyth/audio/audiooutputbase.cpp
  6. +4 −1 mythtv/libs/libmyth/audio/audiooutputbase.h
  7. +24 −269 mythtv/libs/libmyth/audio/audiooutputdigitalencoder.cpp
  8. +7 −3 mythtv/libs/libmyth/audio/audiooutputdigitalencoder.h
  9. +31 −10 mythtv/libs/libmyth/audio/audiooutputsettings.cpp
  10. +38 −1 mythtv/libs/libmyth/audio/audiooutputsettings.h
  11. +50 −2 mythtv/libs/libmyth/audio/audiooutpututil.cpp
  12. +5 −0 mythtv/libs/libmyth/audio/audiooutpututil.h
  13. +39 −13 mythtv/libs/libmyth/audio/audiosettings.cpp
  14. +30 −27 mythtv/libs/libmyth/audio/audiosettings.h
  15. +96 −0 mythtv/libs/libmyth/audio/pink.c
  16. +22 −0 mythtv/libs/libmyth/audio/pink.h
  17. +191 −0 mythtv/libs/libmyth/audio/spdifencoder.cpp
  18. +36 −0 mythtv/libs/libmyth/audio/spdifencoder.h
  19. +5 −4 mythtv/libs/libmyth/libmyth.pro
  20. +7 −0 mythtv/libs/libmyth/settings.cpp
  21. +3 −1 mythtv/libs/libmyth/settings.h
  22. +20 −4 mythtv/libs/libmythtv/audioplayer.cpp
  23. +2 −0 mythtv/libs/libmythtv/audioplayer.h
  24. +25 −223 mythtv/libs/libmythtv/avformatdecoder.cpp
  25. +4 −0 mythtv/libs/libmythtv/avformatdecoder.h
  26. +3 −3 mythtv/libs/libmythtv/playercontext.cpp
  27. +1,145 −0 mythtv/programs/mythfrontend/audiogeneralsettings.cpp
  28. +205 −0 mythtv/programs/mythfrontend/audiogeneralsettings.h
  29. +0 −584 mythtv/programs/mythfrontend/globalsettings.cpp
  30. +0 −65 mythtv/programs/mythfrontend/globalsettings.h
  31. +12 −0 mythtv/programs/mythfrontend/main.cpp
  32. +2 −2 mythtv/programs/mythfrontend/mythfrontend.pro
  33. +0 −1 mythtv/programs/mythtranscode/transcode.cpp
  34. +7 −0 mythtv/themes/DVR/main_settings.xml
  35. +7 −0 mythtv/themes/classic/main_settings.xml
  36. +7 −0 mythtv/themes/defaultmenu/main_settings.xml
  37. +7 −0 mythtv/themes/mediacentermenu/main_settings.xml
@@ -48,11 +48,11 @@ AudioOutput *AudioOutput::OpenAudio(
const QString &main_device, const QString &passthru_device,
AudioFormat format, int channels, int codec, int samplerate,
AudioOutputSource source, bool set_initial_vol, bool passthru,
- int upmixer_startup)
+ int upmixer_startup, AudioOutputSettings *custom)
{
AudioSettings settings(
main_device, passthru_device, format, channels, codec, samplerate,
- source, set_initial_vol, passthru, upmixer_startup);
+ source, set_initial_vol, passthru, upmixer_startup, custom);
return OpenAudio(settings);
}
@@ -41,7 +41,7 @@ class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
const QString &audiodevice, const QString &passthrudevice,
AudioFormat format, int channels, int codec, int samplerate,
AudioOutputSource source, bool set_initial_vol, bool passthru,
- int upmixer_startup = 0);
+ int upmixer_startup = 0, AudioOutputSettings *custom = NULL);
static AudioOutput *OpenAudio(AudioSettings &settings,
bool willsuspendpa = true);
static AudioOutput *OpenAudio(
@@ -60,6 +60,9 @@ class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
virtual void SetStretchFactor(float factor);
virtual float GetStretchFactor(void) const { return 1.0f; }
+ virtual int GetChannels(void) const { return 2; }
+ virtual AudioFormat GetFormat(void) const { return FORMAT_S16; };
+ virtual int GetBytesPerFrame(void) const { return 4; };
virtual AudioOutputSettings* GetOutputSettingsCleaned(void)
{ return new AudioOutputSettings; }
@@ -55,7 +55,7 @@ AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) :
if (args < 0)
{
/* no existing parameters: add it behind device name */
- passthru_device += ":AES0=6";
+ passthru_device += ":AES0=6,AES1=0x82,AES2=0x00,AES3=0x01";
}
else
{
@@ -66,12 +66,12 @@ AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) :
if (args == passthru_device.length())
{
/* ":" but no parameters */
- passthru_device += "AES0=6";
+ passthru_device += "AES0=6,AES1=0x82,AES2=0x00,AES3=0x01";
}
else if (passthru_device[args] != '{')
{
/* a simple list of parameters: add it at the end of the list */
- passthru_device += ",AES0=6";
+ passthru_device += ",AES0=6,AES1=0x82,AES2=0x00,AES3=0x01";
}
else
{
@@ -80,7 +80,8 @@ AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) :
--len;
while (len > 0 && passthru_device[len].isSpace());
if (passthru_device[len] == '}')
- passthru_device = passthru_device.insert(len, " AES0=6");
+ passthru_device = passthru_device.insert(
+ len, " AES0=6 AES1 0x82 AES2=0x00 AES3=0x01");
}
}
}
@@ -106,6 +107,7 @@ int AudioOutputALSA::TryOpenDevice(int open_mode, int try_ac3)
if (try_ac3)
{
dev_ba = passthru_device.toAscii();
+ VBAUDIO(QString("OpenDevice %1 for passthrough").arg(passthru_device));
err = snd_pcm_open(&pcm_handle, dev_ba.constData(),
SND_PCM_STREAM_PLAYBACK, open_mode);
m_lastdevice = passthru_device;
@@ -120,6 +122,7 @@ int AudioOutputALSA::TryOpenDevice(int open_mode, int try_ac3)
if (!try_ac3 || err < 0)
{
// passthru open failed, retry default device
+ VBAUDIO(QString("OpenDevice %1").arg(main_device));
dev_ba = main_device.toAscii();
err = snd_pcm_open(&pcm_handle, dev_ba.constData(),
SND_PCM_STREAM_PLAYBACK, open_mode);
@@ -243,7 +246,8 @@ bool AudioOutputALSA::IncPreallocBufferSize(int buffer_time)
(buffer_time / 1000) *
output_bytes_per_frame / 1024;
- VBAUDIO(QString("Prealloc buffer cur: %1 max: %3").arg(cur).arg(max));
+ VBAUDIO(QString("Prealloc buffer cur: %1 need: %2 max: %3")
+ .arg(cur).arg(size).arg(max));
if (size > max)
{
@@ -406,7 +410,7 @@ bool AudioOutputALSA::OpenDevice()
}
period_time = 50000; // aim for an interrupt every 50ms
- buffer_time = period_time << 2; // buffer 200ms worth of samples
+ buffer_time = period_time << 3; // buffer 400ms worth of samples
err = SetParameters(pcm_handle, format, channels, samplerate,
buffer_time, period_time);
@@ -488,7 +492,10 @@ void AudioOutputALSA::WriteAudio(uchar *aubuf, int size)
return;
}
- if ((!passthru && channels == 6) || channels == 8)
+ /* Audio received is using SMPTE channel ordering
+ * ALSA uses its own channel order.
+ * Do not re-order passthu audio */
+ if (!passthru && (channels == 6 || channels == 8))
ReorderSmpteToAlsa(aubuf, frames, output_format, channels - 6);
VERBOSE(VB_AUDIO+VB_TIMESTAMP,
@@ -497,7 +504,7 @@ void AudioOutputALSA::WriteAudio(uchar *aubuf, int size)
while (frames > 0)
{
- lw = pcm_write_func(pcm_handle, tmpbuf, frames);
+ lw = snd_pcm_writei(pcm_handle, tmpbuf, frames);
if (lw >= 0)
{
@@ -517,7 +524,7 @@ void AudioOutputALSA::WriteAudio(uchar *aubuf, int size)
case -EPIPE:
if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN)
{
- VBERROR("WriteAudio: buffer underrun");
+ VBAUDIO("WriteAudio: buffer underrun");
if ((err = snd_pcm_prepare(pcm_handle)) < 0)
{
AERROR("WriteAudio: unable to recover from xrun");
@@ -604,22 +611,10 @@ int AudioOutputALSA::SetParameters(snd_pcm_t *handle, snd_pcm_format_t format,
err = snd_pcm_hw_params_any(handle, params);
CHECKERR("No playback configurations available");
- /* set the interleaved read/write format, use mmap if available */
- pcm_write_func = &snd_pcm_mmap_writei;
- if ((err = snd_pcm_hw_params_set_access(handle, params,
- SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0)
- {
- Warn("mmap not available, attempting to fall back to slow writes");
- QString old_err = snd_strerror(err);
- pcm_write_func = &snd_pcm_writei;
- if ((err = snd_pcm_hw_params_set_access(handle, params,
- SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
- {
- Error("Interleaved sound types MMAP & RW are not available");
- AERROR(QString("MMAP Error: %1\n\t\t\tRW Error").arg(old_err));
- return err;
- }
- }
+ /* set the interleaved read/write format */
+ err = snd_pcm_hw_params_set_access(handle, params,
+ SND_PCM_ACCESS_RW_INTERLEAVED);
+ CHECKERR(QString("Interleaved RW audio not available"));
/* set the sample format */
err = snd_pcm_hw_params_set_format(handle, params, format);
@@ -46,8 +46,6 @@ class AudioOutputALSA : public AudioOutputBase
int pbufsize;
int m_card, m_device, m_subdevice;
QMutex killAudioLock;
- snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*,
- snd_pcm_uframes_t);
bool m_autopassthrough;
QString m_lastdevice;
@@ -73,7 +73,7 @@ AudioOutputBase::AudioOutputBase(const AudioSettings &settings) :
pSoundStretch(NULL),
encoder(NULL), upmixer(NULL),
source_channels(-1), source_samplerate(0),
- source_bytes_per_frame(0),
+ source_bytes_per_frame(0), upmix_default(false),
needs_upmix(false), needs_downmix(false),
surround_mode(QUALITY_LOW), old_stretchfactor(1.0f),
volume(80), volumeControl(QString()),
@@ -107,8 +107,7 @@ AudioOutputBase::AudioOutputBase(const AudioSettings &settings) :
src_quality = QUALITY_MEDIUM;
// Handle override of SRC quality settings
- if (gCoreContext->GetNumSetting("AdvancedAudioSettings", false) &&
- gCoreContext->GetNumSetting("SRCQualityOverride", false))
+ if (gCoreContext->GetNumSetting("SRCQualityOverride", false))
{
src_quality = gCoreContext->GetNumSetting("SRCQuality", QUALITY_MEDIUM);
// Extra test to keep backward compatibility with earlier SRC setting
@@ -145,6 +144,17 @@ AudioOutputBase::~AudioOutputBase()
void AudioOutputBase::InitSettings(const AudioSettings &settings)
{
+ if (settings.custom)
+ {
+ // got a custom audio report already, use it
+ // this was likely provided by the AudioTest utility
+ output_settings = new AudioOutputSettings;
+ *output_settings = *settings.custom;
+ max_channels = output_settings->BestSupportedChannels();
+ configured_channels = max_channels;
+ return;
+ }
+
// Ask the subclass what we can send to the device
output_settings = GetOutputSettingsUsers();
@@ -163,7 +173,7 @@ void AudioOutputBase::InitSettings(const AudioSettings &settings)
/**
* Returns capabilities supported by the audio device
* amended to take into account the digital audio
- * options (AC3 and DTS)
+ * options (AC3, DTS, E-AC3 and TrueHD)
*/
AudioOutputSettings* AudioOutputBase::GetOutputSettingsCleaned(void)
{
@@ -185,7 +195,7 @@ AudioOutputSettings* AudioOutputBase::GetOutputSettingsCleaned(void)
/**
* Returns capabilities supported by the audio device
* amended to take into account the digital audio
- * options (AC3 and DTS) as well as the user settings
+ * options (AC3, DTS, E-AC3 and TrueHD) as well as the user settings
*/
AudioOutputSettings* AudioOutputBase::GetOutputSettingsUsers(void)
{
@@ -211,10 +221,12 @@ bool AudioOutputBase::CanPassthrough(int samplerate, int channels) const
// Don't know any cards that support spdif clocked at < 44100
// Some US cable transmissions have 2ch 32k AC-3 streams
ret &= samplerate >= 44100;
- // Will downmix if we can't support the amount of channels
- ret &= channels <= max_channels;
- // Stereo content will always be decoded so it can later be upmixed
- ret &= channels != 2;
+ // Will passthrough if surround audio was defined. Amplifier will
+ // do the downmix if required
+ ret &= max_channels >= 6;
+ // Stereo content will always be decoded so it can later be upmixed
+ // unless audio is configured for stereoo
+ ret |= channels == 2 && max_channels == 2;
return ret;
}
@@ -419,7 +431,8 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
VBAUDIO(QString("Original codec was %1, %2, %3 kHz, %4 channels")
.arg(ff_codec_id_string((CodecID)codec))
.arg(output_settings->FormatToString(format))
- .arg(samplerate/1000).arg(source_channels));
+ .arg(samplerate/1000)
+ .arg(source_channels));
/* Encode to AC-3 if we're allowed to passthru but aren't currently
and we have more than 2 channels but multichannel PCM is not supported
@@ -429,22 +442,25 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
output_settings->canAC3() &&
((!output_settings->canLPCM() && configured_channels > 2) ||
!output_settings->IsSupportedChannels(channels)));
- VBAUDIO(QString("enc(%1), passthru(%2), canAC3(%3), canDTS(%4), canLPCM(%5)"
- ", configured_channels(%6), %7 channels supported(%8)")
+ VBAUDIO(QString("enc(%1), passthru(%2), canAC3(%3), canDTS(%4), canHD(%5), "
+ "canHDLL(%6), canLPCM(%7), "
+ "configured_channels(%8), %9 channels supported(%10)")
.arg(enc)
.arg(passthru)
.arg(output_settings->canAC3())
.arg(output_settings->canDTS())
+ .arg(output_settings->canHD())
+ .arg(output_settings->canHDLL())
.arg(output_settings->canLPCM())
.arg(configured_channels)
- .arg(channels).arg(output_settings->IsSupportedChannels(channels)));
+ .arg(channels)
+ .arg(output_settings->IsSupportedChannels(channels)));
int dest_rate = 0;
// Force resampling if we are encoding to AC3 and sr > 48k
// or if 48k override was checked in settings
if ((samplerate != 48000 &&
- gCoreContext->GetNumSetting("AdvancedAudioSettings", false) &&
gCoreContext->GetNumSetting("Audio48kOverride", false)) ||
(enc && (samplerate > 48000 || (need_resampler && dest_rate > 48000))))
{
@@ -511,8 +527,46 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
}
}
- source_bytes_per_frame = source_channels *
- output_settings->SampleSize(format);
+ if (passthru)
+ {
+ switch (settings.codec)
+ {
+ case CODEC_ID_EAC3:
+ samplerate *= 4;
+ case CODEC_ID_AC3:
+ case CODEC_ID_DTS:
+ channels = 2;
+ break;
+ case CODEC_ID_TRUEHD:
+ channels = 8;
+ switch(samplerate)
+ {
+ case 48000:
+ case 96000:
+ case 192000:
+ samplerate = 192000;
+ break;
+ case 44100:
+ case 88200:
+ case 176400:
+ samplerate = 176400;
+ break;
+ default:
+ VBAUDIO("TrueHD: Unsupported samplerate");
+ break;
+ }
+ break;
+ }
+ //AC3, DTS, DTS-HD MA and TrueHD use 16 bits samples
+ format = output_format = FORMAT_S16;
+ source_bytes_per_frame = channels *
+ output_settings->SampleSize(format);
+ }
+ else
+ {
+ source_bytes_per_frame = source_channels *
+ output_settings->SampleSize(format);
+ }
// Turn on float conversion?
if (need_resampler || needs_upmix || needs_downmix ||
@@ -525,12 +579,20 @@ void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings)
if (enc)
output_format = FORMAT_S16; // Output s16le for AC-3 encoder
else
- output_format = output_settings->BestSupportedFormat();
+ {
+ // re-encode audio using same format as input if upmixing
+ // to minimize the memory sound buffer usage. There should be
+ // no siginificant quality loss
+ if (needs_upmix &&
+ output_settings->IsSupportedFormat(format))
+ {
+ output_format = format;
+ }
+ else
+ output_format = output_settings->BestSupportedFormat();
+ }
}
- if (passthru)
- channels = 2; // IEC958 bitstream - 2 ch
-
bytes_per_frame = processing ? 4 : output_settings->SampleSize(format);
bytes_per_frame *= channels;
@@ -967,6 +1029,7 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
if (!needs_upmix)
{
int num = len;
+
if (bdiff <= num)
{
memcpy(WPOS, buffer, bdiff);
@@ -1045,7 +1108,8 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
int org_waud = waud, afree = audiofree();
int frames = in_frames;
void *buffer = in_buffer;
- int bpf = bytes_per_frame, len = frames * source_bytes_per_frame;
+ int bpf = bytes_per_frame;
+ int len = frames * source_bytes_per_frame;
int used = kAudioRingBufferSize - afree;
bool music = false;
int bdiff;
@@ -1110,7 +1174,8 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
int frames_remaining = in_frames;
int frames_final = 0;
- int maxframes = (kAudioSRCInputSize / source_channels) & ~0xf;
+ int maxframes = (kAudioSRCInputSize /
+ (passthru ? channels : source_channels)) & ~0xf;
int offset = 0;
while(frames_remaining > 0)
@@ -1131,6 +1196,7 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
// Convert to floats
len = AudioOutputUtil::toFloat(format, src_in, buffer, len);
}
+
frames_remaining -= frames;
// Perform downmix if necessary
Oops, something went wrong.

0 comments on commit b2a86a2

Please sign in to comment.