[RK3288][Android6.0] Audio中的单声道到双声道的转换处理过程

来源:互联网 发布:选择排序和冒泡算法 编辑:程序博客网 时间:2024/05/17 19:59

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);    volumeMix<MIXTYPE, is_same<TI, float>::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,也就是转换成立体声。

阅读全文
1 0