一、背景:

发现网上能搜到的都是几年前的例子,现在Android版本都出到12了,几年前的例子以及不适用新版本了。于是就自己研究了下AudioRecord.java是如何调用到jni和C++层的AudioRecord.cpp。做一下记录为后来者避坑(PS:以前都不喜欢写博客,本人没时间也不太想分享)。改demo应该适用于Android8,Android9,Android10,Android11,Android12。或许过个几年到Androidxx又不适用了。

二、遇到比较有意思的坑:

程序运行没有报错但是录音没有声音,dump文件拉到电脑播放也是一条直线没有声音。后来分析是google基于安全 权限考虑做的限制。会根据uid,ui是否在前台等对AudioRecord进行静音。

解决方法有两个:
1. 注释掉:void AudioFlinger::setRecordSilenced(audio_port_handle_t portId, bool silenced)函数静音代码。

2. 使用 audio_source_t inputSource =AUDIO_SOURCE_HOTWORD;//AUDIO_SOURCE_MIC;

在老版本Android是使用AUDIO_SOURCE_MIC类型的。这里因为是c++ native没有ui界面等所以必须使用AUDIO_SOURCE_HOTWORD类型,否则 AudioRecord录音没有声音。

三、Demo源码:

例子有点乱,没有整理。AudioTrack是基于framework目录下AudioTrack共享内存例子修改的。

AudioRecord没有原生例子,只能自己研究了。

demo_test:


#define LOG_NDEBUG 0
#define LOG_TAG "demo_test"#include <stdlib.h>
#include <stdio.h>
#include <cutils/properties.h>
#include <media/AudioSystem.h>
#include <media/AudioTrack.h>
#include <media/AudioRecord.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <media/AidlConversion.h>#include <utils/Log.h>#include <fcntl.h>
#include "demo_test.h"
#define SOUND_LENGTH        18470
volatile bool                         g_bQuitAudioRecordThread = false;
int                                                                 g_iNotificationPeriodInFrames = 8000/10;
void StartAudioRecordThread();
void StopAudioRecordThread();
void *        inBuffer = NULL;
int myreadlen = 0;
int mywritelen = 0;
int                                                                         bufferSizeInBytes = 1600;
#define SAMPLE_RATE 16000// 这里必须使用 AUDIO_SOURCE_HOTWORD 否则录音无声,或者把 void AudioFlinger::setRecordSilenced(audio_port_handle_t portId, bool silenced)
//函数注释为空。
audio_source_t                                 inputSource                         = AUDIO_SOURCE_HOTWORD;//AUDIO_SOURCE_HOTWORD;//AUDIO_SOURCE_MIC;
static const audio_attributes_t pAttributes = {
/* .content_type = */ AUDIO_CONTENT_TYPE_UNKNOWN, // 0
/* .usage = */ (audio_usage_t)AUDIO_USAGE_UNKNOWN, // 0
/* .source = */ inputSource, // 1
/* .flags = */ AUDIO_FLAG_MUTE_HAPTIC,// 0x00000800 //AUDIO_FLAG_NONE,
/* .tags = */ "demo_test"
};
static android::content::AttributionSourceState attributionSource;namespace android {void AudioRecordCallback(int event, void* user, void *info)
{char *p;if(user)p = (char *)user;if(event == android::AudioRecord::EVENT_NEW_POS){       ALOGD(" android::AudioRecord::EVENT_NEW_POS \n");//if(g_iInSampleTime > g_iNotificationPeriodInFrames*100)//                g_bQuitAudioRecordThread = true;}else if (event == android::AudioRecord::EVENT_MORE_DATA){               ALOGD(" android::AudioRecord::EVENT_MORE_DATA..... \n");android::AudioRecord::Buffer* pBuff = (android::AudioRecord::Buffer*)info;pBuff->size = 0;}else if (event == android::AudioRecord::EVENT_OVERRUN){ALOGD(" EVENT_OVERRUN \n");}
}
#if 1
static void AudioRecordThread()
{audio_format_t                                 audioFormat                         = AUDIO_FORMAT_PCM_16_BIT;        // 1audio_channel_mask_t         channelConfig                 = AUDIO_CHANNEL_IN_MONO;//AUDIO_CHANNEL_IN_MONO; //AUDIO_CHANNEL_IN_STEREO;       int                                                                         sampleRateInHz                 = SAMPLE_RATE;       sp<AudioRecord> pAudioRecord = 0;FILE *                                                                         g_pAudioRecordFile                 = NULL;char                                                                                 strAudioFile[]                                 = "/sdcard/AudioRecordFile.pcm";int iNbChannels                 = 1;        // 1 channel for mono, 2 channel for streoint iBytesPerSample = 2;         // 16bits pcm, 2Bytesint frameSize                         = 0;        // frameSize = iNbChannels * iBytesPerSamplesize_t minFrameCount         = 0;        // get from AudroRecord objectg_pAudioRecordFile = fopen(strAudioFile, "wb+");       iNbChannels = (channelConfig == AUDIO_CHANNEL_IN_STEREO) ? 2 : 1;frameSize         = iNbChannels * iBytesPerSample;       android::status_t         status = AudioRecord::getMinFrameCount(&minFrameCount, sampleRateInHz, audioFormat, channelConfig);       if(status != android::NO_ERROR){ALOGD("%s  AudioRecord.getMinFrameCount fail \n", __FUNCTION__);}// sampleRateInHz = 16000 minFrameCount = 768 iNbChannels = 2 frameSize = 4ALOGD("sampleRateInHz = %d minFrameCount = %d iNbChannels = %d frameSize = %d ",sampleRateInHz, (int)minFrameCount, iNbChannels, frameSize);       bufferSizeInBytes = (int)minFrameCount * frameSize;//bufferSizeInBytes =  2*SOUND_LENGTH;g_iNotificationPeriodInFrames = sampleRateInHz/10;       String16 opPackageName("demo_test");uid_t uid = -1;pid_t pid = -1;attributionSource.packageName = VALUE_OR_FATAL(legacy2aidl_String16_string(opPackageName));attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t((unsigned int)uid));attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t((int)pid));attributionSource.token = sp<BBinder>::make();pAudioRecord  = new AudioRecord(attributionSource);       if(NULL == pAudioRecord){ALOGD(" create native AudioRecord failed! ");}                       audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;// 0audio_session_t sessionId = (audio_session_t)0;int sharedAudioHistoryMs  = 0;status_t status2 =pAudioRecord->set(pAttributes.source, sampleRateInHz,audioFormat, // word length, PCMchannelConfig, 768,AudioRecordCallback, // callback_tNULL,   // void* user0,                // notificationFrames,true,             // threadCanCallJavasessionId, AudioRecord::TRANSFER_DEFAULT, flags, -1,-1, // default uid, pid&pAttributes, AUDIO_PORT_HANDLE_NONE, MIC_DIRECTION_UNSPECIFIED,MIC_FIELD_DIMENSION_DEFAULT, sharedAudioHistoryMs);if (status2 != NO_ERROR) {ALOGE("Error creating AudioRecord instance: initialization check failed with status2 %d.",status2);}pAudioRecord->setCallerName("demo_test");                               if(pAudioRecord->initCheck() != android::NO_ERROR) {ALOGD("AudioTrack initCheck error!");}if(pAudioRecord->setPositionUpdatePeriod(g_iNotificationPeriodInFrames) != android::NO_ERROR){ALOGD("AudioTrack setPositionUpdatePeriod error!");}if(pAudioRecord->start()!= android::NO_ERROR){ALOGD("AudioTrack start error!");}       int i = 0;int readLen = 0;while (!g_bQuitAudioRecordThread){readLen = pAudioRecord->read((uint8_t*)inBuffer+i*readLen, 320/*bufferSizeInBytes*/, 1);int writeResult = -1;if(readLen > 0){myreadlen += readLen;if ( myreadlen > 7*SOUND_LENGTH ) {ALOGD("pAudioRecord->read  end");break;}//iWriteDataCount += readLen;if(NULL != g_pAudioRecordFile){writeResult = fwrite((uint8_t*)inBuffer+i*readLen, 1, readLen, g_pAudioRecordFile);                               if(writeResult < readLen){ALOGE("Write Audio Record Stream error");}mywritelen += writeResult;}i++;       }else{ALOGD("pAudioRecord->read  readLen = 0");}}ALOGD("myreadlen = %d  mywritelen = %d\n", myreadlen, mywritelen);       if(pAudioRecord){pAudioRecord->stop();}if(NULL != g_pAudioRecordFile){fflush(g_pAudioRecordFile);fclose(g_pAudioRecordFile);               g_pAudioRecordFile = NULL;               }
}#endif/************************************************************
*
*    Constructor
*
************************************************************/
AudioTrackTest::AudioTrackTest(void) {ALOGD("01 AudioTrackTest\n");}/************************************************************
*
*
************************************************************/
void AudioTrackTest::Execute(void) {if (Test01() == 0) {ALOGD("01 passed\n");} else {ALOGD("01 failed\n");}
}/************************************************************
*
*    Shared memory test
*
************************************************************/
#define BUF_SZ 44100int AudioTrackTest::Test01() {bufferSizeInBytes =  10*SOUND_LENGTH;inBuffer = malloc(bufferSizeInBytes);if(inBuffer == NULL){               ALOGD("%s  alloc mem failed \n", __FUNCTION__);               }memset(inBuffer, 0, bufferSizeInBytes);uint8_t* buf = (uint8_t*)inBuffer;long sampleRate = SAMPLE_RATE;size_t framecount = 16;AudioRecordThread();if (AudioTrack::getMinFrameCount(&framecount, AUDIO_STREAM_MUSIC, sampleRate) != NO_ERROR ) {ALOGD("Error: cannot compute output frame count\n");return -1;}ALOGD("framecount = %d \n",  (int)framecount);sp<AudioTrack> track = new AudioTrack(AUDIO_STREAM_MUSIC,// stream typesampleRate,AUDIO_FORMAT_PCM_16_BIT,// word length, PCMAUDIO_CHANNEL_OUT_MONO,  // AUDIO_CHANNEL_OUT_STEREO0);status_t status = track->initCheck();if(status != NO_ERROR) {track.clear();ALOGD("Failed for initCheck()");return -1;}// start playALOGD("start");track->start();for(int j = 0; j < 3; j++)for(int i = 0; i <= 7*SOUND_LENGTH/320 ; i++){track->write(buf+i*320, 320, 1);}ALOGD("stop");track->stop();if(inBuffer){free(inBuffer);inBuffer = NULL;}return 0;}/************************************************************
*
*    main in name space
*
************************************************************/
int main() {ProcessState::self()->startThreadPool();AudioTrackTest *test;test = new AudioTrackTest();test->Execute();delete test;return 0;
}}/************************************************************
*
*    global main
*
************************************************************/
int main() {return android::main();
}

demo_test.h


// Copyright 2008 The Android Open Source Project#ifndef AUDIOTRACKTEST_H_
#define AUDIOTRACKTEST_H_namespace android {class AudioTrackTest{public:AudioTrackTest(void);~AudioTrackTest() {};void Execute(void);int Test01();};};#endif /*AUDIOTRACKTEST_H_*/

Android.bp


cc_test {name: "demo_test",gtest: false,srcs: ["demo_test.cpp"],shared_libs: ["liblog","libcutils","libutils","libbinder","libhardware_legacy","libmedia","libaudioclient","libaudioclient_aidl_conversion",],header_libs: ["libmediametrics_headers",],}

Android12 Native C++ 层AudioRecord录音AudioTrack播放相关推荐

  1. Android 录音机小米商业项目开源代码 AudioRecord录音暂停 播放 Wav格式(音频二)

    Android MediaRecorder录音录像 暂停 继续录音 播放 ARM格式(音频一) https://blog.csdn.net/WHB20081815/article/details/88 ...

  2. AudioRecord 录音和播放的Demo

    #AudioRecord 录音和播放的Demo 本文介绍一个AudioRecord的简单录音和播放的示例程序. 录音是需要动态获取权限的! ##主要代码 ###1.AudioRecord录音代码 // ...

  3. Android 音频开发——AudioTrack播放

    Android 音频--PCM转WAV Android 音频开发--AudioRecord录音  AudioTrack类用来管理.播放单个音频资源,它只能播放PCM数据,其他音频格式(aac.amr. ...

  4. Android 音视频开发(一) -- 使用AudioRecord 录制PCM(录音);AudioTrack播放音频

    前言,音视频这块,确实比较难入门,本着学习的态度,我这边也跟着 Android 音视频开发入门指南 打怪升级,留下个脚印,大家共勉. 音视频 系列文章 Android 音视频开发(一) – 使用Aud ...

  5. android 使用 audiorecord 和 audiotrack 实现实时录音播放

    基本思路就是用 audiorecord不断得到音频数据,然后使用audiotrack 播放 //得到音频 package com.ysg.audiotest;import java.io.IOExce ...

  6. NDK学习笔记:JNI调用Java层方法创建Native的AudioTrack播放PCM(方法签名,CallXXXMethod)

    NDK学习笔记:JNI调用Java层方法创建Native的AudioTrack播放PCM 题目有点复杂,不过确实就是那么回事.这章想记录的内容比较多,先列出来: native static 与 nat ...

  7. android 实时录音播放,android 使用 audiorecord 和 audiotrack 实现实时录音播放

    基本思路就是用 audiorecord不断得到音频数据,然后使用audiotrack 播放 //得到音频 package com.ysg.audiotest; import java.io.IOExc ...

  8. android audiotrack权限,android 使用 audiorecord 和 audiotrack 实现实时录音播放

    基本思路就是用 audiorecord不断得到音频数据,然后使用audiotrack 播放 //得到音频 package com.ysg.audiotest; import java.io.IOExc ...

  9. android中录音断点播放,Android实现暂停--继续录音(AudioRecord)

    Android提供了两个API用于录音的实现:MediaRecorder 和 AudioRecord,各有优劣. 1.MediaRecorder 已经集成了录音.编码.压缩等,支持少量的录音音频格式, ...

最新文章

  1. python恶搞程序-愚人节恶搞程序源码【两种语言】
  2. 将一台电脑的磁盘空间映射到另一台电脑
  3. 【解析】Alice and Bob_24行代码AC
  4. USB 摄像头成熟方案介绍
  5. leetcode 483. 最小好进制
  6. oracle truncate 日期,【Oracle】truncate和delete区别
  7. SAP License:成本不是靠算出来的
  8. Linux中Redis的安装
  9. RedissonMultiLock + RedissonLock部分源码
  10. Windows、Linux、Mac OS下的锐捷认证的程序——mentohust
  11. svn合并分支到主干
  12. Springboot项目中添加Quartz定时任务
  13. 让你的网站用上炫酷的中文字体
  14. html5dragw3c,HTML5拖拽功能drag
  15. 物联网技术,主要包括哪些核心技术
  16. 大厂的人自带光环,但光环是从哪儿来的呢?
  17. 嵌入式linux开发笔记——Ubuntu的使用
  18. 详细解说RAID6结构及原理
  19. chromecast 协议_如何删除Chromecast的网络范围内的Android通知
  20. 微信ipad协议GO版本 最新不封号

热门文章

  1. Python 常用库
  2. UNIX/Linux期末复习考试试题
  3. Android 检查版本更新服务并下载,BLE蓝牙连接,BLE蓝牙连接1对多及通用工具
  4. COMSOL如何绘制空间某点声压级曲线
  5. MIUI又出大BUG,把10年米粉整破防了
  6. 07-HTTPS双向认证及Java案例
  7. C语言实验--字符变量的输入输出
  8. 【OpenCL】求矩阵所有元素的和——归约算法
  9. Verilog语法篇
  10. Redis--缓存雪崩--含义/原因/解决方案