文章大致内容介绍
本文主要讲述播放音乐流程,AudioResampler是如何生效的
- 播放流程
- AudioMixer分析
- 从MixerThread分析
播放流程
在Android中间,如果使用硬解码OffloadThread是不会出现混频和重采样的,但是播放需要软解的音频,则会按需要重采样。
为了方便研究,这里修改软件配置文件,让primary compress_offload仅仅支持8000的采样率播放,音乐播放会去跑MixerThread线程,这个线程上面才会出现重采样。
configs/msm8909/audio_policy_configuration.xml修改如下:
@@ -69,7 +69,7 @@
<mixPort name="compressed_offload" role="source"
flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
<profile name="" format="AUDIO_FORMAT_MP3"
- 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);
// discard the previous downmixer if there was one
unprepareForDownmix();
// MONO_HACK Only remix (upmix or downmix) if the track and mixer/device channel masks
// are not the same and not handled internally, as mono -> stereo currently is.
if (channelMask == mMixerChannelMask
|| (channelMask == AUDIO_CHANNEL_OUT_MONO
&& mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO)) {
//mMixerChannelMask 在getTrackName中间被赋值为双声道,判断是否需要downMixer
return NO_ERROR;
}
// DownmixerBufferProvider is only used for position masks.
if (audio_channel_mask_get_representation(channelMask)
== AUDIO_CHANNEL_REPRESENTATION_POSITION
&& DownmixerBufferProvider::isMultichannelCapable()) {
//条件满足channelMask&0x3为0,即声道数大于2,并且系统支持兼容多声道,则初始化相应的bufferprovider用来改变通道数
DownmixerBufferProvider* pDbp = new DownmixerBufferProvider(channelMask,
mMixerChannelMask,
AUDIO_FORMAT_PCM_16_BIT /* TODO: use mMixerInFormat, now only PCM 16 */,
sampleRate, sessionId, kCopyBufferFrameCount);
if (pDbp->isValid()) { // if constructor completed properly
mDownmixRequiresFormat = AUDIO_FORMAT_PCM_16_BIT; // PCM 16 bit required for downmix
downmixerBufferProvider = pDbp;
reconfigureBufferProviders();
return NO_ERROR;
}
delete pDbp;
}
//使用remixer的情况
// Effect downmixer does not accept the channel conversion. Let's use our remixer.
RemixBufferProvider* pRbp = new RemixBufferProvider(channelMask,
mMixerChannelMask, mMixerInFormat, kCopyBufferFrameCount);
// Remix always finds a conversion whereas Downmixer effect above may fail.
downmixerBufferProvider = pRbp;
reconfigureBufferProviders();
return NO_ERROR;
}
prepareForReformat()判断是否需要格式转换:
status_t AudioMixer::track_t::prepareForReformat()
{
ALOGV("AudioMixer::prepareForReformat(%p) with format %#x", this, mFormat);
// discard previous reformatters
unprepareForReformat();
// only configure reformatters as needed
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()
这个函数中设置重采样参数等操作
// prepareTracks_l() must be called with ThreadBase::mLock held
AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
Vector< sp<Track> > *tracksToRemove)
{
mixer_state mixerStatus = MIXER_IDLE;
// find out which tracks need to be processed
size_t count = mActiveTracks.size();
size_t mixedTracks = 0;
size_t tracksWithEffect = 0;
// counts only _active_ fast tracks
size_t fastTracks = 0;
uint32_t resetMask = 0; // bit mask of fast tracks that need to be reset
float masterVolume = mMasterVolume;
bool masterMute = mMasterMute;
#ifdef DOLBY_ENABLE // DOLBY_DAP_PREGAIN
// The maximum volume of left channel and right channel for pregain calculation.
uint32_t max_vol = 0;
float dvlf = 0.0f;
float dvrf = 0.0f;
#endif // DOLBY_END
if (masterMute) {
masterVolume = 0;
}
// Delegate master volume control to effect in output mix effect chain if needed
sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
if (chain != 0) {
uint32_t v = (uint32_t)(masterVolume * (1 << 24));
chain->setVolume_l(&v, &v);
masterVolume = (float)((v + (