Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.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++ 如何在Qt中混合音频输入设备_C++_Qt_Qtmultimedia - Fatal编程技术网

C++ 如何在Qt中混合音频输入设备

C++ 如何在Qt中混合音频输入设备,c++,qt,qtmultimedia,C++,Qt,Qtmultimedia,我是Qt多媒体库的新手,在我的应用程序中,我希望混合来自多个输入设备(例如麦克风)的音频,以便通过TCP传输 据我所知,我必须首先获得所有所需设备的特定qaudioviceinfo,以及相应的QAudioFormat对象,并将其与QAudioInput一起使用。然后,我只需为每个创建的QAudioInput对象调用start(),并使用readLine()读取挂起的字节 但是如何将多个设备的音频数据混合到一个缓冲区?我不确定是否有任何特定于Qt的方法/类可以做到这一点。不过,自己动手做很简单 最

我是Qt多媒体库的新手,在我的应用程序中,我希望混合来自多个输入设备(例如麦克风)的音频,以便通过TCP传输

据我所知,我必须首先获得所有所需设备的特定
qaudioviceinfo
,以及相应的
QAudioFormat
对象,并将其与
QAudioInput
一起使用。然后,我只需为每个创建的
QAudioInput
对象调用
start()
,并使用
readLine()
读取挂起的字节


但是如何将多个设备的音频数据混合到一个缓冲区?

我不确定是否有任何特定于Qt的方法/类可以做到这一点。不过,自己动手做很简单

最基本的方法(假设您使用的是PCM),您可以简单地将两个流/缓冲区逐字添加到一起(如果我记得它们是16位PCM字)

因此,如果您有两个输入缓冲区:

int16 buff1[10];
int16 buff2[10];
int16 mixBuff[10];

// Fill them...
//... code goes here to read from the buffers ....

// Add them (effectively mix them)

for (int i = 0; i < 10; i++)
{
   mixBuff[i] = buff1[i] + buff2[i];
}
int16 buff1[10];
int16-buff2[10];
int16混合buff[10];
//填满它们。。。
//... 这里的代码用于从缓冲区读取。。。。
//添加它们(有效地混合它们)
对于(int i=0;i<10;i++)
{
mixBuff[i]=buff1[i]+buff2[i];
}
现在,这是非常粗糙的,没有考虑任何缩放。因此,假设buff1和buff2都使用80%的动态范围(称之为完整音量,超过该音量会产生失真),那么当您将它们相加时,将出现数字溢出(即16位最大值为65535,因此50000+50000将是一个溢出)

每次混合时,有效地需要两个输入的一半(因此65535/2+65535/2=65535…也就是说,当你将它们相加时,你不能超支)。因此,您的混合代码如下所示:

for (int i = 0; i < 10; i++)
{
   mixBuff[i] = (buff1[i] >> 1) + (buff2[i] >> 1);
}
for(int i=0;i<10;i++)
{
mixBuff[i]=(buff1[i]>>1)+(buff2[i]>>1);
}
你可以做的还有很多(噪音消除等),但是数学开始变得有点毛茸茸的。这很简单。如果需要,您可以使用shift来增加/减少音量,作为简单的音量控制

编辑


有一件事需要注意。。。您使用的是readline()(文档称它以ASCII格式读取数据)。我总是使用read(),它没有说明读取的“格式”,但我假设是二进制的。因此,如果使用readline(),此代码可能不起作用,但我从未尝试过。它适用于read(),如果您想处理数据,您并不想使用ASCII。

好吧,仔细阅读您的答案后,它看起来非常简单。肯定会很快尝试的。有什么建议我应该选择什么缓冲区大小吗?我需要实时流,没有任何延迟(如果可能的话)。我发现这是延迟(等待大量数据的延迟)和处理/效率之间的折衷。因此,如果您想要低延迟,那么可以使用缓冲区大小约10个字(20字节)。在每秒16kbps 16000/8=2000字节的速度下,这大约是10ms,因此延迟时间很短,但处理器将经常被唤醒。我假设您正在使用readReady()信号,因此它仅在有数据时才会唤醒(即您没有轮询)?是的,我会轮询,并且我正在使用
read()
。每次音频设备有可用字节时,我都会将数据附加到主缓冲区,但我只是获取足够的数据来完全填充缓冲区,然后再发出相应的信号,通知其他类新的数据块可用。如果主缓冲区仍处于最大容量,但有来自音频设备的挂起数据,我会在开始时丢弃足够的数据,以便为新数据腾出空间。说到音频质量,我总是需要使用
2个通道
24位深度
48kHz采样率
来传输音频数据。我做了一个小计算来确定所需的带宽
2个通道
x
24位
x
48kHz
281,25kbyte/s
的数据量。对于实时流,我选择了
10ms延迟
,因此我需要每个周期获得最少
2,81 kbytes
的数据。这样更好吗?最好将
QIODevice signal readyRead()
连接到插槽。然后,无论何时收到任何消息,都会调用您的插槽(比轮询更有效)。然后在插槽中,您总是读取所有内容并将其放入您自己的缓冲区,然后当您有足够的数据时发送。我会避免在实时应用程序中填满缓冲区,因为你经常需要一些回旋余地。假设您的数据包是2000字节,那么您可以将缓冲区设置为4000字节。一旦>2000,则发送数据包。代码仍然可以非常简单。如果空间是个问题,那就把一切都缩小。