QAudioOutput - 应用程序规模不断增长
Posted
技术标签:
【中文标题】QAudioOutput - 应用程序规模不断增长【英文标题】:QAudioOutput - application size is continuously growing 【发布时间】:2016-06-23 13:42:48 【问题描述】:我正在尝试每 20 毫秒写入一次 QAudioOutput 的缓冲区。当我尝试执行此代码时,我可以看到进程的大小每秒增加约 4-8 kB。我试图找到一些函数来清除 QIODevice 或 DAudioOuptut 的内部缓冲区,但没有运气。
我使用的是 Qt 5.2.1
在下面的例子中只写了静音(零)但它具有相同的效果:
#include <QLibraryInfo>
#include <QtCore/QCoreApplication>
#include <windows.h> // for Sleep
#include <QAudioOutput>
#include <QAudioDeviceInfo>
#include <QAudioFormat>
#include <array>
class QAudioOutput;
int main(int argc, char *argv[])
// Create QApplication
QCoreApplication app(argc, argv);
app.setApplicationName("Audiotest");
//Initialize device
QIODevice * _output;
QAudioDeviceInfo _device = QAudioDeviceInfo::defaultOutputDevice();
QAudioFormat _format;
_format.setSampleRate(44100);
_format.setChannelCount(2);
_format.setSampleSize(16);
_format.setCodec("audio/pcm"); // This codec should be supported on all platforms and plugin implementation
_format.setByteOrder(QAudioFormat::LittleEndian);
_format.setSampleType(QAudioFormat::SignedInt);
if (!_device.isFormatSupported(_format))
printf("Default format not supported - trying to use nearest.\n");
_format = _device.nearestFormat(_format);
QAudioOutput * _audioOutput = new QAudioOutput(_device, _format);
_output = _audioOutput->start();
std::array<char, 32768> _buffer;
_buffer.fill(0);
for (;;)
const int periodSize = _audioOutput->periodSize();
const int chunks = _audioOutput->bytesFree() / periodSize;
for (int i = 0; i < chunks; ++i)
const qint64 len = periodSize;
if (len && _output)
_output->write(_buffer.data(), len);
if (len != periodSize)
break;
Sleep(20);
return 0;
【问题讨论】:
如果你占用主线程,你不应该不时打电话给processEvents
吗?
@PeterT 一开始就不应该占用任何东西。这根本不是编写此类代码的方式。
即使您根本不应该在这里使用阻塞睡眠,但您可能希望在将来需要时使用便携式 QThread::msleep
。
【参考方案1】:
当您的循环运行时,其他任何事情都不会发生。您的代码应该是异步的,并且您应该反转控制流。对音频输出设备发出的已处理一定间隔样本的通知作出反应。
要接收第一个通知,您需要使用一些数据来启动设备。
// https://github.com/KubaO/***n/tree/master/questions/audio-37993427
#include <QtMultimedia>
#include <array>
int main(int argc, char ** argv)
QCoreApplication appargc, argv;
auto device = QAudioDeviceInfo::defaultOutputDevice();
QAudioFormat format;
format.setSampleRate(44100);
format.setChannelCount(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
if (!device.isFormatSupported(format))
qFatal("Default format not supported");
QAudioOutput audioOutputdevice, format;
auto output = audioOutput.start();
qDebug() << audioOutput.state();
std::array<char, 32768> buffer;
buffer.fill(0);
auto write = [&]
qDebug() << "notify";
auto periodSize = audioOutput.periodSize();
auto chunks = audioOutput.bytesFree() / periodSize;
for (int i = 0; i < chunks; ++i)
if (periodSize && output)
auto len = output->write(buffer.data(), periodSize);
if (len != periodSize)
break;
;
audioOutput.setNotifyInterval(20);
QObject::connect(&audioOutput, &QAudioOutput::notify, write);
write();
return app.exec();
【讨论】:
【参考方案2】:不要运行自己的事件循环;相反,将 QAudioOutput 的 notify
信号连接到您的一个 QObjects 中的插槽,并让该插槽调用 write() 一次。每当 QAudioOutput 需要播放更多音频数据时,就会发出通知信号。
所有这些都将发生在 QApplication::exec() 中,您应该调用它(在 main() 的末尾附近)为您运行 Qt 事件循环,而不是您自己的 for 循环。
【讨论】:
以上是关于QAudioOutput - 应用程序规模不断增长的主要内容,如果未能解决你的问题,请参考以下文章