Qt - 从QBytearray获取音频幅度

时间:2012-12-20 08:45:50

标签: qt audio-recording waveform amplitude qbytearray

我正在尝试使用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中提取音频幅度?

谢谢。

1 个答案:

答案 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