はじめに
これは Qt Advent Calendar 2024 14日目の記事です。
昨日書いた QtMultimedia にパッチを送ってみました と前提の部分が共通なので、まずはそちらを読んでいただければと思います。
マイクから音声データを読み込む処理のコードを読んでみよう
qtmultimedia/src/multimedia/pulseaudio/qpulseaudiosource.cpp
qint64 QPulseAudioSource::read(char *data, qint64 len)
{
using namespace QPulseAudioInternal;
Q_ASSERT(data != nullptr || len == 0);
m_stateMachine.updateActiveOrIdle(true, QAudio::NoError);
int readBytes = 0;
if (!m_pullMode && !m_tempBuffer.isEmpty()) {
readBytes = qMin(static_cast<int>(len), m_tempBuffer.size());
if (readBytes)
memcpy(data, m_tempBuffer.constData(), readBytes);
m_totalTimeValue += readBytes;
if (readBytes < m_tempBuffer.size()) {
m_tempBuffer.remove(0, readBytes);
return readBytes;
}
m_tempBuffer.clear();
}
while (pa_stream_readable_size(m_stream) > 0) {
...
}
...
}
ここの処理はざっと以下のような感じになっています。
-
Pull Mode
ではなかったらm_tempBuffer
に保持しているものを先に処理する - while 文内で、PulseAudio からデータを取得する
bytesAvailable() の処理を読んでみよう
qtmultimedia/src/multimedia/pulseaudio/qpulseaudiosource.cpp
qsizetype QPulseAudioSource::bytesReady() const
{
using namespace QPulseAudioInternal;
if (!m_stateMachine.isActiveOrIdle())
return 0;
std::lock_guard lock(*QPulseAudioEngine::instance());
int bytes = pa_stream_readable_size(m_stream);
if (bytes < 0) {
qWarning() << "pa_stream_readable_size() failed:" << currentError(m_stream);
return 0;
}
return static_cast<qsizetype>(bytes);
}
基本的には前述の read
と同じ構成であるべきなのですが、
-
Pull Mode
ではなかったらm_tempBuffer
に保持しているものを先に処理する
の部分が見当たりません。
修正してみました
diff --git a/src/multimedia/pulseaudio/qpulseaudiosource.cpp b/src/multimedia/pulseaudio/qpulseaudiosource.cpp
index 87bba24..5a75ac2 100644
--- a/src/multimedia/pulseaudio/qpulseaudiosource.cpp
+++ b/src/multimedia/pulseaudio/qpulseaudiosource.cpp
@@ -320,13 +320,17 @@
std::lock_guard lock(*QPulseAudioEngine::instance());
+ qsizetype tempBufferSize = 0;
+ if (!m_pullMode && !m_tempBuffer.isEmpty()) {
+ tempBufferSize = m_tempBuffer.size();
+ }
int bytes = pa_stream_readable_size(m_stream);
if (bytes < 0) {
qWarning() << "pa_stream_readable_size() failed:" << currentError(m_stream);
- return 0;
+ return tempBufferSize;
}
- return static_cast<qsizetype>(bytes);
+ return static_cast<qsizetype>(bytes) + tempBufferSize;
}
qint64 QPulseAudioSource::read(char *data, qint64 len)
read
に合わせて、Push Mode
の際には m_tempBuffer を考慮するようにしました。
PulseAudio: fix bytesAavailable of QAudioSource in push mode にて Qt 本体へ取り込んでもらうためのレビューを今行っています。
QAudioSource クラスは単体テストも存在しないので(実デバイスとの兼ね合いで難しい)、上記の変更そのままです。
おわりに
QAudioSource を使って遊んでいたら見つけたバグの修正を昨日して、今日はその周辺で見つけたバグの修正をしました。
Qt 自体のビルドも最近は簡単なので、Qt のバグを見つけたら直して、本体に取り込んでもらえるようにしてみましょう。
明日は @hermit4 さんが、なにか書いてくれるようです。お楽しみに!