如何在QT中实现简单的音频环回

rub*_*bmz 0 qt audio-recording qtmultimedia

我需要使用QT(从Windows上的qt 5.7)将从麦克风录制的音频直接回送至扬声器(假设在Windows上为qt 5.7)-假设我无法使用窗口的内部mic->扬声器回送(在麦克风面板上启用“收听此设备” )。

任何方向该怎么做?

Vel*_*kan 5

基于关于https://forum.qt.io/topic/19960/qaudioinput-redirect-to-qaudiooutput/3的讨论

#include <iostream>

#include <QCoreApplication>
#include <QAudioInput>
#include <QAudioOutput>

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    const auto decideAudioFormat = [](const QAudioDeviceInfo& devInfo)
    {
        QAudioFormat format;
        format.setSampleRate(8000);
        format.setChannelCount(1);
        format.setSampleSize(16);
        format.setCodec("audio/pcm");
        format.setByteOrder(QAudioFormat::LittleEndian);
        format.setSampleType(QAudioFormat::SignedInt);

        if (devInfo.isFormatSupported(format))
        {
            return format;
        }
        else
        {
            std::cerr << "Raw audio format not supported by backend, cannot play audio.\n";
            throw 0;
        }
    };

    QAudioInput audioInput(decideAudioFormat(QAudioDeviceInfo::defaultInputDevice()));
    QAudioOutput audioOutput(decideAudioFormat(QAudioDeviceInfo::defaultOutputDevice()));

    audioOutput.start(audioInput.start());

    return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

在两者之间添加缓冲区

我以前遇到过这个问题。如果我没记错的话,read()和write()函数共享同一个pos()跟踪器。这是发生了什么:

QBuffer buffer;

buffer.open(QBuffer::ReadWrite); // buffer.pos() == 0
buffer.write(someData, 5); // Writes in positions 0 -- 4, buffer.pos() == 5;
buffer.write(someData, 5); // Writes in positions 5 -- 9, buffer.pos() == 10;
buffer.read(otherBuffer.data(), 10); // Tries to read from position 10 onwards. No data found
Run Code Online (Sandbox Code Playgroud)

2个解决方案:

实现您自己的单独的读取位置和写入位置跟踪器。然后,在readData()和writeData()中调用seek()以设置pos()-在写入之前指向数据的结尾,但在读取之前指向数据的中间

使用2个单独的缓冲区,并将字节从输入缓冲区复制到输出缓冲区

因此,使用单独的缓冲区:

#include <iostream>
#include <cassert>

#include <QCoreApplication>
#include <QAudioInput>
#include <QAudioOutput>
#include <QBuffer>

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    QBuffer rdBuff;
    QBuffer wrBuff;
    wrBuff.open(QBuffer::WriteOnly);
    rdBuff.open(QBuffer::ReadOnly);

    QObject::connect(&wrBuff, &QIODevice::bytesWritten, [&wrBuff, &rdBuff](qint64)
    {
        // remove all data that was already read
        rdBuff.buffer().remove(0, rdBuff.pos());

        // set pointer to the beginning of the unread data
        const auto res = rdBuff.seek(0);
        assert(res);

        // write new data
        rdBuff.buffer().append(wrBuff.buffer());

        // remove all data that was already written
        wrBuff.buffer().clear();
        wrBuff.seek(0);
    });

    const auto decideAudioFormat = [](const QAudioDeviceInfo& devInfo)
    {
        QAudioFormat format;
        format.setSampleRate(8000);
        format.setChannelCount(1);
        format.setSampleSize(16);
        format.setCodec("audio/pcm");
        format.setByteOrder(QAudioFormat::LittleEndian);
        format.setSampleType(QAudioFormat::SignedInt);

        if (devInfo.isFormatSupported(format))
        {
            return format;
        }
        else
        {
            std::cerr << "Raw audio format not supported by backend, cannot play audio.\n";
            throw 0;
        }
    };

    QAudioInput audioInput(decideAudioFormat(QAudioDeviceInfo::defaultInputDevice()));
    QAudioOutput audioOutput(decideAudioFormat(QAudioDeviceInfo::defaultOutputDevice()));

    audioInput.start(&wrBuff);
    audioOutput.start(&rdBuff);

    return app.exec();
}
Run Code Online (Sandbox Code Playgroud)