1

我正在尝试使用 Qt (c++) 创建一个程序,该程序可以使用 QAudioinput 和 QIODevice 从我的麦克风录制音频。我进行了一项研究,并想出了一个位于此页面上的示例。这个例子做我需要的。

现在,我正在尝试创建录制声音的音频波形。我想提取音频幅度并将它们保存在 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() << 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 在像这样的幅度数据之间也有很多零 (0) ,如果我将其绘制为波形,它们是一条直线,这是不正常的,因为它会损坏我的波形。我的问题是为什么会这样?这些零 (0) 代表什么?难道我做错了什么?另外,有没有更好的方法从 QBytearray 中提取音频幅度?

谢谢你。

4

1 回答 1

0

您使用的 drawline 方法采用整数值。这意味着大多数时候您的两个x索引都是相同的。通过简化您的公式,x给定的值i(i/5.0)。就其本身而言,这不是问题,因为线条将被叠加,这是一种完美的绘图方式(只是为了确保这是您想要做的)。

您看到的零可能是完全有效的。他们代表沉默

真正的问题是 16 位 PCM 值的范围是[-32767 , 32768]. 我怀疑您使用的油漆设备是否涵盖此范围。您需要标准化您的 y 轴。此外,qt 协调系统似乎没有负值(编辑:不要介意负数,它说逻辑坐标已转换)。

例如,使用以下转换您的 pcm 值:

  ((btlist.at(i) / MAX_AMPLITUDE + 1.0) / 2) * paintDevice.height();

编辑:

顺便说一句,您没有使用l,这是您读取的真实数据量。如果它不如len,您将在缓冲区末尾读取无效值,可能会读取垃圾\读取零\崩溃。

你的缓冲区是一个字节缓冲区。并且您使用短指针进行迭代。所以无论你使用l还是len最大尺寸都需要除以二。这可能是您图片中零线的原因。

 for ( i=0; i < l/2; i++ )
 {
     btlist.append( resultingData[ i ]);
 }
于 2012-12-20T09:39:42.940 回答