2013-08-05 56 views
2

我正在嘗試將音頻輸入的低音增強爲12 dB。下面是代碼Java中的低音增強

public class BassBoost { 
    double xn1, xn2, yn1, yn2; 
    double omega, sn, cs, a, shape, beta, b0, b1, b2, a0, a1, a2; 

    public BassBoost(int frequency, int dB_boost, int sampleRate) { 
     xn1 = 0; 
     xn2 = 0; 
     yn1 = 0; 
     yn2 = 0; 

     omega = 2 * Utils.pi * frequency/sampleRate; 
     sn = Math.sin(omega); 
     cs = Math.cos(omega); 
     a = Math.exp(Math.log(10.0) * dB_boost/40); 
     shape = 1.0; 
     beta = Math.sqrt((a * a + 1)/shape - (Math.pow((a - 1), 2))); 
     /* Coefficients */ 
     b0 = a * ((a + 1) - (a - 1) * cs + beta * sn); 
     b1 = 2 * a * ((a - 1) - (a + 1) * cs); 
     b2 = a * ((a + 1) - (a - 1) * cs - beta * sn); 
     a0 = ((a + 1) + (a - 1) * cs + beta * sn); 
     a1 = -2 * ((a - 1) + (a + 1) * cs); 
     a2 = (a + 1) + (a - 1) * cs - beta * sn; 
    } 

    public void process(double[] buffer, int length) { 
     double out, in = 0; 

     for (int i = 0; i < length; i++) { 
      in = buffer[i]; 
      out = (b0 * in + b1 * xn1 + b2 * xn2 - a1 * yn1 - a2 * yn2)/a0; 
      xn2 = xn1; 
      xn1 = in; 
      yn2 = yn1; 
      yn1 = out; 

      if (out < -1.0) 
       out = -1.0; 
      else if (out > 1.0) 
       out = 1.0; // Prevents clipping 

      buffer[i] = out; 
     } 
    } 
} 

,這裏是它調用過程

音頻被記錄並存儲在緩衝區短的僞代碼。 將緩衝區分成小陣列並複製到雙陣列以進行濾波處理。如果我不分,我正在嘗試在Android手機上使用OutofMemory。 應用濾波(LPF,HPF) 在寫入字節數組之前,使用以下代碼對輸出雙緩衝區進行放大。

void doOutput(int outlen, boolean maxGain) { 
    int qi; 
    int i, i2; 

    while (true) { 
     int max = 0; 
     i = outbp; 
     for (i2 = 0; i2 < outlen; i2 += 4) { 
      qi = (int) (leftBuffer[i] * outputGain); 
      if (qi > max) 
       max = qi; 
      if (qi < -max) 
       max = -qi; 
      ob[i2 + 1] = (byte) (qi >> 8); 
      ob[i2] = (byte) qi; 
      i = (i + 1) & fbufmask; 
     } 
     i = outbp; 
     for (i2 = 2; i2 < outlen; i2 += 4) { 
      qi = (int) (rightBuffer[i] * outputGain); 
      if (qi > max) 
       max = qi; 
      if (qi < -max) 
       max = -qi; 
      ob[i2 + 1] = (byte) (qi >> 8); 
      ob[i2] = (byte) qi; 
      i = (i + 1) & fbufmask; 
     } 
     // if we're getting overflow, adjust the gain 
     if (max > 32767) { 
      outputGain *= 30000./max; 
      if (outputGain < 1e-8 || Double.isInfinite(outputGain)) { 
       unstable = true; 
       break; 
      } 
      continue; 
     } else if (maxGain && max < 24000) { 
      if (max == 0) { 
       if (outputGain == 1) 
        break; 
       outputGain = 1; 
      } else 
       outputGain *= 30000./max; 
      continue; 
     } 
     break; 
    } 
    if (unstable) 
     return; 
    outbp = i; 

out.write(ob, 0, outlen); 
} 

此代碼是爲android,因此它必須是有效的內存。我嘗試了使用Arraylist,但那也是內存不足。

問題是 要通過緩衝區應用一致的outputGain,我正在應用兩次過濾並寫入byteOutputStream一次。我嘗試使用Arraylist在應用單個outputGain之前存儲輸出緩衝區,但是該內存需要存儲整個Double緩衝區(1分鐘記錄)。同樣對於BassBoost,我想將它應用於整個輸出。有沒有內存有效的方法來做到這一點。使用ArrayList是沒有問題的。爲了獲得一致的outputGain,我必須通過整個輸出緩衝區並將其應用於單個outputGain。

想要使上面的示例代碼有效,以便我不必通過緩衝區兩次。如果我將其應用於大塊,也會降低連續聲音。

由於

+2

所以,你認爲使用ArrayList是個問題,在你發佈的大量代碼中,我沒有看到任何相關的代碼。你能編輯你的問題來包含代碼段嗎? – marko

+0

這些double []有多大?爲什麼你不使用float []?在我所有的音頻編碼中,我總是使用float [](在java中)。 – Nick

回答

0

short[]爲44.1kHz的立體聲聲音一分鐘取44100 * 2 * 2 * 60 = 10584000,或者存儲器大致10MB。

這就是只是一個簡單的短緩衝區。

由於您使用ArrayList<Double>,根據您的評論,它會變得更大。 Java爲每個Object增加了一點開銷,並且這個數組列表將會有大約5個百萬個對象。我很確定虛擬機的開銷數量是不一樣的。

我相信,但是,開銷是at least 8 bytesObject。用你的500萬Shorts,即(8 + 8) * 5M = 80MB最低

看看這是怎麼回事?

我不認爲你想創建500萬個對象。我給的數字只是樣品本身。如果你在處理階段使用額外的內存,情況會更糟糕。這就是爲什麼基本上每個音頻應用程序都以塊處理的原因。這裏有大量的數據,即使是相對「短」的片段。

+0

我將它存儲在double的ArrayList中。因爲處理的緩衝區是雙倍的。 –

+0

哦。那麼一個double需要8個字節,而不是2個短。讓我在一些數學上編輯,讓你的數字更高。不過,道德依然如此。它可能太大而不適合你的堆。 – Geobits

+0

目前,我正在處理大塊,所以如何有效地做到這一點,無需存儲和處理兩次。 –