2012-05-09 76 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