diff --git a/app/audio/audiomanager.cpp b/app/audio/audiomanager.cpp index e14a9d3ad..12c314c63 100644 --- a/app/audio/audiomanager.cpp +++ b/app/audio/audiomanager.cpp @@ -80,9 +80,9 @@ void AudioManager::PushToOutput(const QByteArray &samples) output_manager_.Push(samples); } -void AudioManager::StartOutput(QIODevice *device, int playback_speed) +void AudioManager::StartOutput(const QString &filename, qint64 offset, int playback_speed) { - output_manager_.PullFromDevice(device, playback_speed); + output_manager_.PullFromDevice(filename, offset, playback_speed); } void AudioManager::StopOutput() diff --git a/app/audio/audiomanager.h b/app/audio/audiomanager.h index 116b62c2f..a90c3ecf6 100644 --- a/app/audio/audiomanager.h +++ b/app/audio/audiomanager.h @@ -82,7 +82,7 @@ public: * * This takes ownership of the QIODevice and will delete it when StopOutput() is called */ - void StartOutput(QIODevice* device, int playback_speed); + void StartOutput(const QString& filename, qint64 offset, int playback_speed); /** * @brief Stop audio output immediately diff --git a/app/audio/outputdeviceproxy.cpp b/app/audio/outputdeviceproxy.cpp index 713888b05..633e7e065 100644 --- a/app/audio/outputdeviceproxy.cpp +++ b/app/audio/outputdeviceproxy.cpp @@ -25,26 +25,37 @@ OLIVE_NAMESPACE_ENTER -AudioOutputDeviceProxy::AudioOutputDeviceProxy() : - device_(nullptr) +AudioOutputDeviceProxy::AudioOutputDeviceProxy() { } +AudioOutputDeviceProxy::~AudioOutputDeviceProxy() +{ + if (file_.isOpen()) { + file_.close(); + } +} + void AudioOutputDeviceProxy::SetParameters(const AudioRenderingParams ¶ms) { params_ = params; } -void AudioOutputDeviceProxy::SetDevice(QIODevice *device, int playback_speed) +void AudioOutputDeviceProxy::SetDevice(const QString &filename, qint64 offset, int playback_speed) { - device_ = device; - - if (!device_->isOpen()) { - if (!device_->open(QIODevice::ReadOnly)) { - qWarning() << "Failed to open sub-device"; - } + if (file_.isOpen()) { + file_.close(); } + file_.setFileName(filename); + + if (!file_.open(QFile::ReadOnly)) { + qCritical() << "Failed to open" << filename << "for audio playback"; + return; + } + + file_.seek(offset); + playback_speed_ = playback_speed; if (qAbs(playback_speed_) != 1) { @@ -56,7 +67,7 @@ void AudioOutputDeviceProxy::close() { QIODevice::close(); - device_->close(); + file_.close(); if (tempo_processor_.IsOpen()) { tempo_processor_.Close(); @@ -65,7 +76,7 @@ void AudioOutputDeviceProxy::close() qint64 AudioOutputDeviceProxy::readData(char *data, qint64 maxlen) { - if (device_) { + if (file_.isOpen()) { qint64 read_count; @@ -106,21 +117,21 @@ qint64 AudioOutputDeviceProxy::ReverseAwareRead(char *data, qint64 maxlen) if (playback_speed_ < 0) { // If we're reversing, we'll seek back by maxlen bytes before we read - new_pos = device_->pos() - maxlen; + new_pos = file_.pos() - maxlen; if (new_pos < 0) { - maxlen = device_->pos(); + maxlen = file_.pos(); new_pos = 0; } - device_->seek(new_pos); + file_.seek(new_pos); } - qint64 read_count = device_->read(data, maxlen); + qint64 read_count = file_.read(data, maxlen); if (playback_speed_ < 0) { - device_->seek(new_pos); + file_.seek(new_pos); // Reverse the samples here AudioManager::ReverseBuffer(data, static_cast(read_count), params_.samples_to_bytes(1)); diff --git a/app/audio/outputdeviceproxy.h b/app/audio/outputdeviceproxy.h index bf639c7fc..52c6a8ca9 100644 --- a/app/audio/outputdeviceproxy.h +++ b/app/audio/outputdeviceproxy.h @@ -21,22 +21,27 @@ #ifndef AUDIOOUTPUTDEVICEPROXY_H #define AUDIOOUTPUTDEVICEPROXY_H -#include +#include #include "common/define.h" #include "tempoprocessor.h" OLIVE_NAMESPACE_ENTER +/** + * @brief QIODevice wrapper that can adjust speed/reverse an audio file + */ class AudioOutputDeviceProxy : public QIODevice { Q_OBJECT public: AudioOutputDeviceProxy(); + virtual ~AudioOutputDeviceProxy() override; + void SetParameters(const AudioRenderingParams& params); - void SetDevice(QIODevice* device, int playback_speed); + void SetDevice(const QString &filename, qint64 offset, int playback_speed); virtual void close() override; @@ -48,7 +53,7 @@ protected: private: qint64 ReverseAwareRead(char* data, qint64 maxlen); - QIODevice* device_; + QFile file_; TempoProcessor tempo_processor_; diff --git a/app/audio/outputmanager.cpp b/app/audio/outputmanager.cpp index aa1a97911..1b4e20c57 100644 --- a/app/audio/outputmanager.cpp +++ b/app/audio/outputmanager.cpp @@ -82,9 +82,9 @@ void AudioOutputManager::SetParameters(const AudioRenderingParams ¶ms) device_proxy_.SetParameters(params); } -void AudioOutputManager::PullFromDevice(QIODevice *device, int playback_speed) +void AudioOutputManager::PullFromDevice(const QString &filename, qint64 offset, int playback_speed) { - if (!output_ || !device) { + if (!output_) { return; } @@ -94,7 +94,7 @@ void AudioOutputManager::PullFromDevice(QIODevice *device, int playback_speed) pushed_samples_.clear(); // Pull from the device - device_proxy_.SetDevice(device, playback_speed); + device_proxy_.SetDevice(filename, offset, playback_speed); device_proxy_.open(QIODevice::ReadOnly); output_->start(&device_proxy_); } diff --git a/app/audio/outputmanager.h b/app/audio/outputmanager.h index cf06f0641..e845b02f9 100644 --- a/app/audio/outputmanager.h +++ b/app/audio/outputmanager.h @@ -52,7 +52,7 @@ public: * This will clear any pushed samples or QIODevices currently being read and will start reading from this next time * the audio output requests data. */ - void PullFromDevice(QIODevice* device, int playback_speed); + void PullFromDevice(const QString &filename, qint64 offset, int playback_speed); void ResetToPushMode(); diff --git a/app/render/backend/audio/audiobackend.cpp b/app/render/backend/audio/audiobackend.cpp index 60923cf89..07c023187 100644 --- a/app/render/backend/audio/audiobackend.cpp +++ b/app/render/backend/audio/audiobackend.cpp @@ -34,13 +34,6 @@ AudioBackend::~AudioBackend() Close(); } -QIODevice *AudioBackend::GetAudioPullDevice() -{ - pull_device_.setFileName(CachePathName()); - - return &pull_device_; -} - bool AudioBackend::InitInternal() { // Initiate one thread per CPU core diff --git a/app/render/backend/audio/audiobackend.h b/app/render/backend/audio/audiobackend.h index 8f4772148..81b423c68 100644 --- a/app/render/backend/audio/audiobackend.h +++ b/app/render/backend/audio/audiobackend.h @@ -35,8 +35,6 @@ public: virtual ~AudioBackend() override; - virtual QIODevice* GetAudioPullDevice() override; - protected: virtual bool InitInternal() override; @@ -51,9 +49,6 @@ protected: private slots: void ThreadCompletedCache(NodeDependency dep, NodeValueTable data, qint64 job_time); -private: - QFile pull_device_; - }; OLIVE_NAMESPACE_EXIT diff --git a/app/render/backend/audiorenderbackend.h b/app/render/backend/audiorenderbackend.h index e01cee92e..f2420079d 100644 --- a/app/render/backend/audiorenderbackend.h +++ b/app/render/backend/audiorenderbackend.h @@ -40,8 +40,6 @@ public: */ void SetParameters(const AudioRenderingParams ¶ms); - virtual QIODevice* GetAudioPullDevice() = 0; - const AudioRenderingParams& params() const; QString CachePathName() const; diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index 3c90345c2..4ccae54f6 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -355,11 +355,10 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only) playback_speed_ = speed; play_in_to_out_only_ = in_to_out_only; - 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())); + QString audio_fn = audio_renderer_->CachePathName(); + if (!audio_fn.isEmpty()) { AudioManager::instance()->SetOutputParams(audio_renderer_->params()); - AudioManager::instance()->StartOutput(audio_src, playback_speed_); + AudioManager::instance()->StartOutput(audio_fn, audio_renderer_->params().time_to_bytes(GetTime()), playback_speed_); } start_msec_ = QDateTime::currentMSecsSinceEpoch(); @@ -378,19 +377,20 @@ void ViewerWidget::PushScrubbedAudio() { if (!IsPlaying() && Config::Current()["AudioScrubbing"].toBool()) { // Get audio src device from renderer - QIODevice* audio_src = audio_renderer_->GetAudioPullDevice(); + QString audio_fn = audio_renderer_->CachePathName(); + QFile audio_src(audio_fn); - if (audio_src && audio_src->open(QFile::ReadOnly)) { + if (audio_src.open(QFile::ReadOnly)) { // FIXME: Hardcoded scrubbing interval (20ms) int size_of_sample = audio_renderer_->params().time_to_bytes(rational(20, 1000)); // Push audio - audio_src->seek(audio_renderer_->params().time_to_bytes(GetTime())); - QByteArray frame_audio = audio_src->read(size_of_sample); + 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(); + audio_src.close(); } } }