Android音频系统之AudioFlinger(四)【转】

Android音频系统之AudioFlinger(四)

分类: ALSA/Audio 2014-06-12 17:37 195人阅读 评论(0) 收藏 举报

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是如何处理音频数据的,我们将在后续音频流小节做统一分析。

时间: 2024-11-04 17:18:41

Android音频系统之AudioFlinger(四)【转】的相关文章

Android音频系统之AudioFlinger(一)【转】

1.1 AudioFlinger 在上面的框架图中,我们可以看到AudioFlinger(下面简称AF)是整个音频系统的核心与难点.作为Android系统中的音频中枢,它同时也是 一个系统服务,启到承上(为上层提供访问接口)启下(通过HAL来管理音频设备)的作用.只有理解了AudioFlinger,才能以此为基础更好地深入 到其它模块,因而我们把它放在前面进行分析. 1.1.1 AudioFlinger服务的启动和运行 我们知道,Android中的系统服务分为两类,分别是Java层和Native

Android音频系统之AudioFlinger(一)

http://blog.csdn.net/xuesen_lin/article/details/8805068 1.1 AudioFlinger 在上面的框架图中,我们可以看到AudioFlinger(下面简称AF)是整个音频系统的核心与难点.作为Android系统中的音频中枢,它同时也是一个系统服务,启到承上(为上层提供访问接口)启下(通过HAL来管理音频设备)的作用.只有理解了AudioFlinger,才能以此为基础更好地深入到其它模块,因而我们把它放在前面进行分析. 1.1.1 Audio

Android音频系统之AudioFlinger(二) 【转】

1.1.1 音频设备的管理 虽然AudioFlinger实体已经成功创建并初始化,但到目前为止它还是一块静态的内存空间,没有涉及到具体的工作. 从职能分布上来讲,AudioPolicyService是策略的制定者,比如什么时候打开音频接口设备.某种Stream类型的音频对应什么设备等等.而AudioFlinger则是策略的执行者,例如具体如何与音频设备通信,如何维护现有系统中的音频设备,以及多个音频流的混音如何处理等等都得由它来完成. 目前Audio系统中支持的音频设备接口(Audio Inte

Android音频系统之AudioFlinger(二)

1.1.1 音频设备的管理 虽然AudioFlinger实体已经成功创建并初始化,但到目前为止它还是一块静态的内存空间,没有涉及到具体的工作. 从职能分布上来讲,AudioPolicyService是策略的制定者,比如什么时候打开音频接口设备.某种Stream类型的音频对应什么设备等等.而AudioFlinger则是策略的执行者,例如具体如何与音频设备通信,如何维护现有系统中的音频设备,以及多个音频流的混音如何处理等等都得由它来完成. 目前Audio系统中支持的音频设备接口(Audio Inte

Android音频系统之AudioFlinger(三) 【转】

1.1.1 PlaybackThread的循环主体 当一个PlaybackThread进入主循环后(threadLoop),音频事务就正式开启了.仔细观察的话,我们会发现这个循环中会不断地调用以 “threadLoop_”开头的若干接口,比如threadLoop_mix.threadLoop_sleepTime. threadLoop_standby等等.以这样的前缀开头,是因为这些函数都是在threadLoop这个主体里被调用的,可以说代表了这个 PlaybackThread所需要完成的各个操

Android 音频系统:从 AudioTrack 到 AudioFlinger

1. Android 音频框架概述 Audio 是整个 Android 平台非常重要的一个组成部分,负责音频数据的采集和输出.音频流的控制.音频设备的管理.音量调节等,主要包括如下部分: Audio Application Framework:音频应用框架 AudioTrack:负责回放数据的输出,属 Android 应用框架 API 类 AudioRecord:负责录音数据的采集,属 Android 应用框架 API 类 AudioSystem: 负责音频事务的综合管理,属 Android 应

Android音频系统之音频框架

http://blog.csdn.net/xuesen_lin/article/details/8796492 我们可以结合目前已有的知识,想一下每一个层次都会包含哪些模块(先不考虑蓝牙音频部分)? ·        APP 这是整个音频体系的最上层,因而并不是Android系统实现的重点.比如厂商根据特定需求自己写的一个音乐播放器,游戏中使用到声音,或者调节音频的一类软件等等. ·        Framework 相信大家可以马上想到MediaPlayer和MediaRecorder,因为这

Android音频系统之音频框架(转http://blog.csdn.net/uiop78uiop78/article/details/8796492)

1.1 音频框架 转载请注明,From LXS, http://blog.csdn.net/uiop78uiop78/article/details/8796492 Android的音频系统在很长一段时间内都是外界诟病的焦点.的确,早期的Android系统在音频处理上相比于IOS有一定的差距,这也是很多专业的 音乐播放软件开发商没有推出Android平台产品的一个重要原因.但这并不代表它的音频框架一无是处,相反,基于Linux系统的Android平台有 很多值得我们学习的地方. 1.1.1 Li

Android音频系统之AudioTrack(一) 【转】

1.1 AudioTrack 1.1.1 AudioTrack应用实例 对于Android应用开发人员来讲,音频回放最熟悉的莫过于MediaPlayer,而AudioTrack相信用的人相对会少很多.这是因为 MediaPlayer提供了更完整的封装和状态控制,使得我们用很少的代码就可以实现一个简单的音乐播放器.而相比MediaPlayer,AudioTrack更为精练.高效,实际上MediaPlayerService的内部实现就是使用了AudioTrack. AudioTrack被用于PCM音