【问题标题】:Conversion of Audio Format音频格式转换
【发布时间】:2012-05-09 11:30:00
【问题描述】:

我在转换 WAV 文件的音频格式时遇到问题。

我正在从我的麦克风录制声音,声音以以下格式录制: PCM_SIGNED 44100.0 Hz,16 位,单声道,2 字节/帧

我想将上述格式转换为, ULAW 8000.0 Hz,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 Hz,8 位,单声道,1 字节/帧,从 PCM_SIGNED 44100.0 Hz,16 位,单声道,2 字节/帧,little-endian

谁能帮我解决这个问题!!!

非常感谢!!!

【问题讨论】:

    标签: java audio javasound


    【解决方案1】:

    你看过documentation吗?

    投掷: IllegalArgumentException - 如果不支持转换#see #getTargetEncodings(AudioFormat)

    并非每个系统都会安装足够的编解码器来转换为您要求的特定格式。你假设你的可以,但它抛出了异常,因为它不能转换为那种格式。

    您可以使用getTargetEncodings 以编程方式检查给定格式的适用性,而不依赖于异常,然后可以在您所需的输出格式不可用时采取适当的措施(例如,退回到另一种格式,呈现用户反馈这是不可能的,等等)。

    【讨论】:

    • 嗨安杰!谢谢回复。我已经部分浏览了文档。我以以下方式使用了getTargetEncodings()方法codeEncoding[] encArr = AudioSystem.getTargetEncodings(oldFormat); for(int i=0;i"+encArr[i]); } code 我得到以下输出:0-->PCM_SIGNED 1-->PCM_UNSIGNED 2-->ALAW 3-->ULAW,你对此有什么要说的?谢谢!!
    • 因为我得到了上述输出,我猜我的系统有编解码器可以转换为 ULAW 格式。异常的其他原因可能是什么?有什么想法吗?
    • 它可能不支持转换的其他方面,例如采样率或位数。我并不完全同意这一点,但是您正在“下采样”这一事实为我竖起了大旗。 (从 44100 到 8000)。这通常很棘手,因为频率在 4000 到 22050 Hz 之间的数据信息会混叠,除非您将它们从数据中过滤掉。所以我的猜测是这不是标准支持的转换。但我敢打赌,根据你的输出,你可以转换为 44100 Hz 的 ULAW。 (我的最佳猜测。)
    【解决方案2】:

    这门课可能会对你有所帮助。我找到了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;
      }
    }
    

    【讨论】:

    • 这是做什么的?它会帮助我解决以下错误吗? line with format PCM_SIGNED 44100.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian not supported
    • 我没用过,但它声称将“单PCM字节流转换为A-Law u-Law字节流”。这看起来像你正在尝试做的事情。看来Java不直接支持这种转换,你必须自己做压缩(就像这个类一样)。
    • 原来我的错误是因为我无法使用已经在使用的数据线(因此错误具有误导性)。使用 Beads 声音库解决了我所有的问题 (beadsproject.net)。
    • 这可能没有回答 OP,但这对我有用。
    猜你喜欢
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    • 1970-01-01
    相关资源
    最近更新 更多