android 实时PCM数据编码成AAC【转】

转载 2016年08月30日 10:29:42

来自:http://blog.csdn.net/qq_24551315/article/details/51135681

获取PCM流

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.ff.aac.audio;  
  2. import java.io.File;  
  3. import java.io.FileInputStream;  
  4. import java.io.FileOutputStream;  
  5. import java.io.InputStream;  
  6. import java.io.OutputStream;  
  7. import java.util.ArrayList;  
  8. import java.util.Arrays;  
  9. import java.util.List;  
  10.   
  11. import com.ff.aac.jni.AacEncoder;  
  12.   
  13. import android.media.AudioRecord;  
  14. import android.media.MediaRecorder.AudioSource;  
  15. import android.os.SystemClock;  
  16. import android.util.Log;  
  17. /** 
  18.  * 音频发送封装类 
  19.  */  
  20. public class DAudioRecord implements Runnable{  
  21.     private final String TAG="DAudioRecord";  
  22.     private int mFrequency;//采样率  
  23.     private int mChannel;//声道  
  24.     private int mSampBit;//采样精度  
  25.     private AacEncoder encoder;  
  26.     private AudioRecord mAudioRecord;  
  27.     private boolean recordTag;  
  28.     private int minBufferSize;  
  29.     public DAudioRecord(int frequency,int channel,int sampbit){  
  30.         this.mFrequency = frequency;  
  31.         this.mChannel = channel;  
  32.         this.mSampBit = sampbit;  
  33.     }  
  34.       
  35.     public void init(){  
  36.         if(mAudioRecord != null){  
  37.             release();  
  38.         }  
  39.         try {  
  40.             minBufferSize = AudioRecord.getMinBufferSize(mFrequency, mChannel, mSampBit);  
  41.             mAudioRecord = new AudioRecord(AudioSource.MIC, mFrequency, mChannel, mSampBit, minBufferSize);  
  42.             Log.i(TAG, "minBufferSize = " + minBufferSize);  
  43.         } catch (Exception e) {  
  44.             Log.i(TAG, "创建录音器出错");  
  45.         }  
  46.     }  
  47.       
  48.     public void startRecord(AacEncoder encoder){  
  49.         this.recordTag = true;  
  50.         this.encoder = encoder;  
  51.         new Thread(this).start();  
  52.     }  
  53.       
  54.     public void stopRecord(){  
  55.         this.recordTag = false;  
  56.     }  
  57.       
  58.     public void release(){  
  59.         if(mAudioRecord != null){  
  60.             try {  
  61.                 mAudioRecord.stop();  
  62.                 mAudioRecord.release();  
  63.                 encoder.stopSendRecodData();  
  64.             } catch (Exception e) {  
  65.                 Log.i(TAG, "关闭录音出错");  
  66.             }finally{  
  67.                 mAudioRecord = null;  
  68.                 encoder = null;  
  69.                 System.gc();  
  70.             }  
  71.         }  
  72.     }  
  73.   
  74.     @Override  
  75.     public void run() {  
  76.         try {  
  77.             boolean b = true;  
  78.             while (b && recordTag) {  
  79.                 if(mAudioRecord.getState() == AudioRecord.STATE_INITIALIZED){  
  80.                     mAudioRecord.startRecording();  
  81.                     b = false;  
  82.                 }  
  83.                 Log.i(TAG, "录音开始初始化");  
  84.                 SystemClock.sleep(10);  
  85.             }  
  86.             byte[] audioData = new byte[512]; // 640  
  87.             byte[] audioData1 = new byte[2048]; // inputSamples = 1024, maxOutputBytes = 768  ,maxInputBytes = 2048 (jni 中编码aac中获取到的信息)  
  88.             int i = 0;  
  89.             while (recordTag) {  
  90.                 int size = mAudioRecord.read(audioData, 0,audioData.length);  
  91.                 if (size == audioData.length) {  
  92.                     Log.i("AAC_JNI""录音" + size);  
  93.                     for(int j = 0; j < size; j++){  
  94.                         audioData1[j + i * 512] = audioData[j];  
  95.                     }  
  96.                     i++;  
  97.                     if(i == 4){  
  98.                         this.encoder.sendRecordData(audioData1);  
  99.                         i = 0;  
  100.                     }  
  101.                 }  
  102.             }  
  103.         } catch (Exception e) {  
  104.             Log.i(TAG, "录音过程出错 " + e.getMessage());  
  105.         }  
  106.     }  
  107. }  

jni中结构体

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. struct AacDecoderInfo{  
  2.     faacEncHandle hEncoder;  
  3.     char* pcmBuffer;  
  4.     char* aacBuffer;  
  5.     int maxInputBytes;  
  6.     int maxOutputBytes;  
  7.     int bitSize;  
  8.     int inputSamples;  
  9.     FILE* ftOutFile;  
  10. };  
  11. struct AacDecoderInfo *aacDecoderInfo;  
jni中进行实时编码

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. JNIEXPORT void JNICALL Java_com_ff_aac_jni_AacEncoder_initAACEncoder  
  2.   (JNIEnv *env, jobject obj){  
  3.     unsigned long sampleRate = 8000;  
  4.     unsigned int numChannels = 1;  
  5.     unsigned long inputSamples;  
  6.     unsigned long maxOutputBytes;  
  7.     faacEncHandle hEncoder = faacEncOpen(sampleRate, numChannels, &inputSamples, &maxOutputBytes);  
  8.     LOGD("inputSamples = %d, maxOutputBytes = %d, sampleRate = %d", inputSamples, maxOutputBytes);  
  9.   
  10.     faacEncConfigurationPtr pConfigPtr;  
  11.     pConfigPtr = faacEncGetCurrentConfiguration(hEncoder);  
  12.     if(!pConfigPtr){  
  13.         LOGD("faacEncGetCurrentConfiguration ERROR!");  
  14.         faacEncClose(hEncoder);  
  15.             hEncoder = NULL;  
  16.             return;  
  17.      }  
  18.   
  19.     pConfigPtr->inputFormat = FAAC_INPUT_16BIT;//输入数据类型  
  20.         pConfigPtr->outputFormat = 1//0-Raw ; 1-ADTS  
  21.     pConfigPtr->bitRate = 8000;  
  22.  // pConfigPtr->useTns= 0;//瞬时噪声定形(temporal noise shaping,TNS)滤波器  
  23.  // pConfigPtr->useLfe= 0;//低频效果  
  24.     pConfigPtr->aacObjectType= LOW; //编码类型  
  25.     pConfigPtr->shortctl=SHORTCTL_NORMAL;  
  26.     pConfigPtr->quantqual=20;  
  27.         pConfigPtr->mpegVersion = MPEG2;  
  28.     int nRetVal = faacEncSetConfiguration(hEncoder, pConfigPtr);  
  29.     LOGD("nRetVal = %d", nRetVal);  
  30.   
  31.     int nPCMBitSize = 16// 量化位数  
  32.     int m_nMaxInputBytes = inputSamples * nPCMBitSize / 8;  
  33.     LOGD("m_nMaxInputBytes = %d", m_nMaxInputBytes);  
  34.   
  35.     char pbPCMBuffer[m_nMaxInputBytes]; // 读取PCM数据  
  36.     char pbAACBuffer[maxOutputBytes];  
  37.   
  38.     FILE* fpOut = fopen("/storage/emulated/0/t/pcm2aac.aac""wb");  
  39.     aacDecoderInfo = malloc(sizeof(struct AacDecoderInfo));  
  40.     aacDecoderInfo->hEncoder = hEncoder;  
  41.     aacDecoderInfo->pcmBuffer = pbPCMBuffer;  
  42.     aacDecoderInfo->aacBuffer = pbAACBuffer;  
  43.     aacDecoderInfo->maxInputBytes = m_nMaxInputBytes;  
  44.     aacDecoderInfo->maxOutputBytes = maxOutputBytes;  
  45.     aacDecoderInfo->bitSize = nPCMBitSize;  
  46.     aacDecoderInfo->inputSamples = inputSamples;  
  47.     aacDecoderInfo->ftOutFile = fpOut;  
  48.   
  49.     isRecord = true;  
  50. }  
  51.   
  52. /* 
  53.  * http://blog.csdn.net/jwzhangjie/article/details/8782656 (如果不这样设置将导致编码失败) 
  54.  * 
  55.  *  */  
  56. size_t read_int16(int16_t *outbuf, size_t num, unsigned char *inputbuf){  
  57.     size_t i = 0 , j = 0;  
  58.     unsigned char bufi[8];  
  59.     while(i < num){  
  60.         memcpy(bufi, inputbuf+j, (aacDecoderInfo->bitSize / 8));  
  61.         j+= (aacDecoderInfo->bitSize / 8);  
  62.         int16_t s = ((int16_t*)bufi)[0];  
  63.         outbuf[i] = s;  
  64.         i++;  
  65.     }  
  66.     return 0;  
  67. }  
  68.   
  69. JNIEXPORT void JNICALL Java_com_ff_aac_jni_AacEncoder_sendRecordData  
  70.   (JNIEnv *env, jobject obj, jbyteArray arr){  
  71.     LOGD("sendRecordData isRecord = %d", isRecord);  
  72.     jsize size = (*env)->GetArrayLength(env, arr);  
  73.     LOGD("sendRecordData arr size = %d", size);  
  74.     int inputSamples = size / (aacDecoderInfo->bitSize / 8);  
  75.     LOGD("sendRecordData intputSamples = %d, default intputSamples = %d", inputSamples, aacDecoderInfo->inputSamples);  
  76.     memset(aacDecoderInfo->aacBuffer, 0, aacDecoderInfo->maxOutputBytes);  
  77.     char* cArr = (*env)->GetByteArrayElements(env,arr,false);  
  78.     int pumbuff_size = size / (aacDecoderInfo->bitSize / 8);  
  79.     int pumBuf[pumbuff_size];  
  80.     read_int16(pumBuf, size, cArr);  
  81.   
  82.     int nRetVal = faacEncEncode(aacDecoderInfo->hEncoder, pumBuf, inputSamples, aacDecoderInfo->aacBuffer, aacDecoderInfo->maxOutputBytes);  
  83.     LOGD("sendRecordData nRetVal = %d", nRetVal);  
  84.     (*env)->ReleaseByteArrayElements(env, arr, cArr, 0);  
  85.     fwrite(aacDecoderInfo->aacBuffer, 1, nRetVal, aacDecoderInfo->ftOutFile);  
  86. }  
  87.   
  88. JNIEXPORT void JNICALL Java_com_ff_aac_jni_AacEncoder_stopSendRecodData  
  89.   (JNIEnv *env, jobject obj){  
  90.     fclose(aacDecoderInfo->ftOutFile);  
  91.     faacEncClose(aacDecoderInfo->hEncoder);  
  92.     free(aacDecoderInfo);  
  93. }  
java 调用

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1.        int frequency = 8000;  
  2. int channel = AudioFormat.CHANNEL_IN_MONO;  
  3. int sampbit = AudioFormat.ENCODING_PCM_16BIT;  
  4.     audioRecord = new DAudioRecord(frequency, channel, sampbit);  
  5.     audioRecord.init();  
  6.     final AacEncoder encoder = new AacEncoder();  
  7.     audioRecord.startRecord(encoder);  

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.ff.aac.jni;  
  2.   
  3. public class AacEncoder {  
  4.     static{  
  5.         System.loadLibrary("aacdec");  
  6.     }  
  7.     public native void initAACEncoder();  
  8.     public native void sendRecordData(byte[] data);  
  9.     public native void stopSendRecodData();  
  10. }  

android音频采集,MediaCodec实时PCM转AAC

android音频采集,MediaCodec实时PCM转AAC,网上很多都不是实时采集转换的。希望对有需要的朋友带来一些帮助 先看看关键的转换工具类: package com....
  • KokJuis
  • KokJuis
  • 2017年05月27日 15:36
  • 1714

faad2解码aac到pcm

//解码AAC音频为PCM数据 #pragma once #include "libfaad2/include/faad.h" //aac数据状态 typedef enum AccDataStat...
  • byxdaz
  • byxdaz
  • 2017年01月03日 16:51
  • 2354

FAAD2解码AAC,生成PCM文件,转换WAV格式

  • 2017年05月17日 10:21
  • 30.36MB
  • 下载

音频编解码·实战篇(1)PCM转至AAC(AAC编码)

音频编解码·实战篇(1)PCM转至AAC(AAC编码)作者:柳大·Poechant博客:blog.csdn.net/poechant邮箱:zhongchao.ustc@gmail.com日期:Apri...
  • Poechant
  • Poechant
  • 2012年04月07日 14:15
  • 21474

android 实时PCM数据编码成AAC

获取PCM流 package com.ff.aac.audio; import java.io.File; import java.io.FileInputStream; import java.io...
  • qq_24551315
  • qq_24551315
  • 2016年04月12日 18:01
  • 2421

Android音频处理——通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能

Android音频处理——通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能 音频这方面很博大精深,我这里肯定讲不了什么高级的东西,最多也只是一些基础类知识,首先,我们要介绍...
  • qq_26787115
  • qq_26787115
  • 2016年11月08日 10:41
  • 9520

android pcm编解码

一 什么是音频的采样率和采样大小  自然界中的声音非常复杂,波形极其复杂,通常我们采用的是脉冲代码调制编码。即PCM编码。PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转...
  • pashanhu6402
  • pashanhu6402
  • 2017年08月09日 10:26
  • 235

pcm音频转aac

  • 2013年02月16日 15:32
  • 1.07MB
  • 下载

MediaCodec编译pcm为aac

先说说写这份博客的原因吧: 1.自己的第一篇博客,一味的拿来主义者太过于不厚道 2.记录下来也为自己以后使用,利人利己 3.代码都是亲自测试过 另外说一下需要改动的地方, 1,pac...
  • tn0521
  • tn0521
  • 2015年04月10日 15:21
  • 4856

Android下音频进行转码

一. 音频的简介          先从音频压缩的原理讲起, 人的听力范围是20hz--20khz, 而根据奈奎斯特定理, 要想不产生低频失真,则采样频率至少是录制的最高频率的两倍。 所以CD音质的...
  • qq_26936889
  • qq_26936889
  • 2016年03月01日 13:38
  • 5101
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android 实时PCM数据编码成AAC【转】
举报原因:
原因补充:

(最多只允许输入30个字)