2011-11-03 113 views
6

我試圖將原始pcm數據編碼爲uLaw以節省傳輸語音數據所需的帶寬。Android PCM到Ulaw編碼wav文件

我碰到過一個叫做的類UlawEncoderInputStream on This page但是沒有文檔! :(

構造函數的輸入流和一個最大的PCM值(無論是)。

/** 
    * Create an InputStream which takes 16 bit pcm data and produces ulaw data. 
    * @param in InputStream containing 16 bit pcm data. 
    * @param max pcm value corresponding to maximum ulaw value. 
    */ 
    public UlawEncoderInputStream(InputStream in, int max) { 

通過代碼尋找後,我懷疑我應該使用所提供的計算此「最大」值函數:maxAbsPcm。問題是,我真的不明白我的意思傳入它!我記錄我的原始PCM到SD卡上的文件,所以我沒有一個連續的內存常駐數組傳遞到此。

/** 
    * Compute the maximum of the absolute value of the pcm samples. 
    * The return value can be used to set ulaw encoder scaling. 
    * @param pcmBuf array containing 16 bit pcm data. 
    * @param offset offset of start of 16 bit pcm data. 
    * @param length number of pcm samples (not number of input bytes) 
    * @return maximum abs of pcm data values 
    */ 
    public static int maxAbsPcm(byte[] pcmBuf, int offset, int length) { 

我使用此代碼的另一個問題是我不確定爲uLaw數據的標題寫出哪些值。我如何確定使用uLaw進行編碼後,有多少字節數據?

我聽過我在VLC媒體播放器中創建的(可能)uLaw編碼文件之一(我有唯一一個會嘗試讀取文件的播放器),它的聲音令人討厭,破碎和點擊,但仍然可以發出聲音。

我正在使用類似於我發現名爲WaveHeader的類的代碼來編寫我的wave標題,該類可以找到Here

如果任何人有關於此事的任何想法,我將不勝感激聽到他們的聲音!:)

非常感謝 德克斯特

+0

如果您正在創建.wav文件。將波形頭文件存儲在開頭,並在錄製結束時將其更改回去。通常情況下,直到最後纔會知道大小(記錄數)。無論如何,你的max應該是0x7f。 –

回答

4

構造函數中的max是在PCM數據的最大振幅。它用於在生成輸出之前縮放輸入。如果輸入非常大聲,則需要更高的值,如果它很安靜,則需要較低的值。如果通過0,編碼器默認使用8192,這可能足夠好。

其他方法中的length是您想要從中找到最大振幅的16位採樣的數量。該類假定輸入PCM數據始終使用16位採樣編碼,這意味着每個採樣跨越兩個字節:如果您的輸入是2000字節長,則您有1000個採樣。

該類中的編碼器爲每個16位PCM採樣生成一個8位μ-Law採樣,因此字節大小減半。

+0

非常感謝Joni –

0

這與你想要做的事情相反,但我認爲這可能對某人有幫助。下面是一個實例方法,它將使用內置的Java方法將8位uLaw編碼的二進制文件轉換爲16位的WAV文件。

public static void convertULawFileToWav(String filename) { 
    File file = new File(filename); 
    if (!file.exists()) 
     return; 
    try { 
     long fileSize = file.length(); 
     int frameSize = 160; 
     long numFrames = fileSize/frameSize; 
     AudioFormat audioFormat = new AudioFormat(Encoding.ULAW, 8000, 8, 1, frameSize, 50, true); 
     AudioInputStream audioInputStream = new AudioInputStream(new FileInputStream(file), audioFormat, numFrames); 
     AudioSystem.write(audioInputStream, Type.WAVE, new File("C:\\file.wav")); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
}