2010-10-25 79 views
1

我想用Java混合多個ULAW樣本。有沒有辦法做到這一點,而不轉換到PCM?我試圖做一個8000Hz的8位VoIP應用程序。我使用AUAW編碼測試AU文件(在goldwave中創建)。我目前的實現是:混合8bit 8000Hz PCM_ULAW採樣最簡單的方法是什麼?

[代碼]

AudioFormat f = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 8000, 16, 1, 2, 8000, false); 
    SourceDataLine sdl = AudioSystem.getSourceDataLine(f); 
    sdl.open(f); 
    sdl.start(); 

    File file1 = new File("C:\\Scream3.au"); 
    AudioInputStream ais1 = AudioSystem.getAudioInputStream(file1); 
    AudioInputStream aisTarget1 = AudioSystem.getAudioInputStream(f, ais1); 

    File file2 = new File("C:\\Blackout3.au"); 
    AudioInputStream ais2 = AudioSystem.getAudioInputStream(file2); 
    AudioInputStream aisTarget2 = AudioSystem.getAudioInputStream(f, ais2); 

    byte[] data = new byte[10000]; 
    int[] calc = new int[5000]; 
    AudioInputStream[] streams = {aisTarget1, aisTarget2}; 
    int count = streams.length + 1; 
    while (true) { 
     int r = -1; 
     for (int i = 0; i < streams.length; i++) { 
      r = streams[i].read(data, 0, data.length); 
      if (r == -1) break; 
      for (int j = 0; j < calc.length; j++) { 
       int tempVal = ((data[j * 2 + 1] << 8) | (data[j * 2] & 0xFF)); 
       calc[j] += tempVal; 
      } 
     } 
     for (int i = 0; i < calc.length; i++) { 
      calc[i] /= count; 
      data[i * 2 + 0] = (byte) (calc[i] & 0xFF); 
      data[i * 2 + 1] = (byte) (calc[i] >> 8); 
     } 
     if (r == -1) break; 
     sdl.write(data, 0, data.length); 
    } 

[/代碼]

如果其無法將ULAW樣品直接混合,我必須轉換爲PCM,如何從轉換PCM格式(AudioFormat.Encoding.PCM_SIGNED,8000Hz,16位,1通道,2字節幀大小,8000幀率,小端) 到ULAW(8位8000Hz)。

難道我這樣做: 1)寫WAVE頭字節流 2)的PCM數據寫入的字節流 3)獲取PCM AIS與AudioSystem.getAudioInputStream(字節流) 4)獲取ULAW目標AIS與AudioSystem.getAudioInputStream(ulawFormat,PCM AIS)

任何幫助表示讚賞。

編輯: 試圖從μ定律轉換成PCM(試圖用從http://en.wikipedia.org/wiki/Ulaw方程):

[CODE]

AudioFormat f = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 8000, 8, 1, 1, 8000, false); 
    SourceDataLine sdl = AudioSystem.getSourceDataLine(f); 
    sdl.open(f); 
    sdl.start(); 
    File file1 = new File("C:\\scream3.au"); 
    FileInputStream fis = new FileInputStream(file1); 
    // Skip header 
    fis.skip(24); 
    byte[] data = new byte[8196]; 

    while (true) { 
     int r = fis.read(data, 0, data.length); 
     if (r == -1) break; 
     for (int i = 0; i < r; i++) { 
      float y = ((float) data[i]/Byte.MAX_VALUE); 
      float sample = -1.0f * (float) (Math.signum(y) * (1.0f/255.0f) * (Math.pow(1 + 255, Math.abs(y)) - 1.0f)); 
      data[i] = (byte) (sample * Byte.MAX_VALUE); 
     } 
     sdl.write(data, 0, data.length); 
    } 
    sdl.drain(); 
    sdl.stop(); 
    sdl.close(); 
    fis.close(); 

[/ CODE]

回答

1

我將轉換從/到手動線性編碼,每次一個樣本,使用Wikipedia:μ-law algorithm的公式。

示例代碼(基於OP的代碼):

float sample1 = Math.signum(y1)/255.0*(Math.pow(256, Math.abs(y1))-1); 
float sample2 = Math.signum(y2)/255.0*(Math.pow(256, Math.abs(y2))-1); 
float combined = somethig * sample1 + (1-something) * sample2; 
float result = Math.signum(combined)*Math.log(1+255*Math.abs(combined))/Math.log(256); 
+0

感謝您的答覆!我試圖做到這一點,不幸的是,我不擅長數學。你能幫我嗎? – Xiphias3 2010-10-25 15:42:04

+0

這與轉換爲PCM並返回的方式不一樣嗎? – Gabe 2010-10-25 15:44:56

+0

@加貝:它是一樣的。我的意思是說你不需要編寫頭文件,使用字節流等等。 – 2010-10-25 16:00:39

相關問題