Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92
播放音乐是单声道,硬件用的是双声道。
AudioFlinger::PlaybackThread::Track::Track ->
thread->getTrackName_l ->
AudioMixer::getTrackName ->
t->channelCount = audio_channel_count_from_out_mask(channelMask)
t->channelMask = channelMask;
t->prepareForDownmix
status_t AudioMixer::track_t::prepareForDownmix()
{
......
// 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)) {
return NO_ERROR;
}
......
// Effect downmixer does not accept the channel conversion. Let's use our remixer.
RemixBufferProvider* pRbp = new RemixBufferProvider(channelMask,
mMixerChannelMask, mMixerInFormat, kCopyBufferFrameCount);
......
}
prepareForDownmix()有两种情况下会直接返回:
1.数据源channel和mix channel一样时,那么肯定不需要转换
2.当数据源是单声道时,也不转换,直接返回,它是一个特例,其实后面会处理。
否则会通过RemixBufferProvider这个类来实现input channel到output channel的转换。
那么单声道的处理在哪里呢?
void AudioMixer::process__validate(state_t* state, int64_t pts)
{
......
if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
//第一个参数结果为TRACKTYPE_NORESAMPLEMONO
t.hook = getTrackHook(
(t.mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO // TODO: MONO_HACK
&& t.channelMask == AUDIO_CHANNEL_OUT_MONO)
? TRACKTYPE_NORESAMPLEMONO : TRACKTYPE_NORESAMPLE,
t.mMixerChannelCount,
t.mMixerInFormat, t.mMixerFormat);
all16BitsStereoNoResample = false;
}
......
}
AudioMixer::hook_t AudioMixer::getTrackHook(int trackType, uint32_t channelCount,
audio_format_t mixerInFormat, audio_format_t mixerOutFormat __unused)
{
......
switch (trackType) {
......
case TRACKTYPE_NORESAMPLEMONO:
switch (mixerInFormat) {
case AUDIO_FORMAT_PCM_FLOAT:
return (AudioMixer::hook_t)
track__NoResample<MIXTYPE_MONOEXPAND, float, float, int32_t>;
case AUDIO_FORMAT_PCM_16_BIT:
//16bit的情况
return (AudioMixer::hook_t)
track__NoResample<MIXTYPE_MONOEXPAND, int32_t, int16_t, int32_t>;
default:
LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat);
break;
}
}
......
}
t.hook对应的处理函数是track__NoResample(),在process__genericNoResampling()中调用:
void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
{
......
if (inFrames > 0) {
t.hook(&t, outTemp + (BLOCKSIZE - outFrames) * t.mMixerChannelCount,
inFrames, state->resampleTemp, aux);
t.frameCount -= inFrames;
outFrames -= inFrames;
if (CC_UNLIKELY(aux != NULL)) {
aux += inFrames;
}
}
......
}
track__NoResample()是个模板函数。
template <int MIXTYPE, typename TO, typename TI, typename TA>
void AudioMixer::track__NoResample(track_t* t, TO* out, size_t frameCount,
TO* temp __unused, TA* aux)
{
ALOGVV("track__NoResample\n");
const TI *in = static_cast<const TI *>(t->in);
volumeMixfloat>::value, true>(
out, frameCount, in, aux, t->needsRamp(), t);
// MIXTYPE_MONOEXPAND reads a single input channel and expands to NCHAN output channels.
// MIXTYPE_MULTI reads NCHAN input channels and places to NCHAN output channels.
in += (MIXTYPE == MIXTYPE_MONOEXPAND) ? frameCount : frameCount * t->mMixerChannelCount;
t->in = in;
}
注释说得很明白了,将单声道转换成NCHAN声道,这里的NCHAN是2,也就是转换成立体声。