diff --git a/app/audio/audiomanager.cpp b/app/audio/audiomanager.cpp index 9c7d6417e..18895f4f0 100644 --- a/app/audio/audiomanager.cpp +++ b/app/audio/audiomanager.cpp @@ -90,22 +90,63 @@ void AudioManager::SetOutputDevice(const QAudioDeviceInfo &info) StopOutput(); - QAudioFormat format; - format.setSampleRate(48000); - format.setChannelCount(2); - format.setSampleSize(32); - format.setCodec("audio/pcm"); - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::Float); - - output_ = std::unique_ptr(new QAudioOutput(info, format, this)); - connect(output_.get(), SIGNAL(notify()), this, SLOT(OutputNotified())); output_device_info_ = info; + if (output_params_.is_valid()) { + QAudioFormat format; + format.setSampleRate(output_params_.sample_rate()); + format.setChannelCount(output_params_.channel_count()); + format.setCodec("audio/pcm"); + format.setByteOrder(QAudioFormat::LittleEndian); + + switch (output_params_.format()) { + case SAMPLE_FMT_U8: + format.setSampleSize(8); + format.setSampleType(QAudioFormat::UnSignedInt); + break; + case SAMPLE_FMT_S16: + format.setSampleSize(16); + format.setSampleType(QAudioFormat::SignedInt); + break; + case SAMPLE_FMT_S32: + format.setSampleSize(32); + format.setSampleType(QAudioFormat::SignedInt); + break; + case SAMPLE_FMT_S64: + format.setSampleSize(64); + format.setSampleType(QAudioFormat::SignedInt); + break; + case SAMPLE_FMT_FLT: + format.setSampleSize(32); + format.setSampleType(QAudioFormat::Float); + break; + case SAMPLE_FMT_DBL: + format.setSampleSize(64); + format.setSampleType(QAudioFormat::Float); + break; + case SAMPLE_FMT_COUNT: + case SAMPLE_FMT_INVALID: + Q_ASSERT(false); + } + + output_ = std::unique_ptr(new QAudioOutput(info, format, this)); + connect(output_.get(), SIGNAL(notify()), this, SLOT(OutputNotified())); + } + // Un-comment this to get debug information about what the audio output is doing //connect(output_.get(), SIGNAL(stateChanged(QAudio::State)), this, SLOT(OutputStateChanged(QAudio::State))); } +void AudioManager::SetOutputParams(const AudioRenderingParams ¶ms) +{ + if (output_params_ != params) { + output_params_ = params; + + // Refresh output device + SetOutputDevice(output_device_info_); + } +} + void AudioManager::SetInputDevice(const QAudioDeviceInfo &info) { input_ = std::unique_ptr(new QAudioInput(info, QAudioFormat(), this)); diff --git a/app/audio/audiomanager.h b/app/audio/audiomanager.h index ec4b48f3d..9a6c2f765 100644 --- a/app/audio/audiomanager.h +++ b/app/audio/audiomanager.h @@ -27,6 +27,7 @@ #include #include "audiohybriddevice.h" +#include "render/audioparams.h" /** * @brief A thread for refreshing the total list of devices on the system @@ -86,6 +87,8 @@ public: void SetOutputDevice(const QAudioDeviceInfo& info); + void SetOutputParams(const AudioRenderingParams& params); + void SetInputDevice(const QAudioDeviceInfo& info); const QList& ListInputDevices(); @@ -109,6 +112,7 @@ private: std::unique_ptr output_; QAudioDeviceInfo output_device_info_; + AudioRenderingParams output_params_; std::unique_ptr input_; QAudioDeviceInfo input_device_info_; diff --git a/app/render/audioparams.cpp b/app/render/audioparams.cpp index ea04d90e3..d8d10103c 100644 --- a/app/render/audioparams.cpp +++ b/app/render/audioparams.cpp @@ -48,6 +48,20 @@ const SampleFormat &AudioRenderingParams::format() const return format_; } +bool AudioRenderingParams::operator==(const AudioRenderingParams &other) +{ + return (format() == other.format() + && sample_rate() == other.sample_rate() + && channel_layout() == other.channel_layout()); +} + +bool AudioRenderingParams::operator!=(const AudioRenderingParams &other) +{ + return (format() != other.format() + || sample_rate() != other.sample_rate() + || channel_layout() != other.channel_layout()); +} + int AudioRenderingParams::time_to_bytes(const rational &time) const { Q_ASSERT(is_valid()); diff --git a/app/render/audioparams.h b/app/render/audioparams.h index 043f1b5ca..7c6a3c5ee 100644 --- a/app/render/audioparams.h +++ b/app/render/audioparams.h @@ -38,6 +38,9 @@ public: const SampleFormat& format() const; + bool operator==(const AudioRenderingParams& other); + bool operator!=(const AudioRenderingParams& other); + private: SampleFormat format_; }; diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index bcde6be8f..66a8deb1f 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -210,6 +210,7 @@ void ViewerWidget::PlayInternal(int speed) QIODevice* audio_src = audio_renderer_->GetAudioPullDevice(); if (audio_src != nullptr && audio_src->open(QIODevice::ReadOnly)) { audio_src->seek(audio_renderer_->params().time_to_bytes(GetTime())); + AudioManager::instance()->SetOutputParams(audio_renderer_->params()); AudioManager::instance()->StartOutput(audio_src); } @@ -235,6 +236,7 @@ void ViewerWidget::PushScrubbedAudio() // Push audio audio_src->seek(audio_renderer_->params().time_to_bytes(GetTime())); QByteArray frame_audio = audio_src->read(size_of_sample); + AudioManager::instance()->SetOutputParams(audio_renderer_->params()); AudioManager::instance()->PushToOutput(frame_audio); audio_src->close();