2012-07-18 32 views
1

我已經找到了一些代碼來計算麥克風音量(RMS):聲級RMS

public int calculateRMSLevel(byte[] audioData) { 
    // audioData might be buffered data read from a data line 
    long lSum = 0; 
    for (int i = 0; i < audioData.length; i++) { 
     lSum = lSum + audioData[i]; 
    } 

    double dAvg = lSum/audioData.length; 

    double sumMeanSquare = 0d; 
    for (int j = 0; j < audioData.length; j++) { 
     sumMeanSquare = sumMeanSquare + Math.pow(audioData[j] - dAvg, 2d); 
    } 

    double averageMeanSquare = sumMeanSquare/audioData.length; 
    return (int) (Math.pow(averageMeanSquare, 0.5d) + 0.5); 
} 

但它僅適用於以下音頻格式:

private AudioFormat getAudioFormat() { 
    float sampleRate = 8000.0F; 

    int sampleSizeInBits = 8; 

    int channels = 1; 

    boolean signed = true; 

    boolean bigEndian = true; 

    return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, 
      bigEndian); 
} 

如何擴充,以便它可以使用不同的位數?如果我將位數改爲16,它會返回大約50的值,當靜音在8位時返回1或2.此外,我想在圖表上繪製聲級,聲級值與時間相關如何?

+0

這是一個很老的問題,但我遇到了同樣的問題 - RMS對我來說總是在50左右。你是否設法解決這個問題? – locomotion 2016-03-18 01:44:34

回答

0

您始終可以將輸入縮放到相同的最小 - 最大範圍,以獲得不同格式的類似結果。

至於聲級w.r.t.時間,除了採樣間隔1/SampleRate(以Hz爲單位)秒之外,沒有任何關係。

2

採樣率並不重要,但位深度,字節順序和以不同方式採用的通道數量都很重要。

要明白爲什麼,您必須注意到,所討論的函數將一個字節數組作爲參數,並逐個處理該數組中的每個值。字節數據類型是一個8位值。如果你想要16位值的東西,你需要使用一個不同的數據類型(簡稱)或者從字節轉換。

一旦你這樣做,你仍然會得到16位和8位不同的值,因爲範圍是不同的:8位從-128到+127,16位從-32768到+32767,但它們是既測量相同的東西,這意味着它們將相同的實詞值縮放到不同的表示值。

至於聲音水平及其與時間的關係....以及它取決於你的採樣率和進入這個函數的數組大小。例如,如果您的採樣率是8kHz,並且每個緩衝區有2048個採樣,那麼您的函數將被稱爲8000/2048或每秒大約3.9次,這意味着您的結果以這個速率(每256毫秒)進入。

+0

SR = 8000 mhz buffer size = 2048 – Radek 2012-07-19 08:03:59

+0

我懷疑你的採樣率是8000 mhz!它肯定是8000赫茲或8千赫茲。我會編輯我的答案。 – 2012-07-19 15:14:50

+0

對不起,你是對的。 – Radek 2012-07-19 15:45:02