文章大致内容介绍
本文主要讲述播放音乐流程,AudioResampler是如何生效的
- 播放流程
- AudioMixer分析
- 从MixerThread分析
播放流程
在Android中间,如果使用硬解码OffloadThread是不会出现混频和重采样的,但是播放需要软解的音频,则会按需要重采样。
为了方便研究,这里修改软件配置文件,让primary compress_offload仅仅支持8000的采样率播放,音乐播放会去跑MixerThread线程,这个线程上面才会出现重采样。
configs/msm8909/audio_policy_configuration.xml修改如下:
@@ -69,7 +69,7 @@
- samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ samplingRates="8000"
channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
使用播放流程如下:
AudioMixer分析:
我们从log出发,查看代码调用流程
AudioMixer: add track (0)
AudioMixer::prepareForDownmix(0xb4f7d060) with mask 0x3
AudioMixer::prepareForReformat(0xb4f7d060) with format 0x1
AudioMixer: enable(0) AudioMixer: setParameter(VOLUME, VOLUME0: 0000)
AudioMixer: setParameter(VOLUME, VOLUME1: 0000)
AudioMixer: Creating resampler from track 44100 Hz to device 48000 Hz
AudioResampler: resampler load 0 -> 6 MHz due to delta +6 MHz from quality 6
AudioResampler: Create dynamic Resampler = 6
AudioMixer: setParameter(RESAMPLE, SAMPLE_RATE, 44100) AudioMixer: setParameter(TRACK, MIXER_FORMAT, 0x5) AudioMixer: setParameter(TRACK, MAIN_BUFFER, 0xb4f7a000) AudioMixer: mixer configuration change: 1
AudioMixer:activeTracks (00000001) all16BitsStereoNoResample=0, resampling=1, volumeRamp=0
AudioMixer: track__Resample
这段log的调用流程
1,AudioFlinger::MixerThread::checkForNewParameter_l,
2,AudioFlinger::MixerThread::getTrackName_l
3, AudioMixer::getTrackName(audio_channel_mask_t
channelMask,audio_format_t format, int sessionId)
4,调用prepare处理
prepareForDownmix这个函数,是用来处理多通道,将多通道转化,按照条件选择DownMixer或者Remixer,函数如下:
status_t AudioMixer::track_t::prepareForDownmix()
{
ALOGV("AudioMixer::prepareForDownmix(%p) with mask 0x%x",
this, channelMask);
unprepareForDownmix();
if (channelMask == mMixerChannelMask
|| (channelMask == AUDIO_CHANNEL_OUT_MONO
&& mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO)) {
return NO_ERROR;
}
if (audio_channel_mask_get_representation(channelMask)
== AUDIO_CHANNEL_REPRESENTATION_POSITION
&& DownmixerBufferProvider::isMultichannelCapable()) {
DownmixerBufferProvider* pDbp = new DownmixerBufferProvider(channelMask,
mMixerChannelMask,
AUDIO_FORMAT_PCM_16_BIT ,
sampleRate, sessionId, kCopyBufferFrameCount);
if (pDbp->isValid()) {
mDownmixRequiresFormat = AUDIO_FORMAT_PCM_16_BIT;
downmixerBufferProvider = pDbp;
reconfigureBufferProviders();
return NO_ERROR;
}
delete pDbp;
}
RemixBufferProvider* pRbp = new RemixBufferProvider(channelMask,
mMixerChannelMask, mMixerInFormat, kCopyBufferFrameCount);
downmixerBufferProvider = pRbp;
reconfigureBufferProviders();
return NO_ERROR;
}
prepareForReformat()判断是否需要格式转换:
status_t AudioMixer::track_t::prepareForReformat()
{
ALOGV("AudioMixer::prepareForReformat(%p) with format %#x", this, mFormat);
unprepareForReformat();
const audio_format_t targetFormat = mDownmixRequiresFormat != AUDIO_FORMAT_INVALID
? mDownmixRequiresFormat : mMixerInFormat;
bool requiresReconfigure = false;
if (mFormat != targetFormat) {
mReformatBufferProvider = new ReformatBufferProvider(
audio_channel_count_from_out_mask(channelMask),
mFormat,
targetFormat,
kCopyBufferFrameCount);
requiresReconfigure = true;
}
if (targetFormat != mMixerInFormat) {
mPostDownmixReformatBufferProvider = new ReformatBufferProvider(
audio_channel_count_from_out_mask(mMixerChannelMask),
targetFormat,
mMixerInFormat,
kCopyBufferFrameCount);
requiresReconfigure = true;
}
if (requiresReconfigure) {
reconfigureBufferProviders();
}
return NO_ERROR;
}
从AudioMixer到AudioResampler
调用的时序图如下:
voidAudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
它是把各个track的声音数据相加。所谓声音数据,可以认为是一个个的采样点,Android默认支持的采样精度是16bit的,格式为signedPCM,所以每个采样点用有符号的16位数int16_t表示。如果直接加16bit的数据,肯定会造成16bit的值溢出,Android的做法是强转成int32_t,相加,并把和赋值给了32bit的数。注意,相加前乘上了音量,而表达音量的数据类型也是int32_t。这样,就能保证在这个过程中是不会溢出的。
void ditherAndClamp(int32_t* out, constint32_t *sums, size_t c) 将32bit的输出转成16bit,再把右声道放高16bit,左声道放低16bit输出
AudioMixer->AudioResampler传递设置参数处理主要的函数:prepareTracks_l()
这个函数中设置重采样参数等操作
AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
Vector< sp
AudioTrack.cpp
createTrack_l():
// mTransfer, mCbf, mUserData, mFormat, mFrameSize, mFlags
// mFlags is also assigned by createTrack_l(), but not the bit we care about.
set():
initializing a shared buffer AudioTrack via set()