音频编码成.aac音频文件

使用MediaCodec将振动数据通过音频编码成.aac音频文件
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Environment;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * Created by WJY.
 * Date: 2022-01-11
 * Time: 14:32
 * Description: 音频编码测试  .aac
 */
public class AudioEncoderTest {

    private MediaFormat encoderFormat;
    private MediaCodec encoder;
    private FileOutputStream fos;
    private MediaCodec.BufferInfo info;
    private int perpcmsize;
    private byte[] outByteBuffer;
    private int mSamplingRate;//采样率

    public void initMediaCodec(int samperate) {
        try {
            mSamplingRate = samperate;
            File outfile = new File(Environment.getExternalStorageDirectory()+"/VbAudio", "/audio_encoded.aac");
            touch(outfile);
            encoderFormat = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC,samperate,1);
            encoderFormat.setInteger(MediaFormat.KEY_BIT_RATE,96000);
            encoderFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
            encoderFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1000 * 1024);
            encoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AAC);
            info = new MediaCodec.BufferInfo();
            if (encoder == null) {
                return;
            }
            encoder.configure(encoderFormat,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);
            fos = new FileOutputStream(outfile);
            encoder.start();
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void touch(File f) {
        try {
            if (!f.exists())
                f.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //编码
    public void encodecPcmToAAC(int size, byte[] buffer) {
        if (buffer != null && encoder !=null) {
            int inputBufferIndex = encoder.dequeueInputBuffer(0);
            if (inputBufferIndex >= 0) {
                ByteBuffer byteBuffer = encoder.getInputBuffers()[inputBufferIndex];
                LoggUtils.e("byteBuffer","byteBuffer:" +byteBuffer.capacity()+",buffer:" +buffer.length);
                byteBuffer.clear();
                byteBuffer.put(buffer);
                encoder.queueInputBuffer(inputBufferIndex,0,size,0,0);
            }
            int index = encoder.dequeueOutputBuffer(info,100000);
            while (index < 0){
                index = encoder.dequeueOutputBuffer(info,100000);
            }
            while (index >= 0) {
                try {
                    perpcmsize = info.size + 7;
                    outByteBuffer = new byte[perpcmsize];

                    ByteBuffer byteBuffer = encoder.getOutputBuffers()[index];
                    byteBuffer.position(info.offset);
                    byteBuffer.limit(info.offset + info.size);

                    addADTSHeader(outByteBuffer,perpcmsize);

                    byteBuffer.get(outByteBuffer,7,info.size);
                    byteBuffer.position(info.offset);

                    fos.write(outByteBuffer,0,perpcmsize);

                    encoder.releaseOutputBuffer(index,false);
                    index = encoder.dequeueOutputBuffer(info,100000);
                    outByteBuffer = null;
                    LoggUtils.e("Player","编码中。。。");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //添加ADTS头信息
    private void addADTSHeader(byte[] packet, int packetLen) {
        int profile = 2; // AAC LC
        // 39=MediaCodecInfo.CodecProfileLevel.AACObjectELD;
//        int chanCfg = 2; // CPE  (Channel Pair Element 双通道元素)
        int chanCfg = 1; // 1 通道: 前中心
//        int freqIdx = 4; // 44.1KHz
        int freqIdx = 11; // 8000 赫兹
//        int freqIdx = 10; // 11025 赫兹
//        int freqIdx = 9; // 12000 赫兹
//        int freqIdx = 8; // 16000 赫兹
//        int freqIdx = 7; // 22050 赫兹
        if (mSamplingRate == 8000){
            freqIdx = 11; // 8000 赫兹
        }else if (mSamplingRate == 12000){
            freqIdx = 9; // 12000 赫兹
        }else if (mSamplingRate == 16000){
            freqIdx = 8; // 16000 赫兹
        }else if (mSamplingRate == 44100){
            freqIdx = 4; // 44.1KHz
        }else if (mSamplingRate == 11025){
            freqIdx = 10; // 11025 Hz
        }

        // fill in ADTS data
        packet[0] = (byte) 0xFF;
        packet[1] = (byte) 0xF9;
        packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));//采样率下标(注意是下标,而不是采样率)
        packet[3] = (byte) (((chanCfg & 3) << 6) + (packetLen >> 11));//声道配置(注意是声道配置,而不是声道数)
        packet[4] = (byte) ((packetLen & 0x7FF) >> 3);//数据长度的组合(注意packetLen是原始数据长度加上ADTS头的长度)
        packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);
        packet[6] = (byte) 0xFC;
    }

    //释放Mediacodec
    public void releaseMediaCodec() {
        try {
            if (fos != null) {
                fos.close();
            }
            if (encoder != null) {
                encoder.stop();
                encoder.release();
            }
            encoderFormat = null;
            info = null;
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

使用

private AudioEncoderTest audioEncoder;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    audioEncoder = new AudioEncoderTest();
    audioEncoder.initMediaCodec(采样率);

    audioEncoder.encodecPcmToAAC(数据长度,数据byte[]);
}


@Override
public void onDestory() {
if (null != audioEncoder) {
     audioEncoder.releaseMediaCodec();
}
super.onDestory();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时代新人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值