2012-12-20 154 views
1

我正在嘗試使用Qt(C++)創建一個程序,該程序可以使用QAudioinput和QIODevice從我的麥克風錄製音頻。我做了一個研究,並且在這個page上找到了一個例子。這個例子就是我所需要的。Qt - 從QBytearray獲取音頻振幅

現在,我正試圖創建錄製聲音的音頻波形。我想提取音頻幅度並將它們保存在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 is 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)像this這樣的幅度數據,如果我繪製爲波形,它們是直線,這是不正常的,因爲它會導致我的波形損壞。 我的問題是爲什麼發生這種情況?這些零(0)代表什麼?難道我做錯了什麼?另外,是否有更好的方法從QBytearray中提取音頻幅度?

謝謝。

+0

你怎麼畫出你的波形? – UmNyobe

+0

你好UmNyobe,在Qt中使用QPainter繪製波形,如下所示:for(int i = 1; i DaReDeViL

+0

你是否也可以顯示你的波形,你是什麼意思的腐敗? – UmNyobe

回答

0

您正在使用的劃線方法取整數值。這意味着大多數時候你的兩個x指數都是一樣的。通過簡化公式,給定ix值爲(i/5.0)。它本身並不是問題,因爲線條會疊加,並且它是一種完美的繪畫方式(只是爲了確保這是你想要做的)。

你看到的零可以完全有效。它們代表沉默

真正的問題是您的16位PCM值的範圍是[-32767 , 32768]。我懷疑你使用的油漆裝置是否覆蓋了這個範圍。你需要規範你的Y軸。此外,它似乎是the qt coordinated system doesn't have negative values(編輯:無意中的否定,它說邏輯座標轉換)。

例如,使用轉換你的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 ]); 
} 
+0

感謝您的回覆。我注意到你和弗蘭克奧斯特費爾德提到的那個錯誤。謝謝。我將它改爲「l」,但我仍然遇到同樣的問題。情節與[鏈接]相同(http://s7.postimage.org/fxmo85pnf/waveform.png)。我也嘗試使用Excel繪製數據,並得到同樣的結果。 – DaReDeViL

+0

你用過'l/2'嗎? – UmNyobe

+1

我現在做過。哦,我的上帝!我沒有注意到這個錯誤。先生非常感謝您。我很感謝你和Frank Osterfeld的幫助。謝謝! :) – DaReDeViL