音频解码为PCM

/**
 * <pre>
 *      author : ych
 *      email  : 1147471053@qq.com
 *      time   : 2018/08/18
 *      desc   : 解码器 -》PCM
 *      version:
 * </pre>
 */

public class AudioDecoder2PCM {
    private static AudioDecoder2PCM INSTANCE=null;
   private MediaExtractor mExtractor;
    private int mSampleRate=0;//采样率
    private int channel=0;//通道数
    private LinkedList<byte[]> data = new LinkedList<>();
    private MediaCodec mDecoder;
    private boolean eosReceived;

    public static AudioDecoder2PCM getINSTANCE(){
        if (INSTANCE==null){
            synchronized (AudioDecoder2PCM.class){
                if (INSTANCE==null){
                    INSTANCE= new AudioDecoder2PCM();
                }
            }
        }
        return INSTANCE;
    }

    public void setData(byte[] bytes){
        data.add(bytes);
    }
    public byte[] getData(){
        return data.poll();
    }

    public void startDecoder(String path){
        try {
            eosReceived=false;
            //创建MediaExtractor对象用来解码
             mExtractor = new MediaExtractor();
            //添加需要解码的文件路径
            mExtractor.setDataSource(path);
            MediaFormat format = mExtractor.getTrackFormat(0);
            if (format==null){
                Log.e("tag","format is null");
                return;
            }
            //判断当前文件类型是否是音频
            String mime=format.getString(MediaFormat.KEY_MIME);
            if (mime.startsWith("audio/")){
                Log.e("tag",mime);
                //获取当前音频的采样率
                mExtractor.selectTrack(0);
                mSampleRate=format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
                //获取当前帧的通道数
                channel=format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
                //音频文件长度
                long duration = format.getLong(MediaFormat.KEY_DURATION);
            }
            //创建MedioCodec对象
            mDecoder = MediaCodec.createDecoderByType(mime);
            //配置Mediacodec
            mDecoder.configure(format,null,null,0);
            if (mDecoder==null){
                Log.e("tag","mDecoder is null");
                return;
            }
            //启动MedioCodec等待传入数据
            mDecoder.start();
            
            //启动线程
            new Thread(DecoderAndPlayRunnable).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    Runnable DecoderAndPlayRunnable = new Runnable() {
        @Override
        public void run() {
      DecoderAndPlay();      
        }


    };
    private void DecoderAndPlay() {
        //MeiaCodec在此ByteBuffer[]中获取输入的数据
        ByteBuffer[] inputBuffers = mDecoder.getInputBuffers();
        //MediaCodec将解码后的数据放在ButeBuffer[]中,我们将可以直接从这里面得到pcm数据
        ByteBuffer[] outputBuffers = mDecoder.getOutputBuffers();
        //用于描述解码得到的byte[]数据的相关信息
        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();


        while (!eosReceived){
            //获取可用的inputBuffer
            int inIndex=mDecoder.dequeueInputBuffer(-1);//一直等待
            if (inIndex>=0){
                ByteBuffer buffers=inputBuffers[inIndex];
                //从MediaExtractor中读取一帧待解码的数据
                int sampleSize=mExtractor.readSampleData(buffers,0);
            //小于0 代表全部读取完成
                if (sampleSize<0){
                    mDecoder.queueInputBuffer(inIndex,0,0,0,
                            MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                }else {
                    //插入一帧待解码的数据
                    mDecoder.queueInputBuffer(inIndex,0,sampleSize,
                            mExtractor.getSampleTime(),0);
                    //MediaExtractor移动到下一取样处
                    mExtractor.advance();
                }
                //从mediadecoder队列取出一帧解码后的数据 参数BufferInfo上面已介绍 10000同样为等待时间 同上-1代表一直等待,0代表不等待。此处单位为微秒
                //此处建议不要填-1 有些时候并没有数据输出,那么他就会一直卡在这 等待
                int outIndex = mDecoder.dequeueOutputBuffer(info, 0);
                switch (outIndex){
                    case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                        outputBuffers = mDecoder.getOutputBuffers();
                        break;
                    case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                        break;
                    case MediaCodec.INFO_TRY_AGAIN_LATER:
                        break;
                        default:
                            ByteBuffer outBuffer = outputBuffers[outIndex];
                            //BufferInfo内定义了此数据的大小
                            final byte[] chunk = new byte[info.size];
                            //将buffer中的数据取出,保存在字节数组中
                            outBuffer.get(chunk);
                            //清空
                            outBuffer.clear();
                            //将解码出来的pcm数据Io流保存
                            setData(chunk);
                            mDecoder.releaseOutputBuffer(outIndex,false);
                            break;
                }
            }
        }
        mDecoder.stop();
        mDecoder.release();
        mDecoder=null;

        mExtractor.release();
        mExtractor=null;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值