Android音频系统之AudioFlinger(四)
http://blog.csdn.net/xuesen_lin/article/details/8805096
1.1.1 AudioMixer
每一个MixerThread都有一个唯一对应的AudioMixer(在MixerThread中用mAudioMixer表示),它的作用如其名所表示的,就是为了完成音频的混音操作。
图 13‑14 MixerThread示意图
如上图,MixerThread对外开放的接口主要涉及到Parameter(比如setParameter)、Resampler(比如setResampler)、Volume(比如adjustVolumeRamp)、Buffer(比如setBufferProvider)及Track(比如getTrackName)五个部分。
在内部的实现中,MixerThread的核心是一个mState变量(state_t类型),所有的混音工作都会在这个变量中体现出来——特别是其中的tracks数组,如下所示:
struct state_t {
uint32_t enabledTracks;
uint32_t needsChanged;
size_t frameCount;
void (*hook)(state_t* state, int64_tpts); // one of process__*, never NULL
int32_t *outputTemp;
int32_t *resampleTemp;
int32_t reserved[2];
track_t tracks[MAX_NUM_TRACKS];__attribute__((aligned(32)));
};
MAX_NUM_TRACKS=32,也就是说最多支持32路同时混音,这对于大部分情况肯定是足够了。数据类型track_t是对每个Track的描述,可想而知类似Parameter这种设置,最终影响的就是Track的属性。
struct track_t {
…
union {
int16_t volume[MAX_NUM_CHANNELS];
int32_t volumeRL;
};//音量相关的属性
int32_t prevVolume[MAX_NUM_CHANNELS];
int32_t volumeInc[MAX_NUM_CHANNELS];
…
uint8_t channelCount; //只能是1或2
uint8_t format; // 总是16
uint16_t enabled; // 实际是布尔类型
audio_channel_mask_t channelMask;
AudioBufferProvider* bufferProvider;
mutableAudioBufferProvider::Buffer buffer; // 8 bytes
hook_t hook;
const void* in; //buffer中的当前位置
AudioResampler* resampler;
uint32_t sampleRate;
int32_t* mainBuffer;
int32_t* auxBuffer;
…
bool setResampler(uint32_t sampleRate,uint32_t devSampleRate);
bool doesResample() const { return resampler!= NULL; }
void resetResampler() { if (resampler !=NULL) resampler->reset(); }
void adjustVolumeRamp(bool aux);
size_t getUnreleasedFrames() const { return resampler != NULL ?resampler->getUnreleasedFrames() : 0; };
};
AudioFlinger的threadLoop中,通过不断调用prepareTracks_l来准备数据,而每次prepare实际上都是对所有Track的一次调整。如果属性有变化,就会通过setParamter来告知AudioMixer。
在上一个小节中,threadLoop_mix在内部就是通过AudioMixer来实现混音的,我们这里具体来看下:
void AudioMixer::process(int64_t pts)
{
mState.hook(&mState,pts);
}
“hook”是钩子的意思,为什么取这个名字?一个原因可能是hook指向的实体是变化的,就好像钩子一样,它可以灵活的依附于各种物体之上。从代码层面上看,hook是一个函数指针,它根据当前具体情况会分别指向以下几个函数实现:
process__validate:根据当前具体情况,将hook导向下面的几个实现
process__nop:初始化值
process__OneTrack16BitsStereoNoResampling:只有一路Track,16比特立体声,不重采样
process__genericNoResampling:两路(包含)以上Track,不重采样
process__genericResampling:两路(包含)以上Track,重采样
hook在以下几种情况下会重新赋值
Ø AudioMixer初始化时,hook指向process_nop
Ø 当状态改变或者参数变化时(比如setParameter),调用invalidateState。此时hook指向process__validate
Ø AudioMixer::process是外部调用hook的入口
我们以下面的图来描述一下,大家会看得更清楚些:
图 13‑15 hook的使用
其中process_validate的代码实现如下:
void AudioMixer::process__validate(state_t* state, int64_t pts)
{ …
int countActiveTracks = 0;
boolall16BitsStereoNoResample = true;
bool resampling = false;…
uint32_t en =state->enabledTracks;
while (en) {
const int i = 31 -__builtin_clz(en);
en &= ~(1<<i);
countActiveTracks++;//enabled 状态的Track计数
…
}
state->hook = process__nop;
if (countActiveTracks) {
if (resampling) {
…
state->hook = process__genericResampling;
} else {
…
state->hook = process__genericNoResampling;
if(all16BitsStereoNoResample && !volumeRamp) {
if(countActiveTracks == 1) {
state->hook = process__OneTrack16BitsStereoNoResampling;
}
}
}
}
state->hook(state, pts);
…
}
这个函数先通过while循环逐个分析处于enabled状态的Track,统计其内部各状态位(比如NEEDS_AUX__MASK、NEEDS_RESAMPLE__MASK等等)情况,得出countActiveTracks、resampling、volumeRamp及all16BitsStereoNoResample的合理值,最后根据这几个变量判断选择正确的hook实现,并调用这个hook函数执行具体工作。
关于AudioMixer是如何处理音频数据的,我们将在后续音频流小节做统一分析。
Android音频系统之AudioFlinger(四)的更多相关文章
- Android音频系统之AudioFlinger(一)
1.1 AudioFlinger 在上面的框架图中,我们可以看到AudioFlinger(下面简称AF)是整个音频系统的核心与难点.作为Android系统中的音频中枢,它同时也是一个系统服务,启到承上 ...
- Android音频系统之AudioFlinger(二)
1.1.1 音频设备的管理 虽然AudioFlinger实体已经成功创建并初始化,但到目前为止它还是一块静态的内存空间,没有涉及到具体的工作. 从职能分布上来讲,AudioPolicyService是 ...
- Android音频系统之AudioFlinger(三)
http://blog.csdn.net/xuesen_lin/article/details/8805091 1.1.1 PlaybackThread的循环主体 当一个PlaybackThread进 ...
- Android音频系统之音频框架
1.1 音频框架 转载请注明,From LXS, http://blog.csdn.net/uiop78uiop78/article/details/8796492 Android的音频系统在很长一段 ...
- 转:ANDROID音频系统散记之四:4.0音频系统HAL初探
昨天(2011-11-15)发布了Android4.0的源码,今天download下来,开始挺进4.0时代.简单看了一下,发现音频系统方面与2.3的有较多地方不同,下面逐一描述. 一.代码模块位置 1 ...
- Android音频系统之AudioPolicyService
地址:http://blog.csdn.net/edmond999/article/details/18599327 1.1 AudioPolicy Service 在AudioFlinger小节,我 ...
- Android音频系统
1 分析思路 Thread如何创建? AudioPolicyService是策略的制定者,AudioFlinger是策略的执行者, 所以: AudioPolicyService根据配置文件使唤Audi ...
- Android 音频系统得框架
http://www.mamicode.com/info-detail-1790053.html http://blog.csdn.net/lushengchu_luis/article/detail ...
- Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理
Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理 1. 回顾 我们知道Android输入系统是Reader线程通过驱动程序得到上报的输入事件,还要经过处理 ...
随机推荐
- C++模板元编程 - 挖新坑的时候探索到了模板元编程的新玩法
C++真是一门自由的语言,虽然糖没有C#那么多,但是你想要怎么写,想要实现什么,想要用某种编程范式或者语言特性,它都会提供. 开大数运算类的新坑的时候(又是坑),无意中需要解决一个需求:大数类需要分别 ...
- mac配置impala odbc
下载mac对应驱动并安装:http://www.cloudera.com/downloads.html.html *HOST 地址是impala Daemon所在的机器ip,端口可以在cm中设置 vi ...
- 1. Longest Palindromic Substring ( 最长回文子串 )
要求: Given a string S, find the longest palindromic substring in S. (从字符串 S 中最长回文子字符串.) 何为回文字符串? A pa ...
- windows下使用VS2010编译jpeglib
1.下载源代码下载地址:http://www.ijg.org/files/, 选择最新版本的windows版本压缩包,进行下载. jpegsr9a.zip 1042 Kb Su ...
- 安卓处理原始XML文件
// 获取XML文档(Parser:剖析器) XmlResourceParser parser = getResources().getXml(R.xml.person); try { // 文档未完 ...
- 9. Linux远程登录
1. 检查网络是否通畅 C:\Users\cfm>ping 192.168.232.131 正在 Ping 192.168.232.131 具有 32 字节的数据:来自 192.168.232. ...
- org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'PUT' not supported
1:先上控制台报错信息 org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'PUT' not ...
- bash操作小结
刚开始学写bash脚本,发现有很多需要注意的细节问题,在这里记录一下便于记忆: 1. help test 帮助 2. bash提供的数组数据结构,它是以数字为下标的,和C语言从0开始的下一样 参考 ...
- js方法之间的调用之——传参方法
在最近项目需求中发现,完成一些功能的时候总是要调很多结构类似的方法,写起来很繁琐,所以就想写一个“万能”方法,是的代码更简洁.即:把一个方法作为参数传给这个“万能”方法,让它去执行你给定的方法,就类似 ...
- webview中的页面兼容iphone6和6+
其实写这篇文章的本不该是我,而应该是开发ios的小伙伴,但作为一个前端,我想我还是有必要做一下记录的! 首先我想说下在iphone6或者6+中webview内嵌套的页面宽度已经不在是320px,而是3 ...