Skip to content

Commit

Permalink
New Audio Setup and additional audio capabilities
Browse files Browse the repository at this point in the history
* Provide upmixing capabilities and 5.1 AC3 re-encoding
* Internal volume control to work even when audio is output via a digital devide (including 'passthru' and upmixed AC-3). When setting the mixer to "software", gives mythtv the capability to control the volume of all content (including AC3 and DTS)
* Simplification of the Setup/General/Audio screen, only presenting the options when they are relevant to the selected speaker configuration.
* Remove settings that aren't relevant anymore or that only created problem (like aggressive soundcard buffer)
* Simplify the stereo/surround configuration. Previously you had to set the number of speakers to stereo in order to get digital multi-channels.
* Various fixes across the board (like timestretch with digital sound)

User of digital audio will have to edit the audio configuration settings, and change "Stereo" to "5.1" for the "Speaker configuration" settings.
Ctrl-U will toggle the upmixer during playback or in MythMusic. Default upmixer behaviour for video playback and music can be changed in their respective configuration screen.

Close #6975

Note that AAC multi-channel ordering is still wrong unless you are using libfaad, this will be fixed with the next ffmpeg resync.

Original patch from "foobum". Thank you for your great work.


git-svn-id: http://svn.mythtv.org/svn/trunk@22432 7dbf422c-18fa-0310-86e9-fd20926502f2
  • Loading branch information
jyavenard committed Oct 14, 2009
1 parent 603d45c commit 3d1e2e5
Show file tree
Hide file tree
Showing 36 changed files with 877 additions and 609 deletions.
4 changes: 2 additions & 2 deletions mythplugins/mythmusic/mythmusic/avfdecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ bool avfDecoder::initialize()
if (output())
{
const AudioSettings settings(
16 /*bits*/, m_audioDec->channels, m_audioDec->sample_rate,
false /* AC3/DTS pass through */);
16 /*bits*/, m_audioDec->channels, m_audioDec->codec_id,
m_audioDec->sample_rate, false /* AC3/DTS pass through */);
output()->Reconfigure(settings);
output()->SetSourceBitrate(m_audioDec->bit_rate);
}
Expand Down
4 changes: 3 additions & 1 deletion mythplugins/mythmusic/mythmusic/cddecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ using namespace std;

#include <mythtv/mythcontext.h>
#include <mythtv/mythmediamonitor.h>
#include <mythtv/libavcodec/avcodec.h>

CdDecoder::CdDecoder(const QString &file, DecoderFactory *d, QIODevice *i,
AudioOutput *o) :
Expand Down Expand Up @@ -149,7 +150,8 @@ bool CdDecoder::initialize()
if (output())
{
const AudioSettings settings(
16 /*bits*/, chan, freq, false /* AC3/DTS passthru */);
16 /*bits*/, chan, CODEC_ID_PCM_S16LE, freq,
false /* AC3/DTS passthru */);
output()->Reconfigure(settings);
output()->SetSourceBitrate(44100 * 2 * 16);
}
Expand Down
12 changes: 12 additions & 0 deletions mythplugins/mythmusic/mythmusic/globalsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@ static HostComboBox *MusicAudioDevice()
return gc;
};

static HostCheckBox *MusicUpmixer()
{
HostCheckBox *gc = new HostCheckBox("MusicDefaultUpmix");
gc->setLabel(QObject::tr("Upconvert stereo to 5.1 surround"));
gc->setValue(false);
gc->setHelpText(QObject::tr("MythTV can upconvert stereo tracks to 5.1 audio. "
"Set this option to enable it by default. "
"You can enable or disable the upconversion during playback at anytime."));
return gc;
};

static HostLineEdit *CDDevice()
{
HostLineEdit *gc = new HostLineEdit("CDDevice");
Expand Down Expand Up @@ -545,6 +556,7 @@ MusicGeneralSettings::MusicGeneralSettings(void)
general->setLabel(QObject::tr("General Settings (1)"));
general->addChild(SetMusicDirectory());
general->addChild(MusicAudioDevice());
general->addChild(MusicUpmixer());
general->addChild(CDDevice());
general->addChild(AutoLookupCD());
general->addChild(AutoPlayCD());
Expand Down
2 changes: 2 additions & 0 deletions mythplugins/mythmusic/mythmusic/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ void setupKeys(void)
"Volume up"), "],},F11,Volume Up");
REG_KEY("Music", "MUTE", QT_TRANSLATE_NOOP("MythControls",
"Mute"), "|,\\,F9,Volume Mute");
REG_KEY("Music", "TOGGLEUPMIX",QT_TRANSLATE_NOOP("MythControls",
"Toggle audio upmixer"), "Ctrl+U");
REG_KEY("Music", "CYCLEVIS", QT_TRANSLATE_NOOP("MythControls",
"Cycle visualizer mode"), "6");
REG_KEY("Music", "BLANKSCR", QT_TRANSLATE_NOOP("MythControls",
Expand Down
9 changes: 6 additions & 3 deletions mythplugins/mythmusic/mythmusic/musicplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,16 +348,19 @@ void MusicPlayer::stopDecoder(void)

void MusicPlayer::openOutputDevice(void)
{
QString adevice;
QString adevice, pdevice;

if (gContext->GetSetting("MusicAudioDevice") == "default")
adevice = gContext->GetSetting("AudioOutputDevice");
else
adevice = gContext->GetSetting("MusicAudioDevice");

pdevice = gContext->GetSetting("PassThruOutputDevice");

// TODO: Error checking that device is opened correctly!
m_output = AudioOutput::OpenAudio(adevice, "default", 16, 2, 44100,
AUDIOOUTPUT_MUSIC, true, false);
m_output = AudioOutput::OpenAudio(adevice, pdevice, 16, 2, 0, 44100,
AUDIOOUTPUT_MUSIC, true, false,
gContext->GetNumSetting("MusicDefaultUpmix", 0) + 1);
m_output->setBufferSize(256 * 1024);
m_output->SetBlocking(false);

Expand Down
9 changes: 9 additions & 0 deletions mythplugins/mythmusic/mythmusic/playbackbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@ void PlaybackBoxMusic::keyPressEvent(QKeyEvent *e)
changeSpeed(true);
else if (action == "MUTE")
toggleMute();
else if (action == "TOGGLEUPMIX")
toggleUpmix();
else if (action == "MENU" && visualizer_status != 2)
{
menufilters = false;
Expand Down Expand Up @@ -1202,6 +1204,13 @@ void PlaybackBoxMusic::toggleMute()
}
}

void PlaybackBoxMusic::toggleUpmix()
{
if (gPlayer->getOutput())
gPlayer->getOutput()->ToggleUpmix();
}


void PlaybackBoxMusic::showProgressBar()
{
if (progress_bar && visualizer_status != 2)
Expand Down
1 change: 1 addition & 0 deletions mythplugins/mythmusic/mythmusic/playbackbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class PlaybackBoxMusic : public MythThemedDialog
void changeVolume(bool up_or_down);
void changeSpeed(bool up_or_down);
void toggleMute();
void toggleUpmix();
void resetTimer();
void hideVolume(){showVolume(false);}
void showVolume(bool on_or_off);
Expand Down
10 changes: 6 additions & 4 deletions mythtv/libs/libmyth/audiooutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@ using namespace std;
AudioOutput *AudioOutput::OpenAudio(
const QString &main_device,
const QString &passthru_device,
int audio_bits, int audio_channels, int audio_samplerate,
int audio_bits, int audio_channels,
int audio_codec, int audio_samplerate,
AudioOutputSource source,
bool set_initial_vol, bool audio_passthru)
bool set_initial_vol, bool audio_passthru,
int upmixer_startup)
{
AudioSettings settings(
main_device, passthru_device, audio_bits,
audio_channels, audio_samplerate, source,
set_initial_vol, audio_passthru);
audio_channels, audio_codec, audio_samplerate, source,
set_initial_vol, audio_passthru, upmixer_startup);

settings.FixPassThrough();

Expand Down
7 changes: 5 additions & 2 deletions mythtv/libs/libmyth/audiooutput.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
static AudioOutput *OpenAudio(
const QString &audiodevice,
const QString &passthrudevice,
int audio_bits, int audio_channels, int audio_samplerate,
int audio_bits, int audio_channels,
int audio_codec, int audio_samplerate,
AudioOutputSource source,
bool set_initial_vol, bool audio_passthru);
bool set_initial_vol, bool audio_passthru,
int upmixer_startup = 0);

AudioOutput() :
VolumeBase(), OutputListeners(),
Expand Down Expand Up @@ -68,6 +70,7 @@ class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners

virtual void bufferOutputData(bool y) = 0;
virtual int readOutputData(unsigned char *read_buffer, int max_length) = 0;
virtual bool ToggleUpmix(void) = 0;

protected:
void Error(const QString &msg);
Expand Down
127 changes: 125 additions & 2 deletions mythtv/libs/libmyth/audiooutputalsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,142 @@ AudioOutputALSA::AudioOutputALSA(const AudioSettings &settings) :
AudioOutputALSA::~AudioOutputALSA()
{
KillAudio();
SetIECStatus(true);
}

void AudioOutputALSA::SetIECStatus(bool audio)
{
snd_ctl_t *ctl;
const char *spdif_str = SND_CTL_NAME_IEC958("", PLAYBACK, DEFAULT);
int spdif_index = -1;
snd_ctl_elem_list_t *clist;
snd_ctl_elem_id_t *cid;
snd_ctl_elem_value_t *cval;
snd_aes_iec958_t iec958;
int cidx, controls;

VERBOSE(VB_AUDIO, QString("Setting IEC958 status: %1")
.arg(audio ? "audio" : "non-audio"));

int err;
if ((err = snd_ctl_open(&ctl, "default", 0)) < 0)
{
Error(QString("AudioOutputALSA::SetIECStatus: snd_ctl_open(default): %1")
.arg(snd_strerror(err)));
return;
}
snd_ctl_elem_list_alloca(&clist);
snd_ctl_elem_list(ctl, clist);
snd_ctl_elem_list_alloc_space(clist, snd_ctl_elem_list_get_count(clist));
snd_ctl_elem_list(ctl, clist);
controls = snd_ctl_elem_list_get_used(clist);
for (cidx = 0; cidx < controls; cidx++)
{
if (!strcmp(snd_ctl_elem_list_get_name(clist, cidx), spdif_str))
if (spdif_index < 0 ||
snd_ctl_elem_list_get_index(clist, cidx) == (uint)spdif_index)
break;
}

if (cidx >= controls)
return;

snd_ctl_elem_id_alloca(&cid);
snd_ctl_elem_list_get_id(clist, cidx, cid);
snd_ctl_elem_value_alloca(&cval);
snd_ctl_elem_value_set_id(cval, cid);
snd_ctl_elem_read(ctl,cval);
snd_ctl_elem_value_get_iec958(cval, &iec958);

if (!audio)
iec958.status[0] |= IEC958_AES0_NONAUDIO;
else
iec958.status[0] &= ~IEC958_AES0_NONAUDIO;

snd_ctl_elem_value_set_iec958(cval, &iec958);
snd_ctl_elem_write(ctl, cval);
}

vector<int> AudioOutputALSA::GetSupportedRates()
{
snd_pcm_hw_params_t *params;
int err;
const int srates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000 };
vector<int> rates(srates, srates + sizeof(srates) / sizeof(int) );
QString real_device;

if (audio_passthru || audio_enc)
real_device = audio_passthru_device;
else
real_device = audio_main_device;

if((err = snd_pcm_open(&pcm_handle, real_device.toAscii(),
SND_PCM_STREAM_PLAYBACK,
SND_PCM_NONBLOCK|SND_PCM_NO_AUTO_RESAMPLE)) < 0)
{
Error(QString("snd_pcm_open(%1): %2")
.arg(real_device).arg(snd_strerror(err)));

if (pcm_handle)
{
snd_pcm_close(pcm_handle);
pcm_handle = NULL;
}
rates.clear();
return rates;
}

snd_pcm_hw_params_alloca(&params);

if ((err = snd_pcm_hw_params_any(pcm_handle, params)) < 0)
{
Error(QString("Broken configuration for playback; no configurations"
" available: %1").arg(snd_strerror(err)));
snd_pcm_close(pcm_handle);
pcm_handle = NULL;
rates.clear();
return rates;
}

vector<int>::iterator it = rates.begin();

while (it != rates.end())
{
if(snd_pcm_hw_params_test_rate(pcm_handle, params, *it, 0) < 0)
it = rates.erase(it);
else
it++;
}

snd_pcm_close(pcm_handle);
pcm_handle = NULL;

return rates;
}

bool AudioOutputALSA::OpenDevice()
{
snd_pcm_format_t format;
unsigned int buffer_time, period_time;
int err;
QString real_device;

if (pcm_handle != NULL)
CloseDevice();

pcm_handle = NULL;
numbadioctls = 0;

QString real_device = (audio_passthru) ?
audio_passthru_device : audio_main_device;
if (audio_passthru || audio_enc)
{
real_device = audio_passthru_device;
SetIECStatus(false);
}
else
{
real_device = audio_main_device;
SetIECStatus(true);
}

VERBOSE(VB_GENERAL, QString("Opening ALSA audio device '%1'.")
.arg(real_device));
Expand Down Expand Up @@ -662,6 +782,9 @@ void AudioOutputALSA::SetupMixer(void)
if (mixer_handle != NULL)
CloseMixer();

if (alsadevice.toLower() == "software")
return;

VERBOSE(VB_AUDIO, QString("Opening mixer %1").arg(device));

// TODO: This is opening card 0. Fix for case of multiple soundcards
Expand Down
2 changes: 2 additions & 0 deletions mythtv/libs/libmyth/audiooutputalsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ class AudioOutputALSA : public AudioOutputBase
virtual void WriteAudio(unsigned char *aubuf, int size);
virtual int GetSpaceOnSoundcard(void) const;
virtual int GetBufferedOnSoundcard(void) const;
vector<int> GetSupportedRates(void);

private:
void SetIECStatus(bool audio);
inline int SetParameters(snd_pcm_t *handle,
snd_pcm_format_t format, unsigned int channels,
unsigned int rate, unsigned int buffer_time,
Expand Down

0 comments on commit 3d1e2e5

Please sign in to comment.