audio: don't use a shared QIODevice

This system was kind of janky anyway. It makes more sense ultimately for the
audio management classes to contain the file handle rather than the renderer.
This commit is contained in:
itsmattkc
2020-04-21 17:55:55 +10:00
parent 1d3b9bbf13
commit 05eae1e28a
10 changed files with 51 additions and 49 deletions
+2 -2
View File
@@ -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()
+1 -1
View File
@@ -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
+27 -16
View File
@@ -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 &params)
{
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<int>(read_count), params_.samples_to_bytes(1));
+8 -3
View File
@@ -21,22 +21,27 @@
#ifndef AUDIOOUTPUTDEVICEPROXY_H
#define AUDIOOUTPUTDEVICEPROXY_H
#include <QIODevice>
#include <QFile>
#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_;
+3 -3
View File
@@ -82,9 +82,9 @@ void AudioOutputManager::SetParameters(const AudioRenderingParams &params)
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_);
}
+1 -1
View File
@@ -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();
@@ -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
-5
View File
@@ -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
-2
View File
@@ -40,8 +40,6 @@ public:
*/
void SetParameters(const AudioRenderingParams &params);
virtual QIODevice* GetAudioPullDevice() = 0;
const AudioRenderingParams& params() const;
QString CachePathName() const;
+9 -9
View File
@@ -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();
}
}
}