android 实时PCM数据编码成AAC【转】
来源:互联网 发布:淘宝无名体育发货慢 编辑:程序博客网 时间:2024/06/05 10:19
来自:http://blog.csdn.net/qq_24551315/article/details/51135681
获取PCM流
[java] view plain copy
- package com.ff.aac.audio;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import com.ff.aac.jni.AacEncoder;
- import android.media.AudioRecord;
- import android.media.MediaRecorder.AudioSource;
- import android.os.SystemClock;
- import android.util.Log;
- /**
- * 音频发送封装类
- */
- public class DAudioRecord implements Runnable{
- private final String TAG="DAudioRecord";
- private int mFrequency;//采样率
- private int mChannel;//声道
- private int mSampBit;//采样精度
- private AacEncoder encoder;
- private AudioRecord mAudioRecord;
- private boolean recordTag;
- private int minBufferSize;
- public DAudioRecord(int frequency,int channel,int sampbit){
- this.mFrequency = frequency;
- this.mChannel = channel;
- this.mSampBit = sampbit;
- }
- public void init(){
- if(mAudioRecord != null){
- release();
- }
- try {
- minBufferSize = AudioRecord.getMinBufferSize(mFrequency, mChannel, mSampBit);
- mAudioRecord = new AudioRecord(AudioSource.MIC, mFrequency, mChannel, mSampBit, minBufferSize);
- Log.i(TAG, "minBufferSize = " + minBufferSize);
- } catch (Exception e) {
- Log.i(TAG, "创建录音器出错");
- }
- }
- public void startRecord(AacEncoder encoder){
- this.recordTag = true;
- this.encoder = encoder;
- new Thread(this).start();
- }
- public void stopRecord(){
- this.recordTag = false;
- }
- public void release(){
- if(mAudioRecord != null){
- try {
- mAudioRecord.stop();
- mAudioRecord.release();
- encoder.stopSendRecodData();
- } catch (Exception e) {
- Log.i(TAG, "关闭录音出错");
- }finally{
- mAudioRecord = null;
- encoder = null;
- System.gc();
- }
- }
- }
- @Override
- public void run() {
- try {
- boolean b = true;
- while (b && recordTag) {
- if(mAudioRecord.getState() == AudioRecord.STATE_INITIALIZED){
- mAudioRecord.startRecording();
- b = false;
- }
- Log.i(TAG, "录音开始初始化");
- SystemClock.sleep(10);
- }
- byte[] audioData = new byte[512]; // 640
- byte[] audioData1 = new byte[2048]; // inputSamples = 1024, maxOutputBytes = 768 ,maxInputBytes = 2048 (jni 中编码aac中获取到的信息)
- int i = 0;
- while (recordTag) {
- int size = mAudioRecord.read(audioData, 0,audioData.length);
- if (size == audioData.length) {
- Log.i("AAC_JNI", "录音" + size);
- for(int j = 0; j < size; j++){
- audioData1[j + i * 512] = audioData[j];
- }
- i++;
- if(i == 4){
- this.encoder.sendRecordData(audioData1);
- i = 0;
- }
- }
- }
- } catch (Exception e) {
- Log.i(TAG, "录音过程出错 " + e.getMessage());
- }
- }
- }
jni中结构体
[java] view plain copy
- struct AacDecoderInfo{
- faacEncHandle hEncoder;
- char* pcmBuffer;
- char* aacBuffer;
- int maxInputBytes;
- int maxOutputBytes;
- int bitSize;
- int inputSamples;
- FILE* ftOutFile;
- };
- struct AacDecoderInfo *aacDecoderInfo;
[java] view plain copy
- JNIEXPORT void JNICALL Java_com_ff_aac_jni_AacEncoder_initAACEncoder
- (JNIEnv *env, jobject obj){
- unsigned long sampleRate = 8000;
- unsigned int numChannels = 1;
- unsigned long inputSamples;
- unsigned long maxOutputBytes;
- faacEncHandle hEncoder = faacEncOpen(sampleRate, numChannels, &inputSamples, &maxOutputBytes);
- LOGD("inputSamples = %d, maxOutputBytes = %d, sampleRate = %d", inputSamples, maxOutputBytes);
- faacEncConfigurationPtr pConfigPtr;
- pConfigPtr = faacEncGetCurrentConfiguration(hEncoder);
- if(!pConfigPtr){
- LOGD("faacEncGetCurrentConfiguration ERROR!");
- faacEncClose(hEncoder);
- hEncoder = NULL;
- return;
- }
- pConfigPtr->inputFormat = FAAC_INPUT_16BIT;//输入数据类型
- pConfigPtr->outputFormat = 1; //0-Raw ; 1-ADTS
- pConfigPtr->bitRate = 8000;
- // pConfigPtr->useTns= 0;//瞬时噪声定形(temporal noise shaping,TNS)滤波器
- // pConfigPtr->useLfe= 0;//低频效果
- pConfigPtr->aacObjectType= LOW; //编码类型
- pConfigPtr->shortctl=SHORTCTL_NORMAL;
- pConfigPtr->quantqual=20;
- pConfigPtr->mpegVersion = MPEG2;
- int nRetVal = faacEncSetConfiguration(hEncoder, pConfigPtr);
- LOGD("nRetVal = %d", nRetVal);
- int nPCMBitSize = 16; // 量化位数
- int m_nMaxInputBytes = inputSamples * nPCMBitSize / 8;
- LOGD("m_nMaxInputBytes = %d", m_nMaxInputBytes);
- char pbPCMBuffer[m_nMaxInputBytes]; // 读取PCM数据
- char pbAACBuffer[maxOutputBytes];
- FILE* fpOut = fopen("/storage/emulated/0/t/pcm2aac.aac", "wb");
- aacDecoderInfo = malloc(sizeof(struct AacDecoderInfo));
- aacDecoderInfo->hEncoder = hEncoder;
- aacDecoderInfo->pcmBuffer = pbPCMBuffer;
- aacDecoderInfo->aacBuffer = pbAACBuffer;
- aacDecoderInfo->maxInputBytes = m_nMaxInputBytes;
- aacDecoderInfo->maxOutputBytes = maxOutputBytes;
- aacDecoderInfo->bitSize = nPCMBitSize;
- aacDecoderInfo->inputSamples = inputSamples;
- aacDecoderInfo->ftOutFile = fpOut;
- isRecord = true;
- }
- /*
- * http://blog.csdn.net/jwzhangjie/article/details/8782656 (如果不这样设置将导致编码失败)
- *
- * */
- size_t read_int16(int16_t *outbuf, size_t num, unsigned char *inputbuf){
- size_t i = 0 , j = 0;
- unsigned char bufi[8];
- while(i < num){
- memcpy(bufi, inputbuf+j, (aacDecoderInfo->bitSize / 8));
- j+= (aacDecoderInfo->bitSize / 8);
- int16_t s = ((int16_t*)bufi)[0];
- outbuf[i] = s;
- i++;
- }
- return 0;
- }
- JNIEXPORT void JNICALL Java_com_ff_aac_jni_AacEncoder_sendRecordData
- (JNIEnv *env, jobject obj, jbyteArray arr){
- LOGD("sendRecordData isRecord = %d", isRecord);
- jsize size = (*env)->GetArrayLength(env, arr);
- LOGD("sendRecordData arr size = %d", size);
- int inputSamples = size / (aacDecoderInfo->bitSize / 8);
- LOGD("sendRecordData intputSamples = %d, default intputSamples = %d", inputSamples, aacDecoderInfo->inputSamples);
- memset(aacDecoderInfo->aacBuffer, 0, aacDecoderInfo->maxOutputBytes);
- char* cArr = (*env)->GetByteArrayElements(env,arr,false);
- int pumbuff_size = size / (aacDecoderInfo->bitSize / 8);
- int pumBuf[pumbuff_size];
- read_int16(pumBuf, size, cArr);
- int nRetVal = faacEncEncode(aacDecoderInfo->hEncoder, pumBuf, inputSamples, aacDecoderInfo->aacBuffer, aacDecoderInfo->maxOutputBytes);
- LOGD("sendRecordData nRetVal = %d", nRetVal);
- (*env)->ReleaseByteArrayElements(env, arr, cArr, 0);
- fwrite(aacDecoderInfo->aacBuffer, 1, nRetVal, aacDecoderInfo->ftOutFile);
- }
- JNIEXPORT void JNICALL Java_com_ff_aac_jni_AacEncoder_stopSendRecodData
- (JNIEnv *env, jobject obj){
- fclose(aacDecoderInfo->ftOutFile);
- faacEncClose(aacDecoderInfo->hEncoder);
- free(aacDecoderInfo);
- }
[java] view plain copy
- int frequency = 8000;
- int channel = AudioFormat.CHANNEL_IN_MONO;
- int sampbit = AudioFormat.ENCODING_PCM_16BIT;
- audioRecord = new DAudioRecord(frequency, channel, sampbit);
- audioRecord.init();
- final AacEncoder encoder = new AacEncoder();
- audioRecord.startRecord(encoder);
[java] view plain copy
- package com.ff.aac.jni;
- public class AacEncoder {
- static{
- System.loadLibrary("aacdec");
- }
- public native void initAACEncoder();
- public native void sendRecordData(byte[] data);
- public native void stopSendRecodData();
- }
0 0
- android 实时PCM数据编码成AAC
- android 实时PCM数据编码成AAC【转】
- FFmepg 音频编码(PCM数据编码成AAC android)
- android音频采集,MediaCodec实时PCM转AAC
- Android PCM音频的采集和编码成AAC
- Faac 编码实时pcm流到aac流 并用mp4v2打包成mp4文件
- Faac 编码实时pcm流到aac流
- Faac 编码实时pcm流到aac流
- DirectShow音频采集pcm,实时编码AAC,附源码
- Faac 编码实时pcm流到aac流
- PCM编码AAC
- PCM 编码为AAC
- 【FFmpeg(2016)】PCM编码AAC
- H.264+pcm(实时转aac) 封装mp4 iOS,android,Linux 写文件,效率高.iOS支持写1080P.
- 麦克风PCM数据实时编码MP3数据的方法
- PCM音频采样数据编码为AAC的压缩编码数据
- (转)音频编解码·实战篇(1)PCM转至AAC(AAC编码)
- 从 将pcm数据通过AVAssetWriter输出成aac
- 微信登陆的坑
- Android中NoClassDefFoundError异常解决记录
- --配置虚拟主机的流程
- 年终总结
- VSync Count 垂直同步
- android 实时PCM数据编码成AAC【转】
- cocos2d-js 把JS错误打印到屏幕上
- 104. Maximum Depth of Binary Tree
- Go语言开发IM与推送业务
- GENERATED_BODY vs GENERATED_UCLASS_BODY
- Unity3D项目程序加密1——在Unity3D里使用自己的dll
- JS 基础教程3
- 关于稀疏自编码-------“搞基”总结
- Cookie