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

Commit e93b6b73 authored by Andy Hung's avatar Andy Hung
Browse files

Add multichannel capability to AudioMixer

tests/test-mixer updated to handle multichannel.
New mixer path is still disabled (kUseNewMixer = false).
Subsequent CL will enable multichannel capability.

Change-Id: I71dafa94cc1d9af567c285e0ded7c5c94e3ff926
parent 81e50d0c
Loading
Loading
Loading
Loading
+298 −131

File changed.

Preview size limit exceeded, changes collapsed.

+25 −20
Original line number Diff line number Diff line
@@ -51,12 +51,11 @@ public:
    static const uint32_t MAX_NUM_TRACKS = 32;
    // maximum number of channels supported by the mixer

    // This mixer has a hard-coded upper limit of 2 channels for output.
    // There is support for > 2 channel tracks down-mixed to 2 channel output via a down-mix effect.
    // Adding support for > 2 channel output would require more than simply changing this value.
    static const uint32_t MAX_NUM_CHANNELS = 2;
    // This mixer has a hard-coded upper limit of 8 channels for output.
    static const uint32_t MAX_NUM_CHANNELS = 8;
    static const uint32_t MAX_NUM_VOLUMES = 2; // stereo volume only
    // maximum number of channels supported for the content
    static const uint32_t MAX_NUM_CHANNELS_TO_DOWNMIX = 8;
    static const uint32_t MAX_NUM_CHANNELS_TO_DOWNMIX = AUDIO_CHANNEL_COUNT_MAX;

    static const uint16_t UNITY_GAIN_INT = 0x1000;
    static const float    UNITY_GAIN_FLOAT = 1.0f;
@@ -82,6 +81,7 @@ public:
        AUX_BUFFER      = 0x4003,
        DOWNMIX_TYPE    = 0X4004,
        MIXER_FORMAT    = 0x4005, // AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
        MIXER_CHANNEL_MASK = 0x4006, // Channel mask for mixer output
        // for target RESAMPLE
        SAMPLE_RATE     = 0x4100, // Configure sample rate conversion on this track name;
                                  // parameter 'value' is the new sample rate in Hz.
@@ -164,15 +164,15 @@ private:

        // TODO: Eventually remove legacy integer volume settings
        union {
        int16_t     volume[MAX_NUM_CHANNELS]; // U4.12 fixed point (top bit should be zero)
        int16_t     volume[MAX_NUM_VOLUMES]; // U4.12 fixed point (top bit should be zero)
        int32_t     volumeRL;
        };

        int32_t     prevVolume[MAX_NUM_CHANNELS];
        int32_t     prevVolume[MAX_NUM_VOLUMES];

        // 16-byte boundary

        int32_t     volumeInc[MAX_NUM_CHANNELS];
        int32_t     volumeInc[MAX_NUM_VOLUMES];
        int32_t     auxInc;
        int32_t     prevAuxLevel;

@@ -217,18 +217,20 @@ private:
        audio_format_t mMixerInFormat;   // mix internal format AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
                                         // each track must be converted to this format.

        float          mVolume[MAX_NUM_CHANNELS];     // floating point set volume
        float          mPrevVolume[MAX_NUM_CHANNELS]; // floating point previous volume
        float          mVolumeInc[MAX_NUM_CHANNELS];  // floating point volume increment
        float          mVolume[MAX_NUM_VOLUMES];     // floating point set volume
        float          mPrevVolume[MAX_NUM_VOLUMES]; // floating point previous volume
        float          mVolumeInc[MAX_NUM_VOLUMES];  // floating point volume increment

        float          mAuxLevel;                     // floating point set aux level
        float          mPrevAuxLevel;                 // floating point prev aux level
        float          mAuxInc;                       // floating point aux increment

        // 16-byte boundary
        audio_channel_mask_t mMixerChannelMask;
        uint32_t             mMixerChannelCount;

        bool        needsRamp() { return (volumeInc[0] | volumeInc[1] | auxInc) != 0; }
        bool        setResampler(uint32_t sampleRate, uint32_t devSampleRate);
        bool        setResampler(uint32_t trackSampleRate, uint32_t devSampleRate);
        bool        doesResample() const { return resampler != NULL; }
        void        resetResampler() { if (resampler != NULL) resampler->reset(); }
        void        adjustVolumeRamp(bool aux, bool useFloat = false);
@@ -377,7 +379,11 @@ private:
    // OK to call more often than that, but unnecessary.
    void invalidateState(uint32_t mask);

    static status_t initTrackDownmix(track_t* pTrack, int trackNum, audio_channel_mask_t mask);
    bool setChannelMasks(int name,
            audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask);

    // TODO: remove unused trackName/trackNum from functions below.
    static status_t initTrackDownmix(track_t* pTrack, int trackName);
    static status_t prepareTrackForDownmix(track_t* pTrack, int trackNum);
    static void unprepareTrackForDownmix(track_t* pTrack, int trackName);
    static status_t prepareTrackForReformat(track_t* pTrack, int trackNum);
@@ -418,27 +424,26 @@ private:
     * in AudioMixerOps.h).  The template parameters are as follows:
     *
     *   MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
     *   NCHAN       (number of channels, 2 for now)
     *   USEFLOATVOL (set to true if float volume is used)
     *   ADJUSTVOL   (set to true if volume ramp parameters needs adjustment afterwards)
     *   TO: int32_t (Q4.27) or float
     *   TI: int32_t (Q4.27) or int16_t (Q0.15) or float
     *   TA: int32_t (Q4.27)
     */
    template <int MIXTYPE, int NCHAN, bool USEFLOATVOL, bool ADJUSTVOL,
    template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
        typename TO, typename TI, typename TA>
    static void volumeMix(TO *out, size_t outFrames,
            const TI *in, TA *aux, bool ramp, AudioMixer::track_t *t);

    // multi-format process hooks
    template <int MIXTYPE, int NCHAN, typename TO, typename TI, typename TA>
    template <int MIXTYPE, typename TO, typename TI, typename TA>
    static void process_NoResampleOneTrack(state_t* state, int64_t pts);

    // multi-format track hooks
    template <int MIXTYPE, int NCHAN, typename TO, typename TI, typename TA>
    template <int MIXTYPE, typename TO, typename TI, typename TA>
    static void track__Resample(track_t* t, TO* out, size_t frameCount,
            TO* temp __unused, TA* aux);
    template <int MIXTYPE, int NCHAN, typename TO, typename TI, typename TA>
    template <int MIXTYPE, typename TO, typename TI, typename TA>
    static void track__NoResample(track_t* t, TO* out, size_t frameCount,
            TO* temp __unused, TA* aux);

@@ -457,9 +462,9 @@ private:
    };

    // functions for determining the proper process and track hooks.
    static process_hook_t getProcessHook(int processType, int channels,
    static process_hook_t getProcessHook(int processType, uint32_t channelCount,
            audio_format_t mixerInFormat, audio_format_t mixerOutFormat);
    static hook_t getTrackHook(int trackType, int channels,
    static hook_t getTrackHook(int trackType, uint32_t channelCount,
            audio_format_t mixerInFormat, audio_format_t mixerOutFormat);
};

+67 −14
Original line number Diff line number Diff line
@@ -230,6 +230,8 @@ enum {
    MIXTYPE_MULTI,
    MIXTYPE_MONOEXPAND,
    MIXTYPE_MULTI_SAVEONLY,
    MIXTYPE_MULTI_MONOVOL,
    MIXTYPE_MULTI_SAVEONLY_MONOVOL,
};

/*
@@ -263,6 +265,13 @@ enum {
 *   vol: represents a volume array.
 *
 *   MIXTYPE_MULTI_SAVEONLY does not accumulate into the out pointer.
 *
 * MIXTYPE_MULTI_MONOVOL:
 *   Same as MIXTYPE_MULTI, but uses only volume[0].
 *
 * MIXTYPE_MULTI_SAVEONLY_MONOVOL:
 *   Same as MIXTYPE_MULTI_SAVEONLY, but uses only volume[0].
 *
 */

template <int MIXTYPE, int NCHAN,
@@ -283,18 +292,30 @@ inline void volumeRampMulti(TO* out, size_t frameCount,
                    vol[i] += volinc[i];
                }
                break;
            case MIXTYPE_MONOEXPAND:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum);
                    vol[i] += volinc[i];
                }
                in++;
                break;
            case MIXTYPE_MULTI_SAVEONLY:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
                    vol[i] += volinc[i];
                }
                break;
            case MIXTYPE_MONOEXPAND:
            case MIXTYPE_MULTI_MONOVOL:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum);
                    vol[i] += volinc[i];
                    *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
                }
                in++;
                vol[0] += volinc[0];
                break;
            case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
                }
                vol[0] += volinc[0];
                break;
            default:
                LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
@@ -313,18 +334,30 @@ inline void volumeRampMulti(TO* out, size_t frameCount,
                    vol[i] += volinc[i];
                }
                break;
            case MIXTYPE_MONOEXPAND:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ += MixMul<TO, TI, TV>(*in, vol[i]);
                    vol[i] += volinc[i];
                }
                in++;
                break;
            case MIXTYPE_MULTI_SAVEONLY:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ = MixMul<TO, TI, TV>(*in++, vol[i]);
                    vol[i] += volinc[i];
                }
                break;
            case MIXTYPE_MONOEXPAND:
            case MIXTYPE_MULTI_MONOVOL:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ += MixMul<TO, TI, TV>(*in, vol[i]);
                    vol[i] += volinc[i];
                    *out++ += MixMul<TO, TI, TV>(*in++, vol[0]);
                }
                in++;
                vol[0] += volinc[0];
                break;
            case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ = MixMul<TO, TI, TV>(*in++, vol[0]);
                }
                vol[0] += volinc[0];
                break;
            default:
                LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
@@ -351,16 +384,26 @@ inline void volumeMulti(TO* out, size_t frameCount,
                    *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
                }
                break;
            case MIXTYPE_MONOEXPAND:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum);
                }
                in++;
                break;
            case MIXTYPE_MULTI_SAVEONLY:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[i], &auxaccum);
                }
                break;
            case MIXTYPE_MONOEXPAND:
            case MIXTYPE_MULTI_MONOVOL:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ += MixMulAux<TO, TI, TV, TA>(*in, vol[i], &auxaccum);
                    *out++ += MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
                }
                break;
            case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ = MixMulAux<TO, TI, TV, TA>(*in++, vol[0], &auxaccum);
                }
                in++;
                break;
            default:
                LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
@@ -377,16 +420,26 @@ inline void volumeMulti(TO* out, size_t frameCount,
                    *out++ += MixMul<TO, TI, TV>(*in++, vol[i]);
                }
                break;
            case MIXTYPE_MONOEXPAND:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ += MixMul<TO, TI, TV>(*in, vol[i]);
                }
                in++;
                break;
            case MIXTYPE_MULTI_SAVEONLY:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ = MixMul<TO, TI, TV>(*in++, vol[i]);
                }
                break;
            case MIXTYPE_MONOEXPAND:
            case MIXTYPE_MULTI_MONOVOL:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ += MixMul<TO, TI, TV>(*in, vol[i]);
                    *out++ += MixMul<TO, TI, TV>(*in++, vol[0]);
                }
                break;
            case MIXTYPE_MULTI_SAVEONLY_MONOVOL:
                for (int i = 0; i < NCHAN; ++i) {
                    *out++ = MixMul<TO, TI, TV>(*in++, vol[0]);
                }
                in++;
                break;
            default:
                LOG_ALWAYS_FATAL("invalid mixtype %d", MIXTYPE);
+2 −2
Original line number Diff line number Diff line
@@ -72,9 +72,9 @@ function createwav() {
# track__Resample / track__genericResample
# track__NoResample / track__16BitsStereo / track__16BitsMono
# Aux buffer
    adb shell test-mixer $1 -s 9307 \
    adb shell test-mixer $1 -c 5 -s 9307 \
        -a /sdcard/aux9307gra.wav -o /sdcard/tm9307gra.wav \
        sine:2,1000,3000 sine:1,2000,9307 chirp:2,9307
        sine:4,1000,3000 sine:1,2000,9307 chirp:3,9307
    adb pull /sdcard/tm9307gra.wav $2
    adb pull /sdcard/aux9307gra.wav $2

+26 −6
Original line number Diff line number Diff line
@@ -36,11 +36,12 @@
using namespace android;

static void usage(const char* name) {
    fprintf(stderr, "Usage: %s [-f] [-m]"
    fprintf(stderr, "Usage: %s [-f] [-m] [-c channels]"
                    " [-s sample-rate] [-o <output-file>] [-a <aux-buffer-file>] [-P csv]"
                    " (<input-file> | <command>)+\n", name);
    fprintf(stderr, "    -f    enable floating point input track\n");
    fprintf(stderr, "    -m    enable floating point mixer output\n");
    fprintf(stderr, "    -c    number of mixer output channels\n");
    fprintf(stderr, "    -s    mixer sample-rate\n");
    fprintf(stderr, "    -o    <output-file> WAV file, pcm16 (or float if -m specified)\n");
    fprintf(stderr, "    -a    <aux-buffer-file>\n");
@@ -90,7 +91,7 @@ int main(int argc, char* argv[]) {
    std::vector<int32_t> Names;
    std::vector<SignalProvider> Providers;

    for (int ch; (ch = getopt(argc, argv, "fms:o:a:P:")) != -1;) {
    for (int ch; (ch = getopt(argc, argv, "fmc:s:o:a:P:")) != -1;) {
        switch (ch) {
        case 'f':
            useInputFloat = true;
@@ -98,6 +99,9 @@ int main(int argc, char* argv[]) {
        case 'm':
            useMixerFloat = true;
            break;
        case 'c':
            outputChannels = atoi(optarg);
            break;
        case 's':
            outputSampleRate = atoi(optarg);
            break;
@@ -160,7 +164,7 @@ int main(int argc, char* argv[]) {

            parseCSV(argv[i] + strlen(sine), v);
            if (v.size() == 3) {
                printf("creating sine(%d %d)\n", v[0], v[1]);
                printf("creating sine(%d %d %d)\n", v[0], v[1], v[2]);
                if (useInputFloat) {
                    Providers[i].setSine<float>(v[0], v[1], v[2], kSeconds);
                } else {
@@ -191,6 +195,8 @@ int main(int argc, char* argv[]) {
    const size_t outputFrameSize = outputChannels
            * (useMixerFloat ? sizeof(float) : sizeof(int16_t));
    const size_t outputSize = outputFrames * outputFrameSize;
    const audio_channel_mask_t outputChannelMask =
            audio_channel_out_mask_from_count(outputChannels);
    void *outputAddr = NULL;
    (void) posix_memalign(&outputAddr, 32, outputSize);
    memset(outputAddr, 0, outputSize);
@@ -228,9 +234,23 @@ int main(int argc, char* argv[]) {
        mixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::MIXER_FORMAT, (void *)mixerFormat);
        mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT,
                AudioMixer::MIXER_FORMAT,
                (void *)(uintptr_t)mixerFormat);
        mixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::FORMAT,
                (void *)(uintptr_t)inputFormat);
        mixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::MIXER_CHANNEL_MASK,
                (void *)(uintptr_t)outputChannelMask);
        mixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::CHANNEL_MASK,
                (void *)(uintptr_t)channelMask);
        mixer->setParameter(
                name,
                AudioMixer::RESAMPLE,
Loading