Loading media/libaudioprocessing/AudioMixer.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -162,10 +162,10 @@ status_t AudioMixer::Track::prepareForDownmix() // 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. // are not the same and not handled internally, as mono for channel position masks is. if (channelMask == mMixerChannelMask || (channelMask == AUDIO_CHANNEL_OUT_MONO && mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO)) { && isAudioChannelPositionMask(mMixerChannelMask))) { return NO_ERROR; } // DownmixerBufferProvider is only used for position masks. Loading media/libaudioprocessing/AudioMixerBase.cpp +28 −4 Original line number Diff line number Diff line Loading @@ -643,7 +643,13 @@ void AudioMixerBase::process__validate() if (n & NEEDS_RESAMPLE) { all16BitsStereoNoResample = false; resampling = true; if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1 && t->channelMask == AUDIO_CHANNEL_OUT_MONO // MONO_HACK && isAudioChannelPositionMask(t->mMixerChannelMask)) { t->hook = TrackBase::getTrackHook( TRACKTYPE_RESAMPLEMONO, t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat); } else if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2 && t->useStereoVolume()) { t->hook = TrackBase::getTrackHook( TRACKTYPE_RESAMPLESTEREO, t->mMixerChannelCount, Loading @@ -658,7 +664,7 @@ void AudioMixerBase::process__validate() } else { if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){ t->hook = TrackBase::getTrackHook( (t->mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO // TODO: MONO_HACK (isAudioChannelPositionMask(t->mMixerChannelMask) // TODO: MONO_HACK && t->channelMask == AUDIO_CHANNEL_OUT_MONO) ? TRACKTYPE_NORESAMPLEMONO : TRACKTYPE_NORESAMPLE, t->mMixerChannelCount, Loading Loading @@ -1494,7 +1500,8 @@ void AudioMixerBase::TrackBase::track__Resample(TO* out, size_t outFrameCount, T ALOGVV("track__Resample\n"); mResampler->setSampleRate(sampleRate); const bool ramp = needsRamp(); if (ramp || aux != NULL) { if (MIXTYPE == MIXTYPE_MONOEXPAND || MIXTYPE == MIXTYPE_STEREOEXPAND || ramp || aux != NULL) { // if ramp: resample with unity gain to temp buffer and scale/mix in 2nd step. // if aux != NULL: resample with unity gain to temp buffer then apply send level. Loading Loading @@ -1629,6 +1636,23 @@ AudioMixerBase::hook_t AudioMixerBase::TrackBase::getTrackHook(int trackType, ui break; } break; // RESAMPLEMONO needs MIXTYPE_STEREOEXPAND since resampler will upmix mono // track to stereo track case TRACKTYPE_RESAMPLEMONO: switch (mixerInFormat) { case AUDIO_FORMAT_PCM_FLOAT: return (AudioMixerBase::hook_t) &TrackBase::track__Resample< MIXTYPE_STEREOEXPAND, float /*TO*/, float /*TI*/, TYPE_AUX>; case AUDIO_FORMAT_PCM_16_BIT: return (AudioMixerBase::hook_t) &TrackBase::track__Resample< MIXTYPE_STEREOEXPAND, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>; default: LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); break; } break; case TRACKTYPE_NORESAMPLEMONO: switch (mixerInFormat) { case AUDIO_FORMAT_PCM_FLOAT: Loading media/libaudioprocessing/AudioMixerOps.h +41 −18 Original line number Diff line number Diff line Loading @@ -219,6 +219,7 @@ enum { MIXTYPE_MULTI_SAVEONLY_MONOVOL, MIXTYPE_MULTI_STEREOVOL, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, MIXTYPE_STEREOEXPAND, }; /* Loading @@ -232,7 +233,8 @@ template <int MIXTYPE, int NCHAN, void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) { static_assert(NCHAN > 0 && NCHAN <= 8); static_assert(MIXTYPE == MIXTYPE_MULTI_STEREOVOL || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL); || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL || MIXTYPE == MIXTYPE_STEREOEXPAND); auto proc = [](auto& a, const auto& b) { if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL) { a += b; Loading @@ -240,14 +242,22 @@ void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) { a = b; } }; auto inp = [&in]() -> const TI& { if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) { return *in; } else { return *in++; } }; // HALs should only expose the canonical channel masks. proc(*out++, f(*in++, vol[0])); // front left proc(*out++, f(inp(), vol[0])); // front left if constexpr (NCHAN == 1) return; proc(*out++, f(*in++, vol[1])); // front right proc(*out++, f(inp(), vol[1])); // front right if constexpr (NCHAN == 2) return; if constexpr (NCHAN == 4) { proc(*out++, f(*in++, vol[0])); // back left proc(*out++, f(*in++, vol[1])); // back right proc(*out++, f(inp(), vol[0])); // back left proc(*out++, f(inp(), vol[1])); // back right return; } Loading @@ -258,25 +268,25 @@ void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) { } else { center = (vol[0] >> 1) + (vol[1] >> 1); // rounds to 0. } proc(*out++, f(*in++, center)); // center (or 2.1 LFE) proc(*out++, f(inp(), center)); // center (or 2.1 LFE) if constexpr (NCHAN == 3) return; if constexpr (NCHAN == 5) { proc(*out++, f(*in++, vol[0])); // back left proc(*out++, f(*in++, vol[1])); // back right proc(*out++, f(inp(), vol[0])); // back left proc(*out++, f(inp(), vol[1])); // back right return; } proc(*out++, f(*in++, center)); // lfe proc(*out++, f(*in++, vol[0])); // back left proc(*out++, f(*in++, vol[1])); // back right proc(*out++, f(inp(), center)); // lfe proc(*out++, f(inp(), vol[0])); // back left proc(*out++, f(inp(), vol[1])); // back right if constexpr (NCHAN == 6) return; if constexpr (NCHAN == 7) { proc(*out++, f(*in++, center)); // back center proc(*out++, f(inp(), center)); // back center return; } // NCHAN == 8 proc(*out++, f(*in++, vol[0])); // side left proc(*out++, f(*in++, vol[1])); // side right proc(*out++, f(inp(), vol[0])); // side left proc(*out++, f(inp(), vol[1])); // side right } /* Loading Loading @@ -326,6 +336,11 @@ void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) { * MIXTYPE_MULTI_SAVEONLY_STEREOVOL: * Same as MIXTYPE_MULTI_SAVEONLY, but uses only volume[0] and volume[1]. * * MIXTYPE_STEREOEXPAND: * Stereo input channel. NCHAN represents number of output channels. * Expand size 2 array "in" and "vol" to multi-channel output. Note * that the 2 array is assumed to have replicated L+R. * */ template <int MIXTYPE, int NCHAN, Loading Loading @@ -366,11 +381,13 @@ inline void volumeRampMulti(TO* out, size_t frameCount, } vol[0] += volinc[0]; } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) { || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL || MIXTYPE == MIXTYPE_STEREOEXPAND) { stereoVolumeHelper<MIXTYPE, NCHAN>( out, in, vol, [&auxaccum] (auto &a, const auto &b) { return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum); }); if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2; vol[0] += volinc[0]; vol[1] += volinc[1]; } else /* constexpr */ { Loading Loading @@ -409,10 +426,12 @@ inline void volumeRampMulti(TO* out, size_t frameCount, } vol[0] += volinc[0]; } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) { || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL || MIXTYPE == MIXTYPE_STEREOEXPAND) { stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) { return MixMul<TO, TI, TV>(a, b); }); if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2; vol[0] += volinc[0]; vol[1] += volinc[1]; } else /* constexpr */ { Loading Loading @@ -455,11 +474,13 @@ inline void volumeMulti(TO* out, size_t frameCount, *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum); } } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) { || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL || MIXTYPE == MIXTYPE_STEREOEXPAND) { stereoVolumeHelper<MIXTYPE, NCHAN>( out, in, vol, [&auxaccum] (auto &a, const auto &b) { return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum); }); if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2; } else /* constexpr */ { static_assert(dependent_false<MIXTYPE>, "invalid mixtype"); } Loading Loading @@ -490,10 +511,12 @@ inline void volumeMulti(TO* out, size_t frameCount, *out++ = MixMul<TO, TI, TV>(*in++, vol[0]); } } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) { || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL || MIXTYPE == MIXTYPE_STEREOEXPAND) { stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) { return MixMul<TO, TI, TV>(a, b); }); if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2; } else /* constexpr */ { static_assert(dependent_false<MIXTYPE>, "invalid mixtype"); } Loading media/libaudioprocessing/include/media/AudioMixerBase.h +1 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,7 @@ public: enum { TRACKTYPE_NOP, TRACKTYPE_RESAMPLE, TRACKTYPE_RESAMPLEMONO, TRACKTYPE_RESAMPLESTEREO, TRACKTYPE_NORESAMPLE, TRACKTYPE_NORESAMPLEMONO, Loading Loading
media/libaudioprocessing/AudioMixer.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -162,10 +162,10 @@ status_t AudioMixer::Track::prepareForDownmix() // 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. // are not the same and not handled internally, as mono for channel position masks is. if (channelMask == mMixerChannelMask || (channelMask == AUDIO_CHANNEL_OUT_MONO && mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO)) { && isAudioChannelPositionMask(mMixerChannelMask))) { return NO_ERROR; } // DownmixerBufferProvider is only used for position masks. Loading
media/libaudioprocessing/AudioMixerBase.cpp +28 −4 Original line number Diff line number Diff line Loading @@ -643,7 +643,13 @@ void AudioMixerBase::process__validate() if (n & NEEDS_RESAMPLE) { all16BitsStereoNoResample = false; resampling = true; if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2 if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1 && t->channelMask == AUDIO_CHANNEL_OUT_MONO // MONO_HACK && isAudioChannelPositionMask(t->mMixerChannelMask)) { t->hook = TrackBase::getTrackHook( TRACKTYPE_RESAMPLEMONO, t->mMixerChannelCount, t->mMixerInFormat, t->mMixerFormat); } else if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2 && t->useStereoVolume()) { t->hook = TrackBase::getTrackHook( TRACKTYPE_RESAMPLESTEREO, t->mMixerChannelCount, Loading @@ -658,7 +664,7 @@ void AudioMixerBase::process__validate() } else { if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){ t->hook = TrackBase::getTrackHook( (t->mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO // TODO: MONO_HACK (isAudioChannelPositionMask(t->mMixerChannelMask) // TODO: MONO_HACK && t->channelMask == AUDIO_CHANNEL_OUT_MONO) ? TRACKTYPE_NORESAMPLEMONO : TRACKTYPE_NORESAMPLE, t->mMixerChannelCount, Loading Loading @@ -1494,7 +1500,8 @@ void AudioMixerBase::TrackBase::track__Resample(TO* out, size_t outFrameCount, T ALOGVV("track__Resample\n"); mResampler->setSampleRate(sampleRate); const bool ramp = needsRamp(); if (ramp || aux != NULL) { if (MIXTYPE == MIXTYPE_MONOEXPAND || MIXTYPE == MIXTYPE_STEREOEXPAND || ramp || aux != NULL) { // if ramp: resample with unity gain to temp buffer and scale/mix in 2nd step. // if aux != NULL: resample with unity gain to temp buffer then apply send level. Loading Loading @@ -1629,6 +1636,23 @@ AudioMixerBase::hook_t AudioMixerBase::TrackBase::getTrackHook(int trackType, ui break; } break; // RESAMPLEMONO needs MIXTYPE_STEREOEXPAND since resampler will upmix mono // track to stereo track case TRACKTYPE_RESAMPLEMONO: switch (mixerInFormat) { case AUDIO_FORMAT_PCM_FLOAT: return (AudioMixerBase::hook_t) &TrackBase::track__Resample< MIXTYPE_STEREOEXPAND, float /*TO*/, float /*TI*/, TYPE_AUX>; case AUDIO_FORMAT_PCM_16_BIT: return (AudioMixerBase::hook_t) &TrackBase::track__Resample< MIXTYPE_STEREOEXPAND, int32_t /*TO*/, int16_t /*TI*/, TYPE_AUX>; default: LOG_ALWAYS_FATAL("bad mixerInFormat: %#x", mixerInFormat); break; } break; case TRACKTYPE_NORESAMPLEMONO: switch (mixerInFormat) { case AUDIO_FORMAT_PCM_FLOAT: Loading
media/libaudioprocessing/AudioMixerOps.h +41 −18 Original line number Diff line number Diff line Loading @@ -219,6 +219,7 @@ enum { MIXTYPE_MULTI_SAVEONLY_MONOVOL, MIXTYPE_MULTI_STEREOVOL, MIXTYPE_MULTI_SAVEONLY_STEREOVOL, MIXTYPE_STEREOEXPAND, }; /* Loading @@ -232,7 +233,8 @@ template <int MIXTYPE, int NCHAN, void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) { static_assert(NCHAN > 0 && NCHAN <= 8); static_assert(MIXTYPE == MIXTYPE_MULTI_STEREOVOL || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL); || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL || MIXTYPE == MIXTYPE_STEREOEXPAND); auto proc = [](auto& a, const auto& b) { if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL) { a += b; Loading @@ -240,14 +242,22 @@ void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) { a = b; } }; auto inp = [&in]() -> const TI& { if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) { return *in; } else { return *in++; } }; // HALs should only expose the canonical channel masks. proc(*out++, f(*in++, vol[0])); // front left proc(*out++, f(inp(), vol[0])); // front left if constexpr (NCHAN == 1) return; proc(*out++, f(*in++, vol[1])); // front right proc(*out++, f(inp(), vol[1])); // front right if constexpr (NCHAN == 2) return; if constexpr (NCHAN == 4) { proc(*out++, f(*in++, vol[0])); // back left proc(*out++, f(*in++, vol[1])); // back right proc(*out++, f(inp(), vol[0])); // back left proc(*out++, f(inp(), vol[1])); // back right return; } Loading @@ -258,25 +268,25 @@ void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) { } else { center = (vol[0] >> 1) + (vol[1] >> 1); // rounds to 0. } proc(*out++, f(*in++, center)); // center (or 2.1 LFE) proc(*out++, f(inp(), center)); // center (or 2.1 LFE) if constexpr (NCHAN == 3) return; if constexpr (NCHAN == 5) { proc(*out++, f(*in++, vol[0])); // back left proc(*out++, f(*in++, vol[1])); // back right proc(*out++, f(inp(), vol[0])); // back left proc(*out++, f(inp(), vol[1])); // back right return; } proc(*out++, f(*in++, center)); // lfe proc(*out++, f(*in++, vol[0])); // back left proc(*out++, f(*in++, vol[1])); // back right proc(*out++, f(inp(), center)); // lfe proc(*out++, f(inp(), vol[0])); // back left proc(*out++, f(inp(), vol[1])); // back right if constexpr (NCHAN == 6) return; if constexpr (NCHAN == 7) { proc(*out++, f(*in++, center)); // back center proc(*out++, f(inp(), center)); // back center return; } // NCHAN == 8 proc(*out++, f(*in++, vol[0])); // side left proc(*out++, f(*in++, vol[1])); // side right proc(*out++, f(inp(), vol[0])); // side left proc(*out++, f(inp(), vol[1])); // side right } /* Loading Loading @@ -326,6 +336,11 @@ void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) { * MIXTYPE_MULTI_SAVEONLY_STEREOVOL: * Same as MIXTYPE_MULTI_SAVEONLY, but uses only volume[0] and volume[1]. * * MIXTYPE_STEREOEXPAND: * Stereo input channel. NCHAN represents number of output channels. * Expand size 2 array "in" and "vol" to multi-channel output. Note * that the 2 array is assumed to have replicated L+R. * */ template <int MIXTYPE, int NCHAN, Loading Loading @@ -366,11 +381,13 @@ inline void volumeRampMulti(TO* out, size_t frameCount, } vol[0] += volinc[0]; } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) { || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL || MIXTYPE == MIXTYPE_STEREOEXPAND) { stereoVolumeHelper<MIXTYPE, NCHAN>( out, in, vol, [&auxaccum] (auto &a, const auto &b) { return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum); }); if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2; vol[0] += volinc[0]; vol[1] += volinc[1]; } else /* constexpr */ { Loading Loading @@ -409,10 +426,12 @@ inline void volumeRampMulti(TO* out, size_t frameCount, } vol[0] += volinc[0]; } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) { || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL || MIXTYPE == MIXTYPE_STEREOEXPAND) { stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) { return MixMul<TO, TI, TV>(a, b); }); if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2; vol[0] += volinc[0]; vol[1] += volinc[1]; } else /* constexpr */ { Loading Loading @@ -455,11 +474,13 @@ inline void volumeMulti(TO* out, size_t frameCount, *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum); } } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) { || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL || MIXTYPE == MIXTYPE_STEREOEXPAND) { stereoVolumeHelper<MIXTYPE, NCHAN>( out, in, vol, [&auxaccum] (auto &a, const auto &b) { return MixMulAux<TO, TI, TV, TA>(a, b, &auxaccum); }); if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2; } else /* constexpr */ { static_assert(dependent_false<MIXTYPE>, "invalid mixtype"); } Loading Loading @@ -490,10 +511,12 @@ inline void volumeMulti(TO* out, size_t frameCount, *out++ = MixMul<TO, TI, TV>(*in++, vol[0]); } } else if constexpr (MIXTYPE == MIXTYPE_MULTI_STEREOVOL || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL) { || MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL || MIXTYPE == MIXTYPE_STEREOEXPAND) { stereoVolumeHelper<MIXTYPE, NCHAN>(out, in, vol, [] (auto &a, const auto &b) { return MixMul<TO, TI, TV>(a, b); }); if constexpr (MIXTYPE == MIXTYPE_STEREOEXPAND) in += 2; } else /* constexpr */ { static_assert(dependent_false<MIXTYPE>, "invalid mixtype"); } Loading
media/libaudioprocessing/include/media/AudioMixerBase.h +1 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,7 @@ public: enum { TRACKTYPE_NOP, TRACKTYPE_RESAMPLE, TRACKTYPE_RESAMPLEMONO, TRACKTYPE_RESAMPLESTEREO, TRACKTYPE_NORESAMPLE, TRACKTYPE_NORESAMPLEMONO, Loading