当前位置:   article > 正文

Android12 Native C++ 层AudioRecord录音AudioTrack播放_value_or_fatal

value_or_fatal

一、背景:

      发现网上能搜到的都是几年前的例子,现在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:

  1. #define LOG_NDEBUG 0
  2. #define LOG_TAG "demo_test"
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <cutils/properties.h>
  6. #include <media/AudioSystem.h>
  7. #include <media/AudioTrack.h>
  8. #include <media/AudioRecord.h>
  9. #include <binder/ProcessState.h>
  10. #include <binder/IPCThreadState.h>
  11. #include <media/AidlConversion.h>
  12. #include <utils/Log.h>
  13. #include <fcntl.h>
  14. #include "demo_test.h"
  15. #define SOUND_LENGTH 18470
  16. volatile bool g_bQuitAudioRecordThread = false;
  17. int g_iNotificationPeriodInFrames = 8000/10;
  18. void StartAudioRecordThread();
  19. void StopAudioRecordThread();
  20. void * inBuffer = NULL;
  21. int myreadlen = 0;
  22. int mywritelen = 0;
  23. int bufferSizeInBytes = 1600;
  24. #define SAMPLE_RATE 16000
  25. // 这里必须使用 AUDIO_SOURCE_HOTWORD 否则录音无声,或者把 void AudioFlinger::setRecordSilenced(audio_port_handle_t portId, bool silenced)
  26. //函数注释为空。
  27. audio_source_t inputSource = AUDIO_SOURCE_HOTWORD;//AUDIO_SOURCE_HOTWORD;//AUDIO_SOURCE_MIC;
  28. static const audio_attributes_t pAttributes = {
  29. /* .content_type = */ AUDIO_CONTENT_TYPE_UNKNOWN, // 0
  30. /* .usage = */ (audio_usage_t)AUDIO_USAGE_UNKNOWN, // 0
  31. /* .source = */ inputSource, // 1
  32. /* .flags = */ AUDIO_FLAG_MUTE_HAPTIC,// 0x00000800 //AUDIO_FLAG_NONE,
  33. /* .tags = */ "demo_test"
  34. };
  35. static android::content::AttributionSourceState attributionSource;
  36. namespace android {
  37. void AudioRecordCallback(int event, void* user, void *info)
  38. {
  39. char *p;
  40. if(user)
  41. p = (char *)user;
  42. if(event == android::AudioRecord::EVENT_NEW_POS)
  43. {
  44. ALOGD(" android::AudioRecord::EVENT_NEW_POS \n");
  45. //if(g_iInSampleTime > g_iNotificationPeriodInFrames*100)
  46. // g_bQuitAudioRecordThread = true;
  47. }
  48. else if (event == android::AudioRecord::EVENT_MORE_DATA)
  49. {
  50. ALOGD(" android::AudioRecord::EVENT_MORE_DATA..... \n");
  51. android::AudioRecord::Buffer* pBuff = (android::AudioRecord::Buffer*)info;
  52. pBuff->size = 0;
  53. }
  54. else if (event == android::AudioRecord::EVENT_OVERRUN)
  55. {
  56. ALOGD(" EVENT_OVERRUN \n");
  57. }
  58. }
  59. #if 1
  60. static void AudioRecordThread()
  61. {
  62. audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT; // 1
  63. audio_channel_mask_t channelConfig = AUDIO_CHANNEL_IN_MONO;//AUDIO_CHANNEL_IN_MONO; //AUDIO_CHANNEL_IN_STEREO;
  64. int sampleRateInHz = SAMPLE_RATE;
  65. sp<AudioRecord> pAudioRecord = 0;
  66. FILE * g_pAudioRecordFile = NULL;
  67. char strAudioFile[] = "/sdcard/AudioRecordFile.pcm";
  68. int iNbChannels = 1; // 1 channel for mono, 2 channel for streo
  69. int iBytesPerSample = 2; // 16bits pcm, 2Bytes
  70. int frameSize = 0; // frameSize = iNbChannels * iBytesPerSample
  71. size_t minFrameCount = 0; // get from AudroRecord object
  72. g_pAudioRecordFile = fopen(strAudioFile, "wb+");
  73. iNbChannels = (channelConfig == AUDIO_CHANNEL_IN_STEREO) ? 2 : 1;
  74. frameSize = iNbChannels * iBytesPerSample;
  75. android::status_t status = AudioRecord::getMinFrameCount(
  76. &minFrameCount, sampleRateInHz, audioFormat, channelConfig);
  77. if(status != android::NO_ERROR)
  78. {
  79. ALOGD("%s AudioRecord.getMinFrameCount fail \n", __FUNCTION__);
  80. }
  81. // sampleRateInHz = 16000 minFrameCount = 768 iNbChannels = 2 frameSize = 4
  82. ALOGD("sampleRateInHz = %d minFrameCount = %d iNbChannels = %d frameSize = %d ",
  83. sampleRateInHz, (int)minFrameCount, iNbChannels, frameSize);
  84. bufferSizeInBytes = (int)minFrameCount * frameSize;
  85. //bufferSizeInBytes = 2*SOUND_LENGTH;
  86. g_iNotificationPeriodInFrames = sampleRateInHz/10;
  87. String16 opPackageName("demo_test");
  88. uid_t uid = -1;
  89. pid_t pid = -1;
  90. attributionSource.packageName = VALUE_OR_FATAL(legacy2aidl_String16_string(opPackageName));
  91. attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t((unsigned int)uid));
  92. attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t((int)pid));
  93. attributionSource.token = sp<BBinder>::make();
  94. pAudioRecord = new AudioRecord(attributionSource);
  95. if(NULL == pAudioRecord)
  96. {
  97. ALOGD(" create native AudioRecord failed! ");
  98. }
  99. audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;// 0
  100. audio_session_t sessionId = (audio_session_t)0;
  101. int sharedAudioHistoryMs = 0;
  102. status_t status2 =
  103. pAudioRecord->set(pAttributes.source, sampleRateInHz,
  104. audioFormat, // word length, PCM
  105. channelConfig, 768,
  106. AudioRecordCallback, // callback_t
  107. NULL, // void* user
  108. 0, // notificationFrames,
  109. true, // threadCanCallJava
  110. sessionId, AudioRecord::TRANSFER_DEFAULT, flags, -1,
  111. -1, // default uid, pid
  112. &pAttributes, AUDIO_PORT_HANDLE_NONE, MIC_DIRECTION_UNSPECIFIED,
  113. MIC_FIELD_DIMENSION_DEFAULT, sharedAudioHistoryMs);
  114. if (status2 != NO_ERROR) {
  115. ALOGE("Error creating AudioRecord instance: initialization check failed with status2 %d.",
  116. status2);
  117. }
  118. pAudioRecord->setCallerName("demo_test");
  119. if(pAudioRecord->initCheck() != android::NO_ERROR)
  120. {
  121. ALOGD("AudioTrack initCheck error!");
  122. }
  123. if(pAudioRecord->setPositionUpdatePeriod(g_iNotificationPeriodInFrames) != android::NO_ERROR)
  124. {
  125. ALOGD("AudioTrack setPositionUpdatePeriod error!");
  126. }
  127. if(pAudioRecord->start()!= android::NO_ERROR)
  128. {
  129. ALOGD("AudioTrack start error!");
  130. }
  131. int i = 0;
  132. int readLen = 0;
  133. while (!g_bQuitAudioRecordThread)
  134. {
  135. readLen = pAudioRecord->read((uint8_t*)inBuffer+i*readLen, 320/*bufferSizeInBytes*/, 1);
  136. int writeResult = -1;
  137. if(readLen > 0)
  138. {
  139. myreadlen += readLen;
  140. if ( myreadlen > 7*SOUND_LENGTH ) {
  141. ALOGD("pAudioRecord->read end");
  142. break;
  143. }
  144. //iWriteDataCount += readLen;
  145. if(NULL != g_pAudioRecordFile)
  146. {
  147. writeResult = fwrite((uint8_t*)inBuffer+i*readLen, 1, readLen, g_pAudioRecordFile);
  148. if(writeResult < readLen)
  149. {
  150. ALOGE("Write Audio Record Stream error");
  151. }
  152. mywritelen += writeResult;
  153. }
  154. i++;
  155. }
  156. else
  157. {
  158. ALOGD("pAudioRecord->read readLen = 0");
  159. }
  160. }
  161. ALOGD("myreadlen = %d mywritelen = %d\n", myreadlen, mywritelen);
  162. if(pAudioRecord)
  163. {
  164. pAudioRecord->stop();
  165. }
  166. if(NULL != g_pAudioRecordFile)
  167. {
  168. fflush(g_pAudioRecordFile);
  169. fclose(g_pAudioRecordFile);
  170. g_pAudioRecordFile = NULL;
  171. }
  172. }
  173. #endif
  174. /************************************************************
  175. *
  176. * Constructor
  177. *
  178. ************************************************************/
  179. AudioTrackTest::AudioTrackTest(void) {
  180. ALOGD("01 AudioTrackTest\n");
  181. }
  182. /************************************************************
  183. *
  184. *
  185. ************************************************************/
  186. void AudioTrackTest::Execute(void) {
  187. if (Test01() == 0) {
  188. ALOGD("01 passed\n");
  189. } else {
  190. ALOGD("01 failed\n");
  191. }
  192. }
  193. /************************************************************
  194. *
  195. * Shared memory test
  196. *
  197. ************************************************************/
  198. #define BUF_SZ 44100
  199. int AudioTrackTest::Test01() {
  200. bufferSizeInBytes = 10*SOUND_LENGTH;
  201. inBuffer = malloc(bufferSizeInBytes);
  202. if(inBuffer == NULL)
  203. {
  204. ALOGD("%s alloc mem failed \n", __FUNCTION__);
  205. }
  206. memset(inBuffer, 0, bufferSizeInBytes);
  207. uint8_t* buf = (uint8_t*)inBuffer;
  208. long sampleRate = SAMPLE_RATE;
  209. size_t framecount = 16;
  210. AudioRecordThread();
  211. if (AudioTrack::getMinFrameCount(&framecount, AUDIO_STREAM_MUSIC, sampleRate) != NO_ERROR ) {
  212. ALOGD("Error: cannot compute output frame count\n");
  213. return -1;
  214. }
  215. ALOGD("framecount = %d \n", (int)framecount);
  216. sp<AudioTrack> track = new AudioTrack(AUDIO_STREAM_MUSIC,// stream type
  217. sampleRate,
  218. AUDIO_FORMAT_PCM_16_BIT,// word length, PCM
  219. AUDIO_CHANNEL_OUT_MONO, // AUDIO_CHANNEL_OUT_STEREO
  220. 0);
  221. status_t status = track->initCheck();
  222. if(status != NO_ERROR) {
  223. track.clear();
  224. ALOGD("Failed for initCheck()");
  225. return -1;
  226. }
  227. // start play
  228. ALOGD("start");
  229. track->start();
  230. for(int j = 0; j < 3; j++)
  231. for(int i = 0; i <= 7*SOUND_LENGTH/320 ; i++){
  232. track->write(buf+i*320, 320, 1);
  233. }
  234. ALOGD("stop");
  235. track->stop();
  236. if(inBuffer)
  237. {
  238. free(inBuffer);
  239. inBuffer = NULL;
  240. }
  241. return 0;
  242. }
  243. /************************************************************
  244. *
  245. * main in name space
  246. *
  247. ************************************************************/
  248. int main() {
  249. ProcessState::self()->startThreadPool();
  250. AudioTrackTest *test;
  251. test = new AudioTrackTest();
  252. test->Execute();
  253. delete test;
  254. return 0;
  255. }
  256. }
  257. /************************************************************
  258. *
  259. * global main
  260. *
  261. ************************************************************/
  262. int main() {
  263. return android::main();
  264. }

demo_test.h

  1. // Copyright 2008 The Android Open Source Project
  2. #ifndef AUDIOTRACKTEST_H_
  3. #define AUDIOTRACKTEST_H_
  4. namespace android {
  5. class AudioTrackTest{
  6. public:
  7. AudioTrackTest(void);
  8. ~AudioTrackTest() {};
  9. void Execute(void);
  10. int Test01();
  11. };
  12. };
  13. #endif /*AUDIOTRACKTEST_H_*/

Android.bp

  1. cc_test {
  2. name: "demo_test",
  3. gtest: false,
  4. srcs: ["demo_test.cpp"],
  5. shared_libs: [
  6. "liblog",
  7. "libcutils",
  8. "libutils",
  9. "libbinder",
  10. "libhardware_legacy",
  11. "libmedia",
  12. "libaudioclient",
  13. "libaudioclient_aidl_conversion",
  14. ],
  15. header_libs: [
  16. "libmediametrics_headers",
  17. ],
  18. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/499818
推荐阅读
相关标签
  

闽ICP备14008679号