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语言操作mysql
php中 mysqli, pdo 可以用 mysqlnd 或 libmysqlclient 实现 前者 从 php 5.3.0起已内置到php中, 并且支持更多的特性,推荐用 mysqlnd mysq ...
- css绝对定位问题
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- X-Cart 学习笔记(三)X-Cart框架2
目录 X-Cart 学习笔记(一)了解和安装X-Cart X-Cart 学习笔记(二)X-Cart框架1 X-Cart 学习笔记(三)X-Cart框架2 X-Cart 学习笔记(四)常见操作 3.了解 ...
- NHibernate系列文章六:NHibernate数据类型映射
摘要 NHibernate支持所有的数据库数据类型. 以SQL Server数据库为例,下表是NHibernate支持的SQL Server数据库最常见的数据类型对照表. 第一列是NHibernate ...
- NHibernate系列文章九:NHibernate对象二级缓存上
摘要 NHibernate的二级缓存由SessionFactory管理,由所有Session共享. NHibernate缓存读取顺序: 首先从一级缓存中读取,如果一级缓存对象存在,则读取一级缓存对象并 ...
- Egret版本更新(H5增加版本号)
由于浏览器缓存问题.在服务器上更新了新的图片等资源以后,客户端并不会下载最新的. 关于浏览器缓存机制,可自行百度. Egret中资源更新解决方案有以下: 一 资源名后增加版本号 二 重写Egret引擎 ...
- java并发库_并发库知识点整理
并发库(java.util.concurrent)中的工具数不胜数,那么我们梳理一下线程并发库中重要的一些常用工具: 1.
- java GZIP压缩和解压
最近碰到了一个按GZIP解压指定的输入流数据,备份下 import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream ...
- Asp.net using Oracle.DataAccess.dll access oracle 11g 64bit & x86
使用.net访问oracle数据库时一般需要在机器上安装instantclient才能正常连接. 下面介绍一种不用安装instantclient直接引用dll就用.net能连接oracle数据库的方法 ...
- 现成的HTML5框架
1>sencha-touch 2>phoneGap 3>jQuery mobile 4>bootstrap