一般情况下录音实现的简单流程如下:
- 创建一个数据流。
- 构造一个AudioRecord对象,其中需要的最小录音缓存buffer大小可以通过getMinBufferSize方法得到。如果buffer容量过小,将导致对象构造的失败。
- 初始化一个buffer,该buffer大于等于AudioRecord对象用于写声音数据的buffer大小。
- 开始录音。
- 从AudioRecord中读取声音数据到初始化buffer,将buffer中数据导入数据流。
- 停止录音。
- 关闭数据流。
Java在创建AudioRecord对象时,会调用native_setup函数,对应native层C++ 中AudioRecord对象调用set
AudioRecord pAudioRecord = new android::AudioRecord();
pAudioRecord->set( inputSource,//并不是资源,实际上是一个定义的枚举;
sampleRateInHz,//样本采样频率
audioFormat,//采样精度PCM8,PCM16
channelConfig,//指定声道数
minFrameCount,
AudioRecordCallback,//回调
NULL,
0,
true,
0,
android::AudioRecord::TRANSFER_DEFAULT,
AUDIO_INPUT_FLAG_NONE, //AUDIO_INPUT_FLAG_NONE //audio_input_flags_t flags);
NULL
);
inputSource 的类型定义:
typedef enum {
AUDIO_SOURCE_DEFAULT = 0,
AUDIO_SOURCE_MIC = 1,
AUDIO_SOURCE_VOICE_UPLINK = 2,
AUDIO_SOURCE_VOICE_DOWNLINK = 3,
AUDIO_SOURCE_VOICE_CALL = 4,
AUDIO_SOURCE_CAMCORDER = 5,
AUDIO_SOURCE_VOICE_RECOGNITION = 6,
AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
AUDIO_SOURCE_REMOTE_SUBMIX = 8, / Source for the mix to be presented remotely. /
/ An example of remote presentation is Wifi Display /
/ where a dongle attached to a TV can be used to /
/ play the mix captured by this audio source. /
AUDIO_SOURCE_CNT,
AUDIO_SOURCE_MAX = AUDIO_SOURCE_CNT - 1,
AUDIO_SOURCE_HOTWORD = 1999, / A low-priority, preemptible audio source for
for background software hotword detection.
Same tuning as AUDIO_SOURCE_VOICE_RECOGNITION.
Used only internally to the framework. Not exposed
at the audio HAL. */
} audio_source_t;
在set函数完成三件事:1:进行配置的check;2:获取音频输入操作句柄;3:调用AudioFlinger(AF)处理音频。在openRecord_l()函数创建一个IAudioRecord。
- 2: 调用AudioSystem的方法 与AudioPolicyService跨进程通信
state = AudioSystem::getInputForAttr(&Attr, &input,,,,,,);
//传入input地址,相当于回调,在执行函数的时候将相应数据写入该地址
status_t AudioSystem::getInputForAttr(&Attr, &input,,,,,,){
const sp<IAudioPolicyService>& aps = AudioSystem::getInputForAttr(&Attr, &input,,,,,,);
...
}
//在AudioPolicyInterfaceImpl.cpp里
status_t AudioPolicyService::getInputForAttr(&Attr, &input,,,,,,){
...
return AudioPolicyManager->getInputForAttr(&Attr, &input,,,,,,);
}
在getInputForAttr() ,IAudioPolicyService与AudioPolicyService的实现类AudioPolicyInterfaceImpl进行通信,从而调用到了AudioPolicyManager的getInputForAttr().=>....大致我理解的这部分内容所做的,将传入的input作为key与device传入的mInput进行match,确定输入设备
- 3: AudioRecord与AudioFlinger跨进程通信,创建Bp:IAudioFlinger 命名为audioFlinger.
sp<IAudioRecord> record = audioFlinger->openRecord(input,.....);
//把上面获取的输入句柄input传给AF,以便与在AF中打开输入句柄,在AudioFlinger::openInput中的代码片段,通过音频硬件得到一个音频输入流,接着创建录音线程,并将其添加到录音线程列表中
AudioFlinger::openRecord(input,....){
sp<RecordHanle> recordHandle;
...
//创建RecordTrack
recordTrack = thread ->createRecordTrack_l(input);
//RecordTrack是AF的内部类,开辟了一块共享内存,它的头部是控制块ControlBlock(CB)(audio_track_cblk_t)后面的是缓冲内存,类似与Track,
//该函数返回一个IAudioRecord用于AR 对该内存进行跨进程操作
...
//创建RecordHandle
recordHandle = new RecordHandle(recordTrack);
return recordHandle;
}
这里使用proxy模式,AF返回AR一个RecordHandle,这个RecordHandle以RecordTrack为参数构造。这样一来虽然RecordTrack不能进行基于Binder的通信,但是RecordHandle可以接受远处端的进程请求,然后调用Track的相应函数。RecordHandle是RecordTrack的代理。
将RecordHandle返回给AR之后,AR的 start,stop函数都是通过CB与后面数据缓冲完成数据传递(最终通过memcpy)。
AudioSystem是Audio子系统面向framework层的接口,有AF,AudioPolicyService(APS)的Bn端,也有Bp端。(简单介绍一下:Binder通信,Bp端向ServiceManager(句柄为0)获取Bn端的句柄,通过句柄找到Bn端,通过Binder通信让Bn端做事)
具体看图