Android Native C++ 层中使用AudioRecord录制PCM音频
来源:互联网 发布:进入带网络的安全模式 编辑:程序博客网 时间:2024/05/16 14:07
Android应用程序很少会用到Android Native C++ 层中AudioRecord来录制PCM,但也不是完全没有需求,至少这么做可以在不懂C++的程序员面前装装逼!
直接在Native C++层录制和处理PCM数据可以避免数据拷贝到虚拟机,再由虚拟机拷回到Native C++层;虽然这个消耗笔者认为应该不大,但是没有具体分析过虚拟机,不清楚,有知道的朋友请告诉一下。
本文描述了在Android Native C++ 层中使用AudioRecord录制PCM音频的一般方法,希望对有此需求的童鞋有所帮助。
可以看到AudioRecord位于android名字空间中,继承于RefBase,这个基类是智能指针引用计数用的,而
直接在Native C++层录制和处理PCM数据可以避免数据拷贝到虚拟机,再由虚拟机拷回到Native C++层;虽然这个消耗笔者认为应该不大,但是没有具体分析过虚拟机,不清楚,有知道的朋友请告诉一下。
本文描述了在Android Native C++ 层中使用AudioRecord录制PCM音频的一般方法,希望对有此需求的童鞋有所帮助。
C++层的AudioRecord类位于源码目录\frameworks\av\include\media\AudioRecord.h中,定义如下:
namespace android {class audio_track_cblk_t;// ----------------------------------------------------------------------------class AudioRecord : virtual public RefBase{public: static const int DEFAULT_SAMPLE_RATE = 8000; ...} //end of calss} //end of namespace android
可以看到AudioRecord位于android名字空间中,继承于RefBase,这个基类是智能指针引用计数用的,而
class AudioRecord : virtual public RefBase虚继承是为了解决菱形继承问题,让从不同的路径继承过来的同一个类在子类内存中只有一个拷贝。
以下是具体代码:
#include <media/AudioRecord.h>//==============================================//Audio Record Defination//==============================================static pthread_tg_AudioRecordThread;static pthread_t *g_AudioRecordThreadPtr = NULL;volatile bool g_bQuitAudioRecordThread = false;volatile int g_iInSampleTime = 0;int g_iNotificationPeriodInFrames = 8000/10; // g_iNotificationPeriodInFrames should be change when sample rate changes.static void *AudioRecordThread( void *inArg );void StartAudioRecordThread();void StopAudioRecordThread();void AudioRecordCallback(int event, void* user, void *info){if(event == android::AudioRecord::EVENT_NEW_POS){g_iInSampleTime += g_iNotificationPeriodInFrames;//if(g_iInSampleTime > g_iNotificationPeriodInFrames*100) //g_bQuitAudioRecordThread = true;}else if (event == android::AudioRecord::EVENT_MORE_DATA){android::AudioRecord::Buffer* pBuff = (android::AudioRecord::Buffer*)info; pBuff->size = 0;}else if (event == android::AudioRecord::EVENT_OVERRUN){LOGE(" EVENT_OVERRUN \n");}}static void *AudioRecordThread( void *inArg ){uint64_t inHostTime = 0;void *inBuffer = NULL; audio_source_t inputSource = AUDIO_SOURCE_MIC;audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;audio_channel_mask_t channelConfig = AUDIO_CHANNEL_IN_MONO; //AUDIO_CHANNEL_IN_STEREO;int bufferSizeInBytes = 1600;int sampleRateInHz = 8000;android::AudioRecord *pAudioRecord = NULL;FILE * g_pAudioRecordFile = NULL;char strAudioFile[] = "/mnt/sdcard/external_sd/AudioRecordFile.pcm";int iNbChannels = 1;// 1 channel for mono, 2 channel for streoint iBytesPerSample = 2; // 16bits pcm, 2Bytesint frameSize = 0;// frameSize = iNbChannels * iBytesPerSample int minFrameCount = 0;// get from AudroRecord objectint iWriteDataCount = 0;// how many data are there write to file// log the thread id for debug infoLOGD("%s Thread ID = %d \n", __FUNCTION__, pthread_self()); g_iInSampleTime = 0;g_pAudioRecordFile = fopen(strAudioFile, "wb+");iNbChannels = (channelConfig == AUDIO_CHANNEL_IN_STEREO) ? 2 : 1;frameSize = iNbChannels * iBytesPerSample;android::status_t status = android::AudioRecord::getMinFrameCount(&minFrameCount, sampleRateInHz, audioFormat, channelConfig);if(status != android::NO_ERROR){LOGE("%s AudioRecord.getMinFrameCount fail \n", __FUNCTION__);goto exit ;}LOGE("sampleRateInHz = %d minFrameCount = %d iNbChannels = %d frameSize = %d ", sampleRateInHz, minFrameCount, iNbChannels, frameSize);bufferSizeInBytes = minFrameCount * frameSize;inBuffer = malloc(bufferSizeInBytes); if(inBuffer == NULL){LOGE("%s alloc mem failed \n", __FUNCTION__);goto exit ; }g_iNotificationPeriodInFrames = sampleRateInHz/10;pAudioRecord = new android::AudioRecord();if(NULL == pAudioRecord){LOGE(" create native AudioRecord failed! ");goto exit;}pAudioRecord->set( inputSource, sampleRateInHz, audioFormat, channelConfig, 0, AudioRecordCallback, NULL, 0, true, 0); if(pAudioRecord->initCheck() != android::NO_ERROR) {LOGE("AudioTrack initCheck error!");goto exit;}if(pAudioRecord->setPositionUpdatePeriod(g_iNotificationPeriodInFrames) != android::NO_ERROR){LOGE("AudioTrack setPositionUpdatePeriod error!");goto exit;}if(pAudioRecord->start()!= android::NO_ERROR){LOGE("AudioTrack start error!");goto exit;}while (!g_bQuitAudioRecordThread){inHostTime = UpTicks();int readLen = pAudioRecord->read(inBuffer, bufferSizeInBytes);int writeResult = -1;if(readLen > 0) {iWriteDataCount += readLen;if(NULL != g_pAudioRecordFile){writeResult = fwrite(inBuffer, 1, readLen, g_pAudioRecordFile);if(writeResult < readLen){LOGE("Write Audio Record Stream error");}}// write PCM data to file or other stream,implement it yourselfwriteResult = WriteAudioData(g_iInSampleTime, inHostTime, inBuffer, readLen);//LOGD("readLen = %d writeResult = %d iWriteDataCount = %d", readLen, writeResult, iWriteDataCount);}else {LOGE("pAudioRecord->read readLen = 0");}}exit:if(NULL != g_pAudioRecordFile){fflush(g_pAudioRecordFile);fclose(g_pAudioRecordFile);g_pAudioRecordFile = NULL;}if(pAudioRecord){pAudioRecord->stop();delete pAudioRecord;pAudioRecord == NULL;}if(inBuffer){free(inBuffer);inBuffer = NULL;}LOGD("%s Thread ID = %d quit\n", __FUNCTION__, pthread_self());return NULL;}
呕心沥血所作,有用请点赞!
6 1
- Android Native C++ 层中使用AudioRecord录制PCM音频
- Android使用AudioRecord录制pcm音频原始数据以及使用AudioTrack播放
- 《android多媒体api》之AudioRecord原始音频pcm录制api
- 使用AudioRecord录制音频
- Android音频开发之使用AudioRecord录制
- Android音频处理之通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能
- Android音频录制--AudioRecord
- Android AudioRecord录制wav格式的音频
- android AudioRecord 音频录制 噪音消除
- Android MediaRecorder与AudioRecord音频录制
- Android音频处理——通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能
- Android音频处理——通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能
- Android音频处理——通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能
- AudioRecord 录制音频
- Android 音视频开发(二):使用 AudioRecord 采集音频PCM并保存到文件
- 使用AudioTrack和AudioRecord录制和播放PCM wave文件
- 使用AudioTrack和AudioRecord录制和播放PCM wave文件
- 使用AudioTrack和AudioRecord录制和播放PCM wave文件
- Java多线程(二)
- 初学hadoop2.7.1(一)配置单点模式
- MongoDB C++ 接口说明
- dwr实现聊天室功能
- Android studio更新后创建不了项目
- Android Native C++ 层中使用AudioRecord录制PCM音频
- Java基础知识
- 6.依赖注入
- 行为树-学习笔记(5)-AI寻找玩家目标并攻击的实现
- iOS7新JavaScriptCore框架入门介绍
- Spring配置JNDI及通过JNDI获取DataSource
- ubuntu14.04下通过.frm, .MYD,.MYI文件恢复建立mysql数据库
- MyEclipse从数据库反向生成实体类之Hibernate方式 反向工程
- java内存解析