Android Framework的音频子系统中,每一个音频流对应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到AudioFlinger中,由AudioFlinger把所有的AudioTrack进行混合(Mixer),然后输送到AudioHardware中进行播放,目前Android的Froyo版本设定了同时最多可以创建32个音频流,也就是说,Mixer最多会同时处理32个AudioTrack的数据流。
如何使用AudioTrack
AudioTrack的主要代码位于 frameworks\base\media\libmedia\audiotrack.cpp中。现在先通过一个例子来了解一下如何使用AudioTrack,ToneGenerator是android中产生电话拨号音和其他音调波形的一个实现,我们就以它为例子:
ToneGenerator的初始化函数:
- bool ToneGenerator::initAudioTrack() {
-
- mpAudioTrack = new AudioTrack();
- mpAudioTrack->set(mStreamType,
- 0,
- AudioSystem::PCM_16_BIT,
- AudioSystem::CHANNEL_OUT_MONO,
- 0,
- 0,
- audioCallback,
- this,
- 0,
- 0,
- mThreadCanCallJava);
- if (mpAudioTrack->initCheck() != NO_ERROR) {
- LOGE("AudioTrack->initCheck failed");
- goto initAudioTrack_exit;
- }
- mpAudioTrack->setVolume(mVolume, mVolume);
- mState = TONE_INIT;
- ......
- }
可见,创建步骤很简单,先new一个AudioTrack的实例,然后调用set成员函数完成参数的设置并注册到AudioFlinger中,然后可以调用其他诸如设置音量等函数进一步设置音频参数。其中,一个重要的参数是audioCallback,audioCallback是一个回调函数,负责响应AudioTrack的通知,例如填充数据、循环播放、播放位置触发等等。回调函数的写法通常像这样:
- void ToneGenerator::audioCallback(int event, void* user, void *info) {
- if (event != AudioTrack::EVENT_MORE_DATA) return;
- AudioTrack::Buffer *buffer = static_cast(info);
- ToneGenerator *lpToneGen = static_cast(user);
- short *lpOut = buffer->i16;
- unsigned int lNumSmp = buffer->size/sizeof(short);
- const ToneDescriptor *lpToneDesc = lpToneGen->mpToneDesc;
- if (buffer->size == 0) return;
-
-
- memset(lpOut, 0, buffer->size);
- ......
-
- }
该函数首先判断事件的类型是否是EVENT_MORE_DATA,如果是,则后续的代码会填充相应的音频数据后返回,当然你可以处理其他事件,以下是可用的事件类型:
- enum event_type {
- EVENT_MORE_DATA = 0,
- EVENT_UNDERRUN = 1,
- EVENT_LOOP_END = 2,
- EVENT_MARKER = 3,
- EVENT_NEW_POS = 4,
- EVENT_BUFFER_END = 5
- };
开始播放:
停止播放:
只要简单地调用成员函数start()和stop()即可。
AudioTrack和AudioFlinger的通信机制
通常,AudioTrack和AudioFlinger并不在同一个进程中,它们通过android中的binder机制建立联系。
AudioFlinger是android中的一个service,在android启动时就已经被加载。下面这张图展示了他们两个的关系:
图一 AudioTrack和AudioFlinger的关系
阅读(993) | 评论(0) | 转发(0) |