来自:http://blog.csdn.net/qq_24551315/article/details/51135681
获取PCM流
- 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中结构体
- struct AacDecoderInfo{
- faacEncHandle hEncoder;
- char* pcmBuffer;
- char* aacBuffer;
- int maxInputBytes;
- int maxOutputBytes;
- int bitSize;
- int inputSamples;
- FILE* ftOutFile;
- };
- struct AacDecoderInfo *aacDecoderInfo;
- 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);
- }
- 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);
- 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();
- }