Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e82406fe authored by Andy Hung's avatar Andy Hung Committed by Automerger Merge Worker
Browse files

Merge "Audio: Fixes for FCC_LIMIT validation" into sc-dev am: be2afc55

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/14904545

Change-Id: I5f96e218274f0688b4fe2840c507cd2f2fe46914
parents b505cc6a be2afc55
Loading
Loading
Loading
Loading
+47 −58
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define LOG_TAG "AudioMixer"
//#define LOG_NDEBUG 0

#include <array>
#include <sstream>
#include <string.h>

@@ -1295,8 +1296,29 @@ void AudioMixerBase::process__oneTrack16BitsStereoNoResampling()

// Needs to derive a compile time constant (constexpr).  Could be targeted to go
// to a MONOVOL mixtype based on MAX_NUM_VOLUMES, but that's an unnecessary complication.
#define MIXTYPE_MONOVOL(mixtype) ((mixtype) == MIXTYPE_MULTI ? MIXTYPE_MULTI_MONOVOL : \
        (mixtype) == MIXTYPE_MULTI_SAVEONLY ? MIXTYPE_MULTI_SAVEONLY_MONOVOL : (mixtype))

constexpr int MIXTYPE_MONOVOL(int mixtype, int channels) {
    if (channels <= FCC_2) {
        return mixtype;
    } else if (mixtype == MIXTYPE_MULTI) {
        return MIXTYPE_MULTI_MONOVOL;
    } else if (mixtype == MIXTYPE_MULTI_SAVEONLY) {
        return MIXTYPE_MULTI_SAVEONLY_MONOVOL;
    } else {
        return mixtype;
    }
}

// Helper to make a functional array from volumeRampMulti.
template <int MIXTYPE, typename TO, typename TI, typename TV, typename TA, typename TAV,
          std::size_t ... Is>
static constexpr auto makeVRMArray(std::index_sequence<Is...>)
{
    using F = void(*)(TO*, size_t, const TI*, TA*, TV*, const TV*, TAV*, TAV);
    return std::array<F, sizeof...(Is)>{
            { &volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE, Is + 1), Is + 1, TO, TI, TV, TA, TAV> ...}
        };
}

/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
 * TO: int32_t (Q4.27) or float
@@ -1308,40 +1330,26 @@ template <int MIXTYPE,
static void volumeRampMulti(uint32_t channels, TO* out, size_t frameCount,
        const TI* in, TA* aux, TV *vol, const TV *volinc, TAV *vola, TAV volainc)
{
    switch (channels) {
    case 1:
        volumeRampMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, volinc, vola, volainc);
        break;
    case 2:
        volumeRampMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, volinc, vola, volainc);
        break;
    case 3:
        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out,
                frameCount, in, aux, vol, volinc, vola, volainc);
        break;
    case 4:
        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out,
                frameCount, in, aux, vol, volinc, vola, volainc);
        break;
    case 5:
        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out,
                frameCount, in, aux, vol, volinc, vola, volainc);
        break;
    case 6:
        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out,
                frameCount, in, aux, vol, volinc, vola, volainc);
        break;
    case 7:
        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out,
                frameCount, in, aux, vol, volinc, vola, volainc);
        break;
    case 8:
        volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out,
                frameCount, in, aux, vol, volinc, vola, volainc);
        break;
    static constexpr auto volumeRampMultiArray =
            makeVRMArray<MIXTYPE, TO, TI, TV, TA, TAV>(std::make_index_sequence<FCC_LIMIT>());
    if (channels > 0 && channels <= volumeRampMultiArray.size()) {
        volumeRampMultiArray[channels - 1](out, frameCount, in, aux, vol, volinc, vola, volainc);
    } else {
        ALOGE("%s: invalid channel count:%d", __func__, channels);
    }
}

// Helper to make a functional array from volumeMulti.
template <int MIXTYPE, typename TO, typename TI, typename TV, typename TA, typename TAV,
          std::size_t ... Is>
static constexpr auto makeVMArray(std::index_sequence<Is...>)
{
    using F = void(*)(TO*, size_t, const TI*, TA*, const TV*, TAV);
    return std::array<F, sizeof...(Is)>{
            { &volumeMulti<MIXTYPE_MONOVOL(MIXTYPE, Is + 1), Is + 1, TO, TI, TV, TA, TAV> ... }
        };
}

/* MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
 * TO: int32_t (Q4.27) or float
 * TI: int32_t (Q4.27) or int16_t (Q0.15) or float
@@ -1352,31 +1360,12 @@ template <int MIXTYPE,
static void volumeMulti(uint32_t channels, TO* out, size_t frameCount,
        const TI* in, TA* aux, const TV *vol, TAV vola)
{
    switch (channels) {
    case 1:
        volumeMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, vola);
        break;
    case 2:
        volumeMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, vola);
        break;
    case 3:
        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out, frameCount, in, aux, vol, vola);
        break;
    case 4:
        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out, frameCount, in, aux, vol, vola);
        break;
    case 5:
        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out, frameCount, in, aux, vol, vola);
        break;
    case 6:
        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out, frameCount, in, aux, vol, vola);
        break;
    case 7:
        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out, frameCount, in, aux, vol, vola);
        break;
    case 8:
        volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out, frameCount, in, aux, vol, vola);
        break;
    static constexpr auto volumeMultiArray =
            makeVMArray<MIXTYPE, TO, TI, TV, TA, TAV>(std::make_index_sequence<FCC_LIMIT>());
    if (channels > 0 && channels <= volumeMultiArray.size()) {
        volumeMultiArray[channels - 1](out, frameCount, in, aux, vol, vola);
    } else {
        ALOGE("%s: invalid channel count:%d", __func__, channels);
    }
}

+10 −0
Original line number Diff line number Diff line
@@ -293,6 +293,16 @@ void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) {
    // NCHAN == 8
    proc(*out++, f(inp(), vol[0])); // side left
    proc(*out++, f(inp(), vol[1])); // side right
    if constexpr (NCHAN > FCC_8) {
        // Mutes to zero extended surround channels.
        // 7.1.4 has the correct behavior.
        // 22.2 has the behavior that FLC and FRC will be mixed instead
        // of SL and SR and LFE will be center, not left.
        for (int i = 8; i < NCHAN; ++i) {
            // TODO: Consider using android::audio_utils::channels::kSideFromChannelIdx
            proc(*out++, f(inp(), 0.f));
        }
    }
}

/*
+60 −48
Original line number Diff line number Diff line
@@ -548,61 +548,73 @@ void AudioResamplerDyn<TC, TI, TO>::setSampleRate(int32_t inSampleRate)
    LOG_ALWAYS_FATAL_IF(mChannelCount < 1 || mChannelCount > FCC_LIMIT,
            "Resampler channels(%d) must be between 1 to %d", mChannelCount, FCC_LIMIT);
    // stride 16 (falls back to stride 2 for machines that do not support NEON)


// For now use a #define as a compiler generated function table requires renaming.
#pragma push_macro("AUDIORESAMPLERDYN_CASE")
#undef AUDIORESAMPLERDYN_CASE
#define AUDIORESAMPLERDYN_CASE(CHANNEL, LOCKED) \
    case CHANNEL: if constexpr (CHANNEL <= FCC_LIMIT) {\
        mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<CHANNEL, LOCKED, 16>; \
    } break

    if (locked) {
        switch (mChannelCount) {
        case 1:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, true, 16>;
            break;
        case 2:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, true, 16>;
            break;
        case 3:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<3, true, 16>;
            break;
        case 4:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<4, true, 16>;
            break;
        case 5:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<5, true, 16>;
            break;
        case 6:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<6, true, 16>;
            break;
        case 7:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<7, true, 16>;
            break;
        case 8:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<8, true, 16>;
            break;
        AUDIORESAMPLERDYN_CASE(1, true);
        AUDIORESAMPLERDYN_CASE(2, true);
        AUDIORESAMPLERDYN_CASE(3, true);
        AUDIORESAMPLERDYN_CASE(4, true);
        AUDIORESAMPLERDYN_CASE(5, true);
        AUDIORESAMPLERDYN_CASE(6, true);
        AUDIORESAMPLERDYN_CASE(7, true);
        AUDIORESAMPLERDYN_CASE(8, true);
        AUDIORESAMPLERDYN_CASE(9, true);
        AUDIORESAMPLERDYN_CASE(10, true);
        AUDIORESAMPLERDYN_CASE(11, true);
        AUDIORESAMPLERDYN_CASE(12, true);
        AUDIORESAMPLERDYN_CASE(13, true);
        AUDIORESAMPLERDYN_CASE(14, true);
        AUDIORESAMPLERDYN_CASE(15, true);
        AUDIORESAMPLERDYN_CASE(16, true);
        AUDIORESAMPLERDYN_CASE(17, true);
        AUDIORESAMPLERDYN_CASE(18, true);
        AUDIORESAMPLERDYN_CASE(19, true);
        AUDIORESAMPLERDYN_CASE(20, true);
        AUDIORESAMPLERDYN_CASE(21, true);
        AUDIORESAMPLERDYN_CASE(22, true);
        AUDIORESAMPLERDYN_CASE(23, true);
        AUDIORESAMPLERDYN_CASE(24, true);
        }
    } else {
        switch (mChannelCount) {
        case 1:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, false, 16>;
            break;
        case 2:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, false, 16>;
            break;
        case 3:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<3, false, 16>;
            break;
        case 4:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<4, false, 16>;
            break;
        case 5:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<5, false, 16>;
            break;
        case 6:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<6, false, 16>;
            break;
        case 7:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<7, false, 16>;
            break;
        case 8:
            mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<8, false, 16>;
            break;
        }
    }
        AUDIORESAMPLERDYN_CASE(1, false);
        AUDIORESAMPLERDYN_CASE(2, false);
        AUDIORESAMPLERDYN_CASE(3, false);
        AUDIORESAMPLERDYN_CASE(4, false);
        AUDIORESAMPLERDYN_CASE(5, false);
        AUDIORESAMPLERDYN_CASE(6, false);
        AUDIORESAMPLERDYN_CASE(7, false);
        AUDIORESAMPLERDYN_CASE(8, false);
        AUDIORESAMPLERDYN_CASE(9, false);
        AUDIORESAMPLERDYN_CASE(10, false);
        AUDIORESAMPLERDYN_CASE(11, false);
        AUDIORESAMPLERDYN_CASE(12, false);
        AUDIORESAMPLERDYN_CASE(13, false);
        AUDIORESAMPLERDYN_CASE(14, false);
        AUDIORESAMPLERDYN_CASE(15, false);
        AUDIORESAMPLERDYN_CASE(16, false);
        AUDIORESAMPLERDYN_CASE(17, false);
        AUDIORESAMPLERDYN_CASE(18, false);
        AUDIORESAMPLERDYN_CASE(19, false);
        AUDIORESAMPLERDYN_CASE(20, false);
        AUDIORESAMPLERDYN_CASE(21, false);
        AUDIORESAMPLERDYN_CASE(22, false);
        AUDIORESAMPLERDYN_CASE(23, false);
        AUDIORESAMPLERDYN_CASE(24, false);
        }
    }
#pragma pop_macro("AUDIORESAMPLERDYN_CASE")

#ifdef DEBUG_RESAMPLER
    printf("channels:%d  %s  stride:%d  %s  coef:%d  shift:%d\n",
            mChannelCount, locked ? "locked" : "interpolated",
+11 −2
Original line number Diff line number Diff line
@@ -48,6 +48,15 @@ namespace android {

/*static*/ const FastMixerState FastMixer::sInitial;

static audio_channel_mask_t getChannelMaskFromCount(size_t count) {
    const audio_channel_mask_t mask = audio_channel_out_mask_from_count(count);
    if (mask == AUDIO_CHANNEL_INVALID) {
        // some counts have no positional masks. TODO: Update this to return index count?
        return audio_channel_mask_for_index_assignment_from_count(count);
    }
    return mask;
}

FastMixer::FastMixer(audio_io_handle_t parentIoHandle)
    : FastThread("cycle_ms", "load_us"),
    // mFastTrackNames
@@ -79,7 +88,7 @@ FastMixer::FastMixer(audio_io_handle_t parentIoHandle)
    mDummyDumpState = &mDummyFastMixerDumpState;
    // TODO: Add channel mask to NBAIO_Format.
    // We assume that the channel mask must be a valid positional channel mask.
    mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
    mSinkChannelMask = getChannelMaskFromCount(mSinkChannelCount);

    unsigned i;
    for (i = 0; i < FastMixerState::sMaxFastTracks; ++i) {
@@ -238,7 +247,7 @@ void FastMixer::onStateChange()
            LOG_ALWAYS_FATAL_IF(mSinkChannelCount > AudioMixer::MAX_NUM_CHANNELS);

            if (mSinkChannelMask == AUDIO_CHANNEL_NONE) {
                mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
                mSinkChannelMask = getChannelMaskFromCount(mSinkChannelCount);
            }
            mAudioChannelCount = mSinkChannelCount - audio_channel_count_from_out_mask(
                    mSinkChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);