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

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

获取PCM流

[java]  view plain  copy
 
  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
 
  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
 
  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
 
  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
 
  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 实时PCM数据编码成AAC【转】)