2012-05-09 79 views
5

我在轉換WAV文件的音頻格式時遇到了問題。音頻格式轉換

我從我的麥克風記錄的聲音和聲音被記錄在下面的格式: PCM_SIGNED 44100.0赫茲,16位,單聲道,2個字節/幀

我想把上述格式轉換爲, ULAW 8000.0赫茲,8位,單聲道,1個字節/幀

我使用下面的代碼,

InputStream is = request.getInputStream(); 
      AudioInputStream ais = AudioSystem.getAudioInputStream(is); 
      AudioFormat oldFormat = ais.getFormat(); 
      AudioFormat newFormat = new AudioFormat(AudioFormat.Encoding.ULAW, 8000, 8, 1, 1, 8000, false) ; 
AudioInputStream lowResAIS = AudioSystem.getAudioInputStream(newFormat, ais); //Getting the below Exception on this line 

我正在以下錯誤,

java.lang.IllegalArgumentException異常:不支持的轉換:ULAW 8000.0赫茲,8位,單聲道,1個字節/幀,從PCM_SIGNED 44100.0赫茲,16位,單聲道,2個字節/幀,小端

可有人請幫我解決這個問題!!!

謝謝!

回答

3

你看過documentation嗎?

拋出: IllegalArgumentException - 如果不支持轉換#see #getTargetEncodings

不是每個系統將安裝轉換到你問的具體格式編解碼器足夠(AudioFormat的)對於。你假設你的確如此,但它拋出了異常,因爲它無法轉換爲該格式。

您可以使用getTargetEncodings以編程方式檢查給定格式的適用性,而不依賴於例外情況,如果您希望的輸出格式不可用,則可以採取適當的措施(例如回退到另一個格式,呈現給用戶反饋說這是不可能的,等等)。

+0

嘿Andrzej!謝謝回覆。我已經部分瀏覽了文檔。我以如下方式使用了getTargetEncodings()方法:'''Encoding [] encArr = AudioSystem.getTargetEncodings(oldFormat); \t \t \t \t對(INT I = 0;我」 + encArr [I]); \t \t \t \t}'code',我得到了以下的輸出:0 - > PCM_SIGNED 1 - > PCM_UNSIGNED 2 - > ALAW 3 - > ULAW,你有什麼要說的?謝謝!! –

+0

由於我得到上述輸出,我猜測,我的系統有編解碼器轉換爲ULAW格式。除此之外,其他原因是什麼?任何想法? –

+1

它可能不支持轉換的其他方面,例如採樣率或位數。我並不完全瞭解這一點,但事實證明你正在「降低採樣率」爲我提供了一面旗幟。 (從44100到8000)。這通常很棘手,因爲數據信息的頻率在4000和22050 Hz之間將會混淆,除非您將它們過濾掉數據。所以我的猜測是,這不是一個標準的支持轉換。但是我敢打賭,如果你輸出的話,你可以轉換成ULAW 44100Hz。 (我最好猜) –

0

這個班可以幫助你。我發現它here

package uk.co.mmscomputing.sound; 

import java.io.*; 

public class CompressInputStream extends FilterInputStream{ 

    /* 
    Convert mono PCM byte stream into A-Law u-Law byte stream 

    static AudioFormat alawformat= new AudioFormat(AudioFormat.Encoding.ALAW,8000,8,1,1,8000,false); 
    static AudioFormat ulawformat= new AudioFormat(AudioFormat.Encoding.ULAW,8000,8,1,1,8000,false); 

    PCM 8000.0 Hz, 16 bit, mono, SIGNED, little-endian 
    static AudioFormat pcmformat = new AudioFormat(8000,16,1,true,false); 

    */ 

    static private Compressor alawcompressor=new ALawCompressor(); 
    static private Compressor ulawcompressor=new uLawCompressor(); 

    private Compressor compressor=null; 

    public CompressInputStream(InputStream in, boolean useALaw)throws IOException{ 
    super(in); 
    compressor=(useALaw)?alawcompressor:ulawcompressor; 
    } 

    public int read()throws IOException{ 
    throw new IOException(getClass().getName()+".read() :\n\tDo not support simple read()."); 
    } 

    public int read(byte[] b)throws IOException{ 
    return read(b,0,b.length); 
    } 

    public int read(byte[] b, int off, int len)throws IOException{ 
    int  i,sample; 
    byte[] inb; 

    inb=new byte[len<<1];   // get 16bit PCM data 
    len=in.read(inb); 
    if(len==-1){return -1;}; 

    i=0; 
    while(i<len){ 
     sample = (inb[i++]&0x00FF); 
     sample |= (inb[i++]<<8); 
     b[off++]=(byte)compressor.compress((short)sample); 
    } 
    return len>>1; 
    } 
} 

abstract class Compressor{ 
    protected abstract int compress(short sample);  
} 

/* 
    Mathematical Tools in Signal Processing with C++ and Java Simulations 
     by Willi-Hans Steeb 
      International School for Scientific Computing 
*/ 

class ALawCompressor extends Compressor{ 

    static final int cClip = 32635; 

    static final int[] ALawCompressTable ={ 
    1,1,2,2,3,3,3,3, 
    4,4,4,4,4,4,4,4, 
    5,5,5,5,5,5,5,5, 
    5,5,5,5,5,5,5,5, 
    6,6,6,6,6,6,6,6, 
    6,6,6,6,6,6,6,6, 
    6,6,6,6,6,6,6,6, 
    6,6,6,6,6,6,6,6, 
    7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7 
    }; 

    protected int compress(short sample){ 
    int sign; 
    int exponent; 
    int mantissa; 
    int compressedByte; 

    sign = ((~sample) >> 8) & 0x80; 
    if(sign==0){ sample *= -1;} 
    if(sample > cClip){ sample = cClip; } 
    if(sample >= 256){ 
     exponent = ALawCompressTable[(sample >> 8) & 0x007F]; 
     mantissa = (sample >> (exponent + 3)) & 0x0F; 
     compressedByte = 0x007F & ((exponent << 4) | mantissa); 
    }else{ 
     compressedByte = 0x007F & (sample >> 4); 
    } 
    compressedByte ^= (sign^0x55); 
    return compressedByte; 
    } 
} 

class uLawCompressor extends Compressor{ 

    static final int cClip = 32635; 
    static final int cBias = 0x84; 

    int[] uLawCompressTable ={ 
    0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, 
    4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 
    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 
    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 
    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 
    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 
    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 
    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 
    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 
    }; 

    protected int compress(short sample){ 
    int sign; 
    int exponent; 
    int mantissa; 
    int compressedByte; 

    sign = (sample >> 8) & 0x80; 
    if(sign!=0){ sample *= -1;} 
    if(sample > cClip){ sample = cClip; } 
    sample += cBias; 

    exponent = uLawCompressTable[(sample >> 7) & 0x00FF]; 
    mantissa = (sample >> (exponent + 3)) & 0x0F; 
    compressedByte = ~(sign | (exponent << 4) | mantissa); 
    return compressedByte&0x000000FF; 
    } 
} 
+0

那是幹什麼的?它會幫助我以下錯誤? '格式爲PCM_SIGNED 44100.0 Hz,16位,單聲道,2字節/幀,不支持little-endian格式的行 – trusktr

+0

我還沒有使用它,但它聲稱將單聲道PCM字節流轉換成A-Law u-Law字節流「。這看起來像你正在做的事情。看起來,這種轉換不是直接在Java中支持的,你必須做你自己的壓縮(就像這個類一樣)。 – 11101101b

+1

結果我的錯誤是因爲我無法使用已經被使用的數據行(所以錯誤是誤導性的)。使用Beads聲音庫解決了我所有的問題(http://beadsproject.net)。 – trusktr