2013-07-13 60 views
1

我正在嘗試爲Android手機制作一個簡單的基音檢測應用程序。我已經拿到電話來顯示我計算出的自相關值的圖表,這些值存儲在一個雙精度數組中。現在我需要弄清楚如何檢測數組中的重複模式。這是自相關圖與我的截圖哼着穩定間距:檢測一維Java陣列中局部最大值的一般模式

screenshot of my autocorrelation graph when humming a steady pitch

我試圖實現在這個幻燈片甲板給出一維數組的遞歸峯值尋找算法:http://courses.csail.mit.edu/6.006/spring11/lectures/lec02.pdf但我得到了內存不足的錯誤在Android上。

接下來我嘗試實現類似於這種算法的算法,以找到二階導數:https://stackoverflow.com/a/3869172,但來自手機的自相關值非常緊張,以至於發現太多極小值和極大值。

我需要弄清楚如何做的是對自相關數據應用某種過濾器來平滑它,但是我吮吸數學並且不知道該怎麼做。我嘗試將自相關值舍入到小數點後幾位,但我沒有得到我期待的結果。

基本上我需要幫助弄清楚如何找到重複模式的總體最大值(實際上只是第一個可能會好的)。在上面的屏幕截圖中,圖案是一個高峯,接着是兩個較短的峯值。我需要知道第二個高峯發生的時間,以便我可以計算出音高。

+0

平均濾波器或濾波器濾波器可以平滑你的信號。定義適合您需要的窗口長度。 – dervish

回答

0

回答我自己問題,這是我最終做的。 (對不起,花了我很長時間纔回到這個問題來發布答案。)

double frequency = findFrequency(lowPassFilter(signal)); 

private double findFrequency(double[] signal) { 
    int[] signs = new int[signal.length]; 
    for (int i = 0; i < signal.length - 1; i++) { 
     double diff = signal[i+1] - signal[i]; 
     if (diff < 0) { 
      signs[i] = -1; 
     } else if (diff == 0) { 
      signs[i] = 0; 
     } else { 
      signs[i] = 1; 
     } 
    } 
    int[] secondDerivatives = new int[signs.length]; 
    for (int i = 0; i < signs.length - 1; i++) { 
     secondDerivatives[i] = signs[i+1] - signs[i]; 
    } 
    double biggestSoFar = 0.0; 
    int indexOfBiggestSoFar = 0; 
    for (int i = 0; i < secondDerivatives.length; i++) { 
     if (secondDerivatives[i] == -2 && signal[i] > biggestSoFar) { 
      biggestSoFar = signal[i]; 
      indexOfBiggestSoFar = i; 
     } 
    } 
    return 1/(double)indexOfBiggestSoFar * AudioListener.SAMPLE_RATE; 
} 

private double[] lowPassFilter(double[] signal) { 
    double alpha = 0.15; 
    for (int i = 1; i < signal.length; i++) { 
     signal[i] = signal[i] + alpha * (signal[i] - signal[i-1]); 
    } 
    return signal; 
} 
0

您正在嘗試估計樣本數據中幅度峯值的頻率。你可以做到這一點,而不必手動找到估計的峯值,然後找出頻率。相反,您可以使用快速傅立葉變換,它將幅度隨時間變化的圖形轉換爲頻率隨時間變化的圖形。有概念的,一般這裏http://en.wikipedia.org/wiki/Fast_Fourier_transform

一個很好的說明...並有實現的變換,包括 阿帕奇百科全書數學幾個Java庫 - http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/transform/FastFourierTransformer.html 和 JTransform - https://sites.google.com/site/piotrwendykier/software/jtransforms