gpt4 book ai didi

c++ - 使用 QAudioOutput (qt) 进行实时流式传输

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:35:39 29 4
gpt4 key购买 nike

我想播放实时声音以响应用户交互而没有明显的延迟。

为了低延迟,我必须发送小块的 pcm 数据。我在做什么:

    QAudioFormat format;
format.setSampleRate(22050);
format.setChannelCount(1);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);

QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
qWarning()<<"raw audio format not supported by backend, cannot play audio.";
return;
}

qAudioOutput = new QAudioOutput(format, NULL);

qAudioDevice=qAudioOutput->start();

以后

void Enqueue(TYPESAMPLEPCM *data,int countBytes){
while(qAudioOutput->bytesFree()<countBytes){
Sleep(1);
}
qAudioDevice->write((char *)data,countBytes);
}

数据 block 为 256 字节(128 个样本将提供大约 6 毫秒的“粒度”。

Enqueue 是从提供数据 block 的具有高优先级的线程中的循环中调用的。那里没有延迟,因为它调用 Enqueue 的速度比渲染音频数据快得多。

但在我看来,存在缓冲区不足的情况,因为播放声音时会发出“噼啪”的规律噪音。

如果我将 block 大小增加到 256 个样本,问题几乎就消失了。开始时只有一些噼啪声(?)

平台是Windows和Qt 5.3。

这是正确的程序还是我遗漏了什么?

最佳答案

问题是关于

void Enqueue(TYPESAMPLEPCM *data,int countBytes){
while(qAudioOutput->bytesFree()<countBytes){
Sleep(1);
}
qAudioDevice->write((char *)data,countBytes);
}

有点天真。

首先Sleep(1);。你在 window 上。问题是 Windows 不是实时操作系统,预计时间分辨率约为 10 - 15 毫秒。 这意味着当没有地方接收传入的音频时,您会睡得比预期的多。

其次。当音频输出无法消耗所提供的数据量时,您真的需要 sleep 吗?您真正想要的是在音频输出消耗了一些之后提供一些音频。具体来说,这意味着:

  1. 设置QAudioOutput notify interval ,即系统将使用音频数据并告诉您的时间段。
  2. 收到关于 QAudioOutput 消耗一些数据的通知。它位于连接到 QAudioOutput::notify()
  3. 的插槽中
  4. 在音频输出已满时缓冲来自高优先级线程的数据 block 。

这给:

QByteArray samplebuffer;

//init code
{
qAudioOutput = new QAudioOutput(format, NULL);
...
qAudioOutput->setNotifyInterval(128); //play with this number
connect(qAudioOutput, SIGNAL(notify), someobject, SLOT(OnAudioNotify));
...
qAudioDevice=qAudioOutput->start();
}

void EnqueueLock(TYPESAMPLEPCM *data,int countBytes)
{
//lock mutex
samplebuffer.append((char *)data,countBytes);
tryWritingSomeSampleData();
//unlock mutex
}

//slot
void SomeClass::OnAudioNotify()
{
//lock mutex
tryWritingSomeSampleData()
//unlock mutex
}

void SomeClass::tryWritingSomeSampleData()
{
int towritedevice = min(qAudioOutput->bytesFree(), samplebuffer.size());
if(towritedevice > 0)
{
qAudioDevice->write(samplebuffer.data(),towritedevice);
samplebuffer.remove(0,towritedevice); //pop front what is written
}
}

如您所见,您需要保护 samplebuffer 免受并发访问。提供足够的互斥量。

关于c++ - 使用 QAudioOutput (qt) 进行实时流式传输,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32049950/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com