我正在尝试使用Qt(c ++)创建一个程序,它可以使用QAudioinput和QIODevice从我的麦克风录制音频。我做了一个研究,我想出了一个位于page的例子。这个例子做我需要的。
现在,我正在尝试创建录制声音的音频波形。我想提取音频幅度并将它们保存在QList上。为此,我使用以下代码:
//Check the number of samples in input buffer
qint64 len = m_audioInput->bytesReady();
//Limit sample size
if(len > 4096)
len = 4096;
//Read sound samples from input device to buffer
qint64 l = m_input->read(m_buffer.data(), len);
if(l > 0)
{
//Assign sound samples to short array
short* resultingData = (short*)m_buffer.data();
for ( i=0; i < len; i++ )
{
btlist.append( resultingData[ i ]);
}
}
m_audioInput是QAudioinput | m_buffer是QBytearray | m_input是QIODevice | btlist是QList
我使用以下QAudioFormat:
m_format.setFrequency(44100); //set frequency to 44100
m_format.setSampleRate(44100); //set sample rate to 44100
m_format.setChannels(1); //set channels to mono
m_format.setSampleSize(16); //set sample sze to 16 bit
m_format.setSampleType(QAudioFormat::SignedInt ); //signed integer sample
m_format.setByteOrder(QAudioFormat::LittleEndian); //Byte order
m_format.setCodec("audio/pcm"); //set codec as simple audio/pcm
当我打印我的QList时,使用qWarning()&lt;&lt; btlist.at(int),我得到一些正负数,代表我的音频幅度。我使用Microsoft Excel绘制数据并将其与实际声音波形进行比较。
(根据OP评论编辑) 我正在使用Qt中的QPainter绘制波形,如下所示
for(int i = 1; i < btlist.size(); i++){
double x1 = (i-(i/1.25))-0.2;
double y1 = btlist.at(i-1);
double x2 = i-(i/1.25);
double y2 = btlist.at(i);
painter.drawLine(x1,y1,x2, y2);
}
问题是我的QList中的this之类的振幅数据之间也有很多零(0),如果我绘制为波形它们是直线,这是不正常的,因为它会导致我的波形损坏。 我的问题是为什么会发生这种情况?这些零(0)代表什么?难道我做错了什么?另外,有没有更好的方法从QBytearray中提取音频幅度?
谢谢。
答案 0 :(得分:0)
您使用的绘制线方法采用 整数值 。这意味着大多数时候你的x
索引都是一样的。通过简化您的公式,给定x
的{{1}}值为i
。它本身并不是一个问题,因为线条会叠加,它是一种完美的绘图方式(只是为了确保你想做的事情)。
你看到的零可以完全有效。它们代表 沉默 。
真正的问题是16位PCM值的范围是(i/5.0)
。我怀疑你使用的油漆设备是否涵盖了这个范围。您需要标准化您的y轴。此外,它似乎是the qt coordinated system doesn't have negative values(编辑:没关系负面,它说逻辑坐标被转换)。
例如,使用以下方法转换pcm值:
[-32767 , 32768]
修改:
顺便说一句,您没有使用 ((btlist.at(i) / MAX_AMPLITUDE + 1.0) / 2) * paintDevice.height();
,这是您阅读的真实数据量。如果它不如l
,您将在缓冲区末尾读取无效值,可能是读取garbage \ read zeros \ crash。
您的缓冲区是 字节缓冲区 。然后使用 短指针 进行迭代。因此,无论您使用len
还是l
,最大尺寸都需要除以2 。这可能是你图片中零线的原因。
len