2012-04-30 66 views
2

任何人都可以看到一個從byte[]聲音中去除白噪聲的算法嗎?我工作的Android個人音頻錄製應用程序,我使用android API進行錄製。以下是用於將記錄寫入文件的方法(採用wav格式)。java - 從字節數組wav文件中移除噪聲

private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener() 
{ 
    public void onPeriodicNotification(AudioRecord recorder) 
    { 
     aRecorder.read(buffer, 0, buffer.length); 
     try 
     { 
      fWriter.write(buffer); // Write buffer to file 
      payloadSize += buffer.length; 
      if (bSamples == 16) 
      { 
       for (int i=0; i<buffer.length/2; i++) 
       { // 16bit sample size 
        short curSample = getShort(buffer[i*2], buffer[i*2+1]); 
        if (curSample > cAmplitude) 
        { // Check amplitude 
         cAmplitude = curSample; 
        } 
       } 
      } 
      else 
      { // 8bit sample size 
       for (int i=0; i<buffer.length; i++) 
       { 
        if (buffer[i] > cAmplitude) 
        { // Check amplitude 
         cAmplitude = buffer[i]; 
        } 
       } 
      } 
     } 
     catch (IOException e) 
     { 
      Log.e(AudioRecorder2.class.getName(), "Error occured in updateListener, recording is aborted"); 
     } 
    } 

    public void onMarkerReached(AudioRecord recorder) 
    {} 
}; 

我想對緩衝區應用一些轉換來消除播放錄製過程中可能聽到的白噪聲。 如果有人知道一些低通濾波器的算法/鏈接(或其他可能有用的東西),請幫忙。

謝謝。

+4

一般情況下,你不能刪除白噪聲,除非你瞭解你的音頻信號。例如,如果您知道它只佔用某個頻段,那麼您可以使用低通濾波器,這將消除高頻噪聲。雖然沒有一般的解決方案。 –

+0

我也收到相同的噪音。你找到解決方案嗎? – Manoj

+0

不,我離開了這個項目。如果你發現它,請在這裏回覆,以便我接受你的答案。 –

回答

0

實現低通最簡單的方法是平均多個採樣。所以如果你有N個樣本,你可以做這樣的事情:

// your sample data array 
int[] samples 
//number of samples you want to average 
int AVERAGE_SAMPLE_COUNT = 3; 

for(int i=0; i<samples.length-AVERAGE_SAMPLE_COUNT; i++){ 
    //variable for storing the values of multiple samples 
    int avgSample = 0; 
    for(int a=0; a<AVERAGE_SAMPLE_COUNT; a++){ 
     //add up the current and the next n samples 
     avgSample += samples[i+a] 
    } 
    //devide by the number of samples to average them 
    avgSample /= AVERAGE_SAMPLE_COUNT; 
    //replace first sample with the averaged value 
    samples[i] = avgSample 
} 

正如你看到的,唯一的缺陷可能是,該輸出會通過AVERAGE_SAMPLE_COUNT短。通過更改AVERAGE_SAMPLE_COUNT,您可以輕鬆嘗試不同強度的算法。 此外,它正在就地工作,這意味着它會更改您的初始輸入數據。

+1

平均值給出了一個非常差的低通濾波器 - 如果丟棄2/3的帶寬,音頻質量也會受到嚴重影響。 –

+0

謝謝,我會嘗試實施此過濾器並查看結果。 –

+0

事實上,輸出的質量比原來還要糟糕(儘管原始聲音有一點「噪音」,所以目前我會保持原樣 - 可能將來我會開始深入研究聲音理論,所以我將能夠像大膽地執行噪音去除。Dreams :)。)無論如何你的答案。 –

1

,如果你知道你可以平均樣本: 採樣頻率(8,16,32,64,128)和 位深度(8,16,32)和 通道記錄(單聲道,立體聲)。

.wav音頻以位深度的大小寫入交替通道或隔行排列在數組中。 (我認爲它與左通道開始)

16kHz的16位是一個短[]與每個音頻的第二16000個條目

的64kHz的32位是一個INT []與64000「」

你可以平均該16位通道從立體聲要單(簡稱[甚至] +短[奇])/ 2

你可以平均16位頻率128kHz的至16kHz的(8至11)的簡稱[ 0,2,4,6,8,10,12,14]/8

平均低於16kHZ頻率可能聽起來更差

根據音頻是如何量化的(模擬到數字的線性或對數的a-law/u-law/linear),您可能需要嘗試不同的方法。

+0

謝謝,我會嘗試立體聲單聲道第一(如果我沒有錯的.wav幀(16位深度)由2個採樣(4字節) - 1個樣本爲右聲道,1爲左),所以平均會結果作爲單聲道輸出。 –

0

另一種方法是在你的預處理階段以下,

recorder.read(data, 0, data.length); 
if(isAudible(data)) { 
    // TODO further processing can go here 
} 

public static boolean isAudible(short[] data) { 
    double rms = getRootMeanSquared(data); 
    return (rms > 198 && 5600 > rms); 
} 

public static double getRootMeanSquared(short[] data) { 
    double ms = 0; 
    for (int i = 0; i < data.length; i++) { 
     ms += data[i] * data[i]; 
    } 
    ms /= data.length; 
    return Math.sqrt(ms); 
}