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

qWarning() << btlist.at(int) を使用して QList を出力すると、オーディオの振幅を表す正と負の数値が得られます。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、バッファの最後で無効な値を読み取ります。おそらく、ガベージ\読み取りゼロ\クラッシュを読み取ります。

そして、あなたのバッファはbyte bufferです。そして、短いポインタを使用して反復します。したがって、使用するかどうか、またはl最大サイズを 2 で割る必要があります。これはおそらく、写真のゼロのリング ラインの原因です。len

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