Qt: Fix underrun stalling with Qt6

This commit is contained in:
Vicki Pfau 2024-03-25 21:16:09 -07:00
parent 1179d218e7
commit ae8b88a4a3
4 changed files with 47 additions and 1 deletions

View File

@ -62,3 +62,13 @@ qint64 AudioDevice::writeData(const char*, qint64) {
LOG(QT, WARN) << tr("Writing data to read-only audio device");
return 0;
}
bool AudioDevice::atEnd() const {
if (!m_context->core) {
return true;
}
mCoreSyncLockAudio(&m_context->impl->sync);
bool available = blip_samples_avail(m_context->core->getAudioChannel(m_context->core, 0)) == 0;
mCoreSyncUnlockAudio(&m_context->impl->sync);
return available;
}

View File

@ -20,6 +20,7 @@ public:
void setInput(mCoreThread* input);
void setFormat(const QAudioFormat& format);
bool atEnd() const override;
protected:
virtual qint64 readData(char* data, qint64 maxSize) override;

View File

@ -21,6 +21,10 @@ using namespace QGBA;
AudioProcessorQt::AudioProcessorQt(QObject* parent)
: AudioProcessor(parent)
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
m_recheckTimer.setInterval(1);
connect(&m_recheckTimer, &QTimer::timeout, this, &AudioProcessorQt::recheckUnderflow);
#endif
}
void AudioProcessorQt::setInput(std::shared_ptr<CoreController> controller) {
@ -34,6 +38,9 @@ void AudioProcessorQt::setInput(std::shared_ptr<CoreController> controller) {
}
void AudioProcessorQt::stop() {
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
m_recheckTimer.stop();
#endif
if (m_audioOutput) {
m_audioOutput->stop();
m_audioOutput.reset();
@ -72,6 +79,12 @@ bool AudioProcessorQt::start() {
QAudioDevice device(QMediaDevices::defaultAudioOutput());
m_audioOutput = std::make_unique<QAudioSink>(device, format);
LOG(QT, INFO) << "Audio outputting to " << device.description();
connect(m_audioOutput.get(), &QAudioSink::stateChanged, this, [this](QAudio::State state) {
if (state != QAudio::IdleState) {
return;
}
m_recheckTimer.start();
});
#endif
}
@ -86,6 +99,9 @@ bool AudioProcessorQt::start() {
}
void AudioProcessorQt::pause() {
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
m_recheckTimer.stop();
#endif
if (m_audioOutput) {
m_audioOutput->suspend();
}
@ -115,3 +131,16 @@ unsigned AudioProcessorQt::sampleRate() const {
}
return m_audioOutput->format().sampleRate();
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
void AudioProcessorQt::recheckUnderflow() {
if (!m_device) {
m_recheckTimer.stop();
return;
}
if (!m_device->atEnd()) {
start();
m_recheckTimer.stop();
}
}
#endif

View File

@ -11,6 +11,7 @@
#include <QAudioOutput>
#else
#include <QAudioSink>
#include <QTimer>
#endif
class QAudioOutput;
@ -38,10 +39,15 @@ public slots:
virtual void requestSampleRate(unsigned) override;
private:
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
private slots:
void recheckUnderflow();
private:
QTimer m_recheckTimer;
std::unique_ptr<QAudioSink> m_audioOutput;
#else
private:
std::unique_ptr<QAudioOutput> m_audioOutput;
#endif
std::unique_ptr<AudioDevice> m_device;