RK32XX系列 Android音频采集

如果是Android 平台可以使用ndk下的opensles进行采集,如果是Linux使用alsa 通用api,本文只贴openeles

audioReader.h

/*
 * Copyright 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef NATIVE_AUDIO_AUDIO_RECORDER_H
#define NATIVE_AUDIO_AUDIO_RECORDER_H
#include <sys/types.h>
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
//#include "DataManager.h"
//#define MAXAUDIOSIZE 441*100
#define MAXAUDIONUM 5

struct SampleFormat{
    uint32_t sampleRate = 44100000;
    uint32_t framesPerBuf = 512;
    uint16_t channels = 1;
    uint16_t pcmFormat = 16;  // 8 bit, 16 bit, 24 bit ...
    uint32_t representation;  // android extensions
};


class AudioRecorder {
private:
  SLObjectItf recObjectItf_;
  SLRecordItf recItf_;
  SLAndroidSimpleBufferQueueItf recBufQueueItf_;
  
  SLEngineItf slEngineItf_;
  SLObjectItf slEngineObj_;

  SampleFormat sampleInfo;
  uint32_t audioBufCount;
  //StreamDataPool<ImageNode> mStreamDataPool;
  unsigned char mStart=0;
  unsigned char *mFrameList[MAXAUDIONUM]={0};
  unsigned char *mBuf=NULL;
  unsigned long long mBufSize=0;
  unsigned long long mMaxBufSize=0;
  //ENGINE_CALLBACK callback_;
  void *ctx_;
  //uint8_t* audioBuf;
  int mFrameSize = 512;
 public:
  static AudioRecorder *GetInstance(){
  	static AudioRecorder aRecorder;
    return &aRecorder;
  }
  AudioRecorder();
  ~AudioRecorder();
  void Init(SampleFormat *sampleFormat);
  SLboolean Start();
  SLboolean Stop();
  void ProcessSLCallback(SLAndroidSimpleBufferQueueItf bq);
  int32_t dbgGetDevBufCount(void);
  int getAudio(unsigned char *Buf,int getSize,unsigned long long &getPos);
#ifdef ENABLE_LOG
  AndroidLog *recLog_;
#endif
};

#endif  // NATIVE_AUDIO_AUDIO_RECORDER_H

AudioReader.cpp

/*
 * Copyright 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstring>
#include <cstdlib>
#include "AudioReader.h"

/*
 * bqRecorderCallback(): called for every buffer is full;
 *                       pass directly to handler
 */
void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *rec)
{
  (static_cast<AudioRecorder *>(rec))->ProcessSLCallback(bq);
}

void AudioRecorder::ProcessSLCallback(SLAndroidSimpleBufferQueueItf bq)
{
  // static FILE *audiofile = NULL;
  
  SLresult result;
  //static FILE *fp=fopen("./aaa.pcm","wb");
  //ImagePool *p = DataManager::GetInstance()->GetNewImagePool(AUDIO_DATA, mFrameSize);
  /*char tmpBuf[4096];
  result = (*bq)->Enqueue(bq, tmpBuf, mFrameSize);
  printf("result=%d,mFrameSize=%d\n",result,mFrameSize);
  if(fp){
		fwrite(tmpBuf,1,mFrameSize,fp);
  }
  return;*/
  unsigned int startPos=mBufSize%mMaxBufSize;
  if(mMaxBufSize-startPos>=mFrameSize){
  	result = (*bq)->Enqueue(bq, mBuf+startPos, mFrameSize);
	//printf("result1=%d,mFrameSize=%d\n",result,mFrameSize);
    //if(fp){
		//fwrite(mBuf+startPos,1,mFrameSize,fp);
    //}
  }
  else{//设置好mMaxBufSize是mFrameSize的整数倍,就不会出现下面的情况
  	char tmpBuf[4096]={0};
  	int rightSize=mMaxBufSize-startPos;
	int leftSize=mFrameSize-rightSize;
	result = (*bq)->Enqueue(bq, tmpBuf, rightSize);
	//printf("result2=%d,mFrameSize=%d\n",result,mFrameSize);
  	memcpy(mBuf+startPos, tmpBuf,rightSize);
	memcpy(mBuf,tmpBuf+rightSize,leftSize);
	//if(fp){
	//	fwrite(mBuf,1,leftSize,fp);
    //}
  }
  mBufSize+=mFrameSize;
 // printf("bufSize=%d\n",mBufSize);
  /*ImageNode node(p->mIndex);
  mStreamDataPool.writeData(&node);
  if (result != SL_RESULT_SUCCESS)
  {
    printf("error\n");
  }*/
  //printf("ProcessSLCallback\n");
}
int AudioRecorder::getAudio(unsigned char *Buf,int getSize,unsigned long long &getPos){
	if(getPos + (unsigned long long)getSize > mBufSize){
		//等待新数据
		return 0;
	}
	if(getPos + (unsigned long long)getSize + mMaxBufSize < mBufSize){
		//延时超过一个缓冲区
		getPos=mBufSize-getSize;
	}
	unsigned long long tmp=getPos;
	//printf("getPosquMAXAUDIOSIZE=%lld,640qu44100=%d\n",getPos%44100,640%44100);
	unsigned int startPos= getPos % mMaxBufSize;
    if(mMaxBufSize-startPos>=getSize){
		//printf("getSize=%d,getPos=%lld,startpos=%d,MAXAUDIOSIZE=%d\n",getSize,getPos,startPos,MAXAUDIOSIZE);
    	memcpy(Buf,mBuf+startPos,getSize);
    }
    else{
  	  int rightSize=mMaxBufSize-startPos;
	  int leftSize=getSize-rightSize;
  	  memcpy(Buf,mBuf+startPos, rightSize);
	  memcpy(Buf+rightSize,mBuf, leftSize);
	 // printf("getSize=%lld,startpos=%d,rightSize=%d,leftSize=%d\n",getSize,startPos,rightSize,leftSize);
  }
	return getSize;
}

void ConvertToSLSampleFormat(SLAndroidDataFormat_PCM_EX *pFormat,
                             SampleFormat *pSampleInfo)
{
  // assert(pFormat);
  memset(pFormat, 0, sizeof(*pFormat));

  pFormat->formatType = SL_DATAFORMAT_PCM;
  // Only support 2 channels
  // For channelMask, refer to wilhelm/src/android/channels.c for details
  if (pSampleInfo->channels <= 1)
  {
    pFormat->numChannels = 1;
    pFormat->channelMask = SL_SPEAKER_FRONT_LEFT;
  }
  else
  {
    pFormat->numChannels = 2;
    pFormat->channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
  }
  pFormat->sampleRate = pSampleInfo->sampleRate;

  pFormat->endianness = SL_BYTEORDER_LITTLEENDIAN;
  pFormat->bitsPerSample = pSampleInfo->pcmFormat;
  pFormat->containerSize = pSampleInfo->pcmFormat;

  /*
   * fixup for android extended representations...
   */
  pFormat->representation = pSampleInfo->representation;
  switch (pFormat->representation)
  {
  case SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT:
    pFormat->bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_8;
    pFormat->containerSize = SL_PCMSAMPLEFORMAT_FIXED_8;
    pFormat->formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
    break;
  case SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT:
    pFormat->bitsPerSample =
        SL_PCMSAMPLEFORMAT_FIXED_16; // supports 16, 24, and 32
    pFormat->containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
    pFormat->formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
    break;
  case SL_ANDROID_PCM_REPRESENTATION_FLOAT:
    pFormat->bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_32;
    pFormat->containerSize = SL_PCMSAMPLEFORMAT_FIXED_32;
    pFormat->formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
    break;
  case 0:
    break;
  default:
    break;
  }
}

void AudioRecorder::Init(SampleFormat *sampleFormat)
{
  printf("AudioRecorder Init in\n");
  if(mStart==1){
  	printf("audio input already opened\n");
  	return ;
  }
  mStart=1;
  memcpy(&sampleInfo, sampleFormat, sizeof(SampleFormat));

  SLresult result;
  uint32_t bufSize = sampleInfo.framesPerBuf * sampleInfo.channels *
                     sampleInfo.pcmFormat;

  result = slCreateEngine(&slEngineObj_, 0, NULL, 0, NULL, NULL);
  result = (*slEngineObj_)->Realize(slEngineObj_, SL_BOOLEAN_FALSE);
  result = (*slEngineObj_)->GetInterface(slEngineObj_, SL_IID_ENGINE, &slEngineItf_);
  // slEngine = slEngineItf_;
  bufSize = (bufSize + 7) >> 3;
  mFrameSize = (bufSize + 3) & ~3;
  mMaxBufSize=16000*3/mFrameSize*mFrameSize;//缓冲区3秒数据
  if(mBuf==NULL)
  	mBuf=new unsigned char[mMaxBufSize];
  //audioBuf = new uint8_t[mFrameSize];

  SLAndroidDataFormat_PCM_EX format_pcm;
  ConvertToSLSampleFormat(&format_pcm, &sampleInfo);

  // configure audio source
  SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE,
                                    SL_IODEVICE_AUDIOINPUT,
                                    SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
  SLDataSource audioSrc = {&loc_dev, NULL};
  //int size = DataManager::GetInstance()->GetPoolSize(AUDIO_DATA);

  for(int i=0;i<MAXAUDIONUM;i++)
  	if(mFrameList[i]==NULL)//没有考虑mFrameSize发生改变的情况
  		mFrameList[i]=new unsigned char[mFrameSize];
  // configure audio sink
  SLDataLocator_AndroidSimpleBufferQueue loc_bq = {
      SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, (SLuint32)MAXAUDIONUM};//

  SLDataSink audioSnk = {&loc_bq, &format_pcm};

  // create audio recorder
  // (requires the RECORD_AUDIO permission)
  const SLInterfaceID id[2] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
                               SL_IID_ANDROIDCONFIGURATION};
  const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
  result = (*slEngineItf_)->CreateAudioRecorder(slEngineItf_, &recObjectItf_, &audioSrc, &audioSnk, sizeof(id) / sizeof(id[0]), id, req);
  // SLASSERT(result);

  // Configure the voice recognition preset which has no
  // signal processing for lower latency.
  SLAndroidConfigurationItf inputConfig;
  result = (*recObjectItf_)
               ->GetInterface(recObjectItf_, SL_IID_ANDROIDCONFIGURATION,
                              &inputConfig);
  if (SL_RESULT_SUCCESS == result)
  {
    SLuint32 presetValue = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
    (*inputConfig)
        ->SetConfiguration(inputConfig, SL_ANDROID_KEY_RECORDING_PRESET,
                           &presetValue, sizeof(SLuint32));
  }
  result = (*recObjectItf_)->Realize(recObjectItf_, SL_BOOLEAN_FALSE);
  if (SL_RESULT_SUCCESS != result)
  {
    printf("audio input Realize error\n");
    return;
  }
  result =
      (*recObjectItf_)->GetInterface(recObjectItf_, SL_IID_RECORD, &recItf_);
  if (SL_RESULT_SUCCESS != result)
  {
    printf("audio input GetInterface error\n");
    return;
  }
  result = (*recObjectItf_)
               ->GetInterface(recObjectItf_, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
                              &recBufQueueItf_);
  if (SL_RESULT_SUCCESS != result)
  {
    printf("audio input GetInterface error\n");
    return;
  }
  result = (*recBufQueueItf_)
               ->RegisterCallback(recBufQueueItf_, bqRecorderCallback, this);
  if (SL_RESULT_SUCCESS != result)
  {
    printf("audio input RegisterCallback error\n");
    return ;
  }
  printf("audio input AudioRecorder Init out\n");
  Start();
}

SLboolean AudioRecorder::Start(void)
{
  printf("AudioRecorder Start in\n");
 
  audioBufCount = 0;

  SLresult result;
  // in case already recording, stop recording and clear buffer queue
  result = (*recItf_)->SetRecordState(recItf_, SL_RECORDSTATE_STOPPED);
  if (SL_RESULT_SUCCESS != result)
  {
    printf("SetRecordState error\n");
    return -1;
  }
  result = (*recBufQueueItf_)->Clear(recBufQueueItf_);
  if (SL_RESULT_SUCCESS != result)
  {
    printf("Clear error\n");
    return -1;
  }
  //int size = DataManager::GetInstance()->GetPoolSize(AUDIO_DATA);
  //mStreamDataPool.setSize(size);
  for (int i = 0; i < MAXAUDIONUM; i++)
  {
    //ImagePool *p = DataManager::GetInstance()->GetNewImagePool(AUDIO_DATA, mFrameSize);
    result = (*recBufQueueItf_)->Enqueue(recBufQueueItf_, mFrameList[i], mFrameSize);
    printf("Enqueue here    \n");
    if (SL_RESULT_SUCCESS != result)
    {
      printf("Enqueue error\n");
      return -1;
    }
  }
  result = (*recItf_)->SetRecordState(recItf_, SL_RECORDSTATE_RECORDING);
  if (SL_RESULT_SUCCESS != result)
  {
    printf("SetRecordState error\n");
    return -1;
  }
  printf("AudioRecorder Start out\n");
  return (result == SL_RESULT_SUCCESS ? SL_BOOLEAN_TRUE : SL_BOOLEAN_FALSE);
}

SLboolean AudioRecorder::Stop(void)
{
  // in case already recording, stop recording and clear buffer queue
  if(mStart==0){
  	printf("audio input not open\n");
	return SL_BOOLEAN_FALSE;
  }
  SLuint32 curState;

  SLresult result = (*recItf_)->GetRecordState(recItf_, &curState);
  if (curState == SL_RECORDSTATE_STOPPED)
  {
    return SL_BOOLEAN_TRUE;
  }
  result = (*recItf_)->SetRecordState(recItf_, SL_RECORDSTATE_STOPPED);
  result = (*recBufQueueItf_)->Clear(recBufQueueItf_);
  mStart=0;
  return SL_BOOLEAN_TRUE;
}
AudioRecorder::AudioRecorder()
{
}
AudioRecorder::~AudioRecorder()
{
  // destroy audio recorder object, and invalidate all associated interfaces
  if (recObjectItf_ != NULL)
  {
    (*recObjectItf_)->Destroy(recObjectItf_);
  }
  if(mBuf)
  	delete []mBuf;
  for(int i=0;i<MAXAUDIONUM;i++)
  	if(mFrameList[i])
  		delete []mFrameList[i];
}

CmakeLists.txt 加上 OpenSLES

大功告成

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hmbbPdx_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值