1 简述
Audio 是Android 一个重要组成部分, 它主要包括三个方面:
1 Audio Recorder和Audio Track: 提供对外的API,完成Android 平台audio 数据采集和输出任务。
2 AudioFlinger: 承担音频数据的混音,以及读写audio 硬件等工作以实现数据的输入输出
3 AudioPolicyService:它是Audio 系统的策略控制中心,具体掌管系统中声音设备的选择和切换,音量控制等功能。
2 AudioTrack 使用
关于AudioTrack 有两种数据加载模式:1 MODE_STREAM:将数据一步一步的通过write() 写入,长的音频都是这种模式;2 MODE_STATIC:将数据一次写入,适合于短的铃声。
//相关函数在audioTrack.java 中
//step 1:根据音频数据特定, 确定所需分配的最小buffer
int bufsize = AudioTrack.getMinBufferSize(sampleRate,AudioFormat.CHANNEL_CONFIGURATIO_STEREO,AudioFormat.ENODING_PCM_16BIT);
...
//step 2: 创建audioTrack,需要传入audio type,采样率,声道,采样位数,buffsize,数据加载模式
AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,sampleRate,AudioFormat.CHANNEL_CONFIGURATION_STEREO,AudioFormat.ENCODING_PCM_16BIT,buffsize,AudioTrack.MODE_STREAM);
...
track.play(); //step 3:播放
track.write(); //step 4:写数据
track.stop(); //step 5: 停止播放
track.release(); //step 6: 释放资源
3 AudioTrack(java空间)
AudioTrack构造函数的实现在AudioTrack.java 中,往下call 到JNI , 到Android_media_AudioTrack.cpp。 audioTrack java 到JNI 这段,函数逻辑很简单,大部分逻辑都是在native 层实现的。
4 AudioTrack(Native 空间)
1 new AudioTrack 和set() 分析
AudioTrack::AudioTrack() //无参构造函数
{
//比较简单,把状态初始化成NO_INIT,Andriod 的很多类都采用这种状态控制。
}
status AudioTrack::set(int streamType, uint32_t sampleRate, int format...)
{
.....
audio_io_handle_t output = AudioSystem::getOutput();//这个output 值非常重要,用来表示工作线程索引号,audioFlinger会根据这个值创建几个工作线程。
....
status_t status = createTrack();//这函数往下call 到audioFlinger ,详情往下看
...
if(cbf != 0) //如果设置了回调函数,则启动一个线程,主动从用户那个pull 数据,不然主动write push 数据
{
mAudioTrackTread = new AudioTrackTread()
}
}
status AudioTrack::creatTrack(int streamType ...)
{
...
const sp<IAudioFlinger> &audioFlinger = AudioSystem::get_audio_flinger();//得到AudioFlinger 的binder 代理端bpAudioFlinger
/*IAudioTrack 是联系AT 和 AF 的关键纽带,在IAudioTrack 中有一块共享内存,其头部是audio_track_cblk_t, 通过它协调和管理AT 和 AF 间数据生产和消费
sp<IAudioTrack> track = AuidoFlinger->createTrack();
}
2 pull 与 push mode
在pull mode 下
bool AudioTrack::processAudioBuffer()
{
...
status_t err = obtainBuffer();//从CB那里得到一块可写的缓冲
mCbf(EVENT_MORE_DATA,mUserData,&audioBuffer);//从用户那里pull 数据
releaseBuffer();//更新写位置,同时会触发消费者
...
}
在push mode 下:
size_t AudioTrack::write()
{
...
status err = obtainBuffer(&audioBuffer,-1);
memcpy(aoudioBuffer.i8,src,toWrite);
releaseBuffer(&audioBuffer);
...
}