赞
踩
发现网上能搜到的都是几年前的例子,现在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录音没有声音。
例子有点乱,没有整理。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; // 1
- audio_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 streo
- int iBytesPerSample = 2; // 16bits pcm, 2Bytes
- int frameSize = 0; // frameSize = iNbChannels * iBytesPerSample
- size_t minFrameCount = 0; // get from AudroRecord object
-
- g_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 = 4
- ALOGD("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;// 0
-
- audio_session_t sessionId = (audio_session_t)0;
- int sharedAudioHistoryMs = 0;
- status_t status2 =
- pAudioRecord->set(pAttributes.source, sampleRateInHz,
- audioFormat, // word length, PCM
- channelConfig, 768,
- AudioRecordCallback, // callback_t
- NULL, // void* user
- 0, // notificationFrames,
- true, // threadCanCallJava
- sessionId, 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 44100
-
- int 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 type
- sampleRate,
- AUDIO_FORMAT_PCM_16_BIT,// word length, PCM
- AUDIO_CHANNEL_OUT_MONO, // AUDIO_CHANNEL_OUT_STEREO
- 0);
-
- status_t status = track->initCheck();
- if(status != NO_ERROR) {
- track.clear();
- ALOGD("Failed for initCheck()");
- return -1;
- }
-
- // start play
- ALOGD("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",
- ],
-
- }
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。