Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ QAudioOutput—应用程序规模不断增长_C++_Qt_Qiodevice - Fatal编程技术网

C++ QAudioOutput—应用程序规模不断增长

C++ QAudioOutput—应用程序规模不断增长,c++,qt,qiodevice,C++,Qt,Qiodevice,我试图每20毫秒写入QAudioOutput的缓冲区。当我尝试执行这段代码时,我可以看到进程的大小每秒增加4-8KB。我试图找到一些函数来清除QIODevice或Daudiouput的内部缓冲区,但没有成功 我正在使用Qt5.2.1 在下面的示例中,仅写入静默(零),但其效果相同: #include <QLibraryInfo> #include <QtCore/QCoreApplication> #include <windows.h> // for Sle

我试图每20毫秒写入QAudioOutput的缓冲区。当我尝试执行这段代码时,我可以看到进程的大小每秒增加4-8KB。我试图找到一些函数来清除QIODevice或Daudiouput的内部缓冲区,但没有成功

我正在使用Qt5.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;
}
#包括
#包括
#包括//用于睡眠
#包括
#包括
#包括
#包括
类音频输出;
int main(int argc,char*argv[])
{
//创建QApplication
QCore应用程序应用程序(argc、argv);
app.setApplicationName(“音频测试”);
//初始化设备
QIODevice*_输出;
QAudioDeviceInfo _device=QAudioDeviceInfo::defaultOutputDevice();
QAudioFormat_格式;
_格式:setSampleRate(44100);
_格式。setChannelCount(2);
_格式设置示例(16);
_format.setCodec(“audio/pcm”);//所有平台和插件实现都应支持此编解码器
_setByteOrder格式(QAudioFormat::LittleEndian);
_format.setSampleType(QAudioFormat::SignedInt);
如果(!\u设备.isFormatSupported(\u格式)){
printf(“不支持默认格式-尝试使用最近的格式。\n”);
_格式=\设备。最接近的格式(\格式);
}
QAudioOutput*\u audioOutput=新的QAudioOutput(\u设备,\u格式);
_输出=_audioOutput->start();
std::数组_缓冲区;
_缓冲区填充(0);
对于(;;){
const int periodSize=_audioOutput->periodSize();
const int chunks=\u audioOutput->bytesFree()/periodSize;
for(int i=0;i写入(_buffer.data(),len);
}
if(len!=周期大小){
打破
}
}
睡眠(20);
}
返回0;
}

不要运行自己的事件循环;相反,将QAudioOutput的
notify
信号连接到一个QObject中的插槽,并让该插槽调用write()一次。每当QAudioOutput需要播放更多的音频数据时,就会发出通知信号


所有这些都将发生在QApplication::exec()内部,您应该调用它(在main()的末尾附近)来为您运行Qt事件循环,而不是您自己的for循环。

不要运行您自己的事件循环;相反,将QAudioOutput的
notify
信号连接到一个QObject中的插槽,并让该插槽调用write()一次。每当QAudioOutput需要播放更多的音频数据时,就会发出通知信号


所有这些都将发生在QApplication::exec()内部,您应该调用它(在main()的末尾附近)来为您运行Qt事件循环,而不是您自己的for循环。

当您的循环运行时,其他任何操作都不会执行。您的代码应该是异步的,并且应该反转控制流。对音频输出设备发出的已处理某个采样间隔的通知作出反应

要接收第一个通知,您需要为设备注入一些数据

// https://github.com/KubaO/stackoverflown/tree/master/questions/audio-37993427
#include <QtMultimedia>
#include <array>

int main(int argc, char ** argv) {
   QCoreApplication app{argc, 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 audioOutput{device, 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();
}
//https://github.com/KubaO/stackoverflown/tree/master/questions/audio-37993427
#包括
#包括
int main(int argc,字符**argv){
QCoreApplication{argc,argv};
自动设备=QAudioDeviceInfo::defaultOutputDevice();
QAudioFormat格式;
格式:setSampleRate(44100);
格式。setChannelCount(2);
格式设置示例(16);
格式化.setCodec(“音频/pcm”);
setByteOrder格式(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
如果(!device.isFormatSupported(格式))
qFatal(“不支持默认格式”);
QAudioOutput音频输出{设备,格式};
自动输出=audioOutput.start();

qDebug()当循环运行时,其他任何操作都不起作用。您的代码应该是异步的,并且应该反转控制流。对音频输出设备发出的已处理特定采样间隔的通知作出反应

要接收第一个通知,您需要为设备注入一些数据

// https://github.com/KubaO/stackoverflown/tree/master/questions/audio-37993427
#include <QtMultimedia>
#include <array>

int main(int argc, char ** argv) {
   QCoreApplication app{argc, 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 audioOutput{device, 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();
}
//https://github.com/KubaO/stackoverflown/tree/master/questions/audio-37993427
#包括
#包括
int main(int argc,字符**argv){
QCoreApplication{argc,argv};
自动设备=QAudioDeviceInfo::defaultOutputDevice();
QAudioFormat格式;
格式:setSampleRate(44100);
格式。setChannelCount(2);
格式设置示例(16);
格式化.setCodec(“音频/pcm”);
setByteOrder格式(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
如果(!device.isFormatSupported(格式))
qFatal(“不支持默认格式”);
QAudioOutput音频输出{设备,格式};
自动输出=audioOutput.start();

qDebug()如果你占用主线程,你不应该不时调用吗?@PeterT One一开始就不应该占用任何东西。这根本不是编写此类代码的方式。即使你根本不应该在这里使用阻塞睡眠,将来当你确实需要时,你可能希望使用可移植的
QThread::msleep
。不是吗如果你占用主线程,你会不时调用吗?@PeterT One一开始就不应该占用任何东西。这根本不是编写此类代码的方式。即使你根本不应该在这里使用阻塞睡眠,将来当你确实需要时,你可能希望使用可移植的
QThread::msleep