Initial Contribution
diff --git a/libs/audioflinger/AudioMixer.cpp b/libs/audioflinger/AudioMixer.cpp
new file mode 100644
index 0000000..9f1b17f
--- /dev/null
+++ b/libs/audioflinger/AudioMixer.cpp
@@ -0,0 +1,857 @@
+/* //device/include/server/AudioFlinger/AudioMixer.cpp
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+#define LOG_TAG "AudioMixer"
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include "AudioMixer.h"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+static inline int16_t clamp16(int32_t sample)
+{
+    if ((sample>>15) ^ (sample>>31))
+        sample = 0x7FFF ^ (sample>>31);
+    return sample;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
+    :   mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate)
+{
+    mState.enabledTracks= 0;
+    mState.needsChanged = 0;
+    mState.frameCount   = frameCount;
+    mState.outputTemp   = 0;
+    mState.resampleTemp = 0;
+    mState.hook         = process__nop;
+    track_t* t = mState.tracks;
+    for (int i=0 ; i<32 ; i++) {
+        t->needs = 0;
+        t->volume[0] = UNITY_GAIN;
+        t->volume[1] = UNITY_GAIN;
+        t->volumeInc[0] = 0;
+        t->volumeInc[1] = 0;
+        t->channelCount = 2;
+        t->enabled = 0;
+        t->format = 16;
+        t->buffer.raw = 0;
+        t->bufferProvider = 0;
+        t->hook = 0;
+        t->resampler = 0;
+        t->sampleRate = mSampleRate;
+        t->in = 0;
+        t++;
+    }
+}
+
+ AudioMixer::~AudioMixer()
+ {
+     track_t* t = mState.tracks;
+     for (int i=0 ; i<32 ; i++) {
+         delete t->resampler;
+         t++;
+     }
+     delete [] mState.outputTemp;
+     delete [] mState.resampleTemp;
+ }
+
+ int AudioMixer::getTrackName()
+ {
+    uint32_t names = mTrackNames;
+    uint32_t mask = 1;
+    int n = 0;
+    while (names & mask) {
+        mask <<= 1;
+        n++;
+    }
+    if (mask) {
+        LOGV("add track (%d)", n);
+        mTrackNames |= mask;
+        return TRACK0 + n;
+    }
+    return -1;
+ }
+
+ void AudioMixer::invalidateState(uint32_t mask)
+ {
+    if (mask) {
+        mState.needsChanged |= mask;
+        mState.hook = process__validate;
+    }
+ }
+
+ void AudioMixer::deleteTrackName(int name)
+ {
+    name -= TRACK0;
+    if (uint32_t(name) < MAX_NUM_TRACKS) {
+        LOGV("deleteTrackName(%d)", name);
+        track_t& track(mState.tracks[ name ]);
+        if (track.enabled != 0) {
+            track.enabled = 0;
+            invalidateState(1<<name);
+        }
+        if (track.resampler) {
+            // delete  the resampler
+            delete track.resampler;
+            track.resampler = 0;
+            track.sampleRate = mSampleRate;
+            invalidateState(1<<name);
+        }
+        track.volumeInc[0] = 0;
+        track.volumeInc[1] = 0;
+        mTrackNames &= ~(1<<name);
+    }
+ }
+
+status_t AudioMixer::enable(int name)
+{
+    switch (name) {
+        case MIXING: {
+            if (mState.tracks[ mActiveTrack ].enabled != 1) {
+                mState.tracks[ mActiveTrack ].enabled = 1;
+                LOGV("enable(%d)", mActiveTrack);
+                invalidateState(1<<mActiveTrack);
+            }
+        } break;
+        default:
+            return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
+status_t AudioMixer::disable(int name)
+{
+    switch (name) {
+        case MIXING: {
+            if (mState.tracks[ mActiveTrack ].enabled != 0) {
+                mState.tracks[ mActiveTrack ].enabled = 0;
+                LOGV("disable(%d)", mActiveTrack);
+                invalidateState(1<<mActiveTrack);
+            }
+        } break;
+        default:
+            return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
+status_t AudioMixer::setActiveTrack(int track)
+{
+    if (uint32_t(track-TRACK0) >= MAX_NUM_TRACKS) {
+        return BAD_VALUE;
+    }
+    mActiveTrack = track - TRACK0;
+    return NO_ERROR;
+}
+
+status_t AudioMixer::setParameter(int target, int name, int value)
+{
+    switch (target) {
+    case TRACK:
+        if (name == CHANNEL_COUNT) {
+            if ((uint32_t(value) <= MAX_NUM_CHANNELS) && (value)) {
+                if (mState.tracks[ mActiveTrack ].channelCount != value) {
+                    mState.tracks[ mActiveTrack ].channelCount = value;
+                    LOGV("setParameter(TRACK, CHANNEL_COUNT, %d)", value);
+                    invalidateState(1<<mActiveTrack);
+                }
+                return NO_ERROR;
+            }
+        }
+        break;
+    case RESAMPLE:
+        if (name == SAMPLE_RATE) {
+            if (value > 0) {
+                track_t& track = mState.tracks[ mActiveTrack ];
+                if (track.setResampler(uint32_t(value), mSampleRate)) {
+                    LOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
+                            uint32_t(value));
+                    invalidateState(1<<mActiveTrack);
+                }
+                return NO_ERROR;
+            }
+        }
+        break;
+    case RAMP_VOLUME:
+    case VOLUME:
+        if ((uint32_t(name-VOLUME0) < MAX_NUM_CHANNELS)) {
+            track_t& track = mState.tracks[ mActiveTrack ];
+            if (track.volume[name-VOLUME0] != value) {
+                track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
+                track.volume[name-VOLUME0] = value;
+                if (target == VOLUME) {
+                    track.prevVolume[name-VOLUME0] = value << 16;
+                    track.volumeInc[name-VOLUME0] = 0;
+                } else {
+                    int32_t d = (value<<16) - track.prevVolume[name-VOLUME0];
+                    int32_t volInc = d / int32_t(mState.frameCount);
+                    track.volumeInc[name-VOLUME0] = volInc;
+                    if (volInc == 0) {
+                        track.prevVolume[name-VOLUME0] = value << 16;
+                    }
+                }
+                invalidateState(1<<mActiveTrack);
+            }
+            return NO_ERROR;
+        }
+        break;
+    }
+    return BAD_VALUE;
+}
+
+bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
+{
+    if (value!=devSampleRate || resampler) {
+        if (sampleRate != value) {
+            sampleRate = value;
+            if (resampler == 0) {
+                resampler = AudioResampler::create(
+                        format, channelCount, devSampleRate);
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioMixer::track_t::doesResample() const
+{
+    return resampler != 0;
+}
+
+inline
+void AudioMixer::track_t::adjustVolumeRamp()
+{
+    for (int i=0 ; i<2 ; i++) {
+        if (((volumeInc[i]>0) && ((prevVolume[i]>>16) >= volume[i])) ||
+            ((volumeInc[i]<0) && ((prevVolume[i]>>16) <= volume[i]))) {
+            volumeInc[i] = 0;
+            prevVolume[i] = volume[i]<<16;
+        }
+    }
+}
+
+
+status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
+{
+    mState.tracks[ mActiveTrack ].bufferProvider = buffer;
+    return NO_ERROR;
+}
+
+
+
+void AudioMixer::process(void* output)
+{
+    mState.hook(&mState, output);
+}
+
+
+void AudioMixer::process__validate(state_t* state, void* output)
+{
+    LOGW_IF(!state->needsChanged,
+        "in process__validate() but nothing's invalid");
+
+    uint32_t changed = state->needsChanged;
+    state->needsChanged = 0; // clear the validation flag
+
+    // recompute which tracks are enabled / disabled
+    uint32_t enabled = 0;
+    uint32_t disabled = 0;
+    while (changed) {
+        const int i = 31 - __builtin_clz(changed);
+        const uint32_t mask = 1<<i;
+        changed &= ~mask;
+        track_t& t = state->tracks[i];
+        (t.enabled ? enabled : disabled) |= mask;
+    }
+    state->enabledTracks &= ~disabled;
+    state->enabledTracks |=  enabled;
+
+    // compute everything we need...
+    int countActiveTracks = 0;
+    int all16BitsStereoNoResample = 1;
+    int resampling = 0;
+    int volumeRamp = 0;
+    uint32_t en = state->enabledTracks;
+    while (en) {
+        const int i = 31 - __builtin_clz(en);
+        en &= ~(1<<i);
+
+        countActiveTracks++;
+        track_t& t = state->tracks[i];
+        uint32_t n = 0;
+        n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
+        n |= NEEDS_FORMAT_16;
+        n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
+        
+        if (t.volumeInc[0]|t.volumeInc[1]) {
+            volumeRamp = 1;
+        } else if (!t.doesResample() && t.volumeRL == 0) {
+            n |= NEEDS_MUTE_ENABLED;
+        }
+        t.needs = n;
+
+        if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
+            t.hook = track__nop;
+        } else {
+            if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
+                all16BitsStereoNoResample = 0;
+                resampling = 1;
+                t.hook = track__genericResample;
+            } else {
+                if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
+                    t.hook = track__16BitsMono;
+                    all16BitsStereoNoResample = 0;
+                }
+                if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
+                    t.hook = track__16BitsStereo;
+                }
+            }
+        }
+    }
+
+    // select the processing hooks
+    state->hook = process__nop;
+    if (countActiveTracks) {
+        if (resampling) {
+            if (!state->outputTemp) {
+                state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
+            }
+            if (!state->resampleTemp) {
+                state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
+            }
+            state->hook = process__genericResampling;
+        } else {
+            if (state->outputTemp) {
+                delete [] state->outputTemp;
+                state->outputTemp = 0;
+            }
+            if (state->resampleTemp) {
+                delete [] state->resampleTemp;
+                state->resampleTemp = 0;
+            }
+            state->hook = process__genericNoResampling;
+            if (all16BitsStereoNoResample && !volumeRamp) {
+                if (countActiveTracks == 1) {
+                    state->hook = process__OneTrack16BitsStereoNoResampling;
+                }
+            }
+        }
+    }
+
+    LOGV("mixer configuration change: %d activeTracks (%08x) "
+        "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
+        countActiveTracks, state->enabledTracks,
+        all16BitsStereoNoResample, resampling, volumeRamp);
+
+   state->hook(state, output);
+
+   // Now that the volume ramp has been done, set optimal state and 
+   // track hooks for subsequent mixer process
+   if (countActiveTracks) {
+       int allMuted = 1;
+       uint32_t en = state->enabledTracks;
+       while (en) {
+           const int i = 31 - __builtin_clz(en);
+           en &= ~(1<<i);
+           track_t& t = state->tracks[i];
+           if (!t.doesResample() && t.volumeRL == 0)
+           {
+               t.needs |= NEEDS_MUTE_ENABLED;
+               t.hook = track__nop;
+           } else {
+               allMuted = 0;
+           }
+       }
+       if (allMuted) {
+           state->hook = process__nop;
+       } else if (!resampling && all16BitsStereoNoResample) {
+           if (countActiveTracks == 1) {
+              state->hook = process__OneTrack16BitsStereoNoResampling;
+           }
+       }
+   }
+}
+
+static inline 
+int32_t mulAdd(int16_t in, int16_t v, int32_t a)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    asm( "smlabb %[out], %[in], %[v], %[a] \n"
+         : [out]"=r"(out)
+         : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
+         : );
+    return out;
+#else
+    return a + in * int32_t(v);
+#endif
+}
+
+static inline 
+int32_t mul(int16_t in, int16_t v)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    asm( "smulbb %[out], %[in], %[v] \n"
+         : [out]"=r"(out)
+         : [in]"%r"(in), [v]"r"(v)
+         : );
+    return out;
+#else
+    return in * int32_t(v);
+#endif
+}
+
+static inline 
+int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    if (left) {
+        asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
+             : );
+    } else {
+        asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
+             : );
+    }
+    return out;
+#else
+    if (left) {
+        return a + int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
+    } else {
+        return a + int16_t(inRL>>16) * int16_t(vRL>>16);
+    }
+#endif
+}
+
+static inline 
+int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    if (left) {
+        asm( "smulbb %[out], %[inRL], %[vRL] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL)
+             : );
+    } else {
+        asm( "smultt %[out], %[inRL], %[vRL] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL)
+             : );
+    }
+    return out;
+#else
+    if (left) {
+        return int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
+    } else {
+        return int16_t(inRL>>16) * int16_t(vRL>>16);
+    }
+#endif
+}
+
+
+void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp)
+{
+    t->resampler->setSampleRate(t->sampleRate);
+
+    // ramp gain - resample to temp buffer and scale/mix in 2nd step
+    if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
+        t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
+        memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
+        t->resampler->resample(temp, outFrameCount, t->bufferProvider);
+        volumeRampStereo(t, out, outFrameCount, temp);
+    }
+
+    // constant gain
+    else {
+        t->resampler->setVolume(t->volume[0], t->volume[1]);
+        t->resampler->resample(out, outFrameCount, t->bufferProvider);
+    }
+}
+
+void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp)
+{
+}
+
+void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp)
+{
+    int32_t vl = t->prevVolume[0];
+    int32_t vr = t->prevVolume[1];
+    const int32_t vlInc = t->volumeInc[0];
+    const int32_t vrInc = t->volumeInc[1];
+
+    //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+    //        t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+    //       (vl + vlInc*frameCount)/65536.0f, frameCount);
+    
+    // ramp volume
+    do {
+        *out++ += (vl >> 16) * (*temp++ >> 12);
+        *out++ += (vr >> 16) * (*temp++ >> 12);
+        vl += vlInc;
+        vr += vrInc;
+    } while (--frameCount);
+
+    t->prevVolume[0] = vl;
+    t->prevVolume[1] = vr;
+    t->adjustVolumeRamp();
+}
+
+void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp)
+{
+    int16_t const *in = static_cast<int16_t const *>(t->in);
+
+    // ramp gain
+    if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
+        int32_t vl = t->prevVolume[0];
+        int32_t vr = t->prevVolume[1];
+        const int32_t vlInc = t->volumeInc[0];
+        const int32_t vrInc = t->volumeInc[1];
+
+        // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+        //        t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+        //        (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+        do {
+            *out++ += (vl >> 16) * (int32_t) *in++;
+            *out++ += (vr >> 16) * (int32_t) *in++;
+            vl += vlInc;
+            vr += vrInc;
+        } while (--frameCount);
+        
+        t->prevVolume[0] = vl;
+        t->prevVolume[1] = vr;
+        t->adjustVolumeRamp();
+    }
+
+    // constant gain
+    else {
+        const uint32_t vrl = t->volumeRL;
+        do {
+            uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
+            in += 2;
+            out[0] = mulAddRL(1, rl, vrl, out[0]);
+            out[1] = mulAddRL(0, rl, vrl, out[1]);
+            out += 2;
+        } while (--frameCount);
+    }
+    t->in = in;
+}
+
+void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp)
+{
+    int16_t const *in = static_cast<int16_t const *>(t->in);
+
+    // ramp gain
+    if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
+        int32_t vl = t->prevVolume[0];
+        int32_t vr = t->prevVolume[1];
+        const int32_t vlInc = t->volumeInc[0];
+        const int32_t vrInc = t->volumeInc[1];
+
+        // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+        //         t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+        //         (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+        do {
+            int32_t l = *in++;
+            *out++ += (vl >> 16) * l;
+            *out++ += (vr >> 16) * l;
+            vl += vlInc;
+            vr += vrInc;
+        } while (--frameCount);
+        
+        t->prevVolume[0] = vl;
+        t->prevVolume[1] = vr;
+        t->adjustVolumeRamp();
+    }
+    // constant gain
+    else {
+        const int16_t vl = t->volume[0];
+        const int16_t vr = t->volume[1];
+        do {
+            int16_t l = *in++;
+            out[0] = mulAdd(l, vl, out[0]);
+            out[1] = mulAdd(l, vr, out[1]);
+            out += 2;
+        } while (--frameCount);
+    }
+    t->in = in;
+}
+
+inline 
+void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c)
+{
+    for (size_t i=0 ; i<c ; i++) {
+        int32_t l = *sums++;
+        int32_t r = *sums++;
+        int32_t nl = l >> 12;
+        int32_t nr = r >> 12;
+        l = clamp16(nl);
+        r = clamp16(nr);
+        *out++ = (r<<16) | (l & 0xFFFF);
+    }
+}
+
+// no-op case
+void AudioMixer::process__nop(state_t* state, void* output)
+{
+    // this assumes output 16 bits stereo, no resampling
+    memset(output, 0, state->frameCount*4);
+    uint32_t en = state->enabledTracks;
+    while (en) {
+        const int i = 31 - __builtin_clz(en);
+        en &= ~(1<<i);
+        track_t& t = state->tracks[i];
+        t.bufferProvider->getNextBuffer(&t.buffer);
+        if (t.buffer.raw) {
+            t.bufferProvider->releaseBuffer(&t.buffer);
+        }
+    }
+}
+
+// generic code without resampling
+void AudioMixer::process__genericNoResampling(state_t* state, void* output)
+{
+    int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
+
+    // acquire each track's buffer
+    uint32_t enabledTracks = state->enabledTracks;
+    uint32_t en = enabledTracks;
+    while (en) {
+        const int i = 31 - __builtin_clz(en);
+        en &= ~(1<<i);
+        track_t& t = state->tracks[i];
+        t.bufferProvider->getNextBuffer(&t.buffer);
+        t.in = t.buffer.raw;
+        // t.in == NULL can happen if the track was flushed just after having
+        // been enabled for mixing.
+        if (t.in == NULL)
+            enabledTracks &= ~(1<<i); 
+    }
+
+    // this assumes output 16 bits stereo, no resampling
+    int32_t* out = static_cast<int32_t*>(output);
+    size_t numFrames = state->frameCount;
+    do {
+        memset(outTemp, 0, sizeof(outTemp));
+
+        en = enabledTracks;
+        while (en) {
+            const int i = 31 - __builtin_clz(en);
+            en &= ~(1<<i);
+            track_t& t = state->tracks[i];
+            (t.hook)(&t, outTemp, BLOCKSIZE, state->resampleTemp);
+        }
+
+        ditherAndClamp(out, outTemp, BLOCKSIZE);
+        out += BLOCKSIZE;
+
+        numFrames -= BLOCKSIZE;
+    } while (numFrames);
+
+
+    // release each track's buffer
+    en = enabledTracks;
+    while (en) {
+        const int i = 31 - __builtin_clz(en);
+        en &= ~(1<<i);
+        track_t& t = state->tracks[i];
+        t.bufferProvider->releaseBuffer(&t.buffer);
+    }
+}
+
+// generic code with resampling
+void AudioMixer::process__genericResampling(state_t* state, void* output)
+{
+    int32_t* const outTemp = state->outputTemp;
+    const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
+    memset(outTemp, 0, size);
+
+    int32_t* out = static_cast<int32_t*>(output);
+    size_t numFrames = state->frameCount;
+
+    uint32_t en = state->enabledTracks;
+    while (en) {
+        const int i = 31 - __builtin_clz(en);
+        en &= ~(1<<i);
+        track_t& t = state->tracks[i];
+
+        // this is a little goofy, on the resampling case we don't
+        // acquire/release the buffers because it's done by
+        // the resampler.
+        if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
+            (t.hook)(&t, outTemp, numFrames, state->resampleTemp);
+        } else {
+            t.bufferProvider->getNextBuffer(&t.buffer);
+            t.in = t.buffer.raw;
+            // t.in == NULL can happen if the track was flushed just after having
+            // been enabled for mixing.
+            if (t.in) {
+                (t.hook)(&t, outTemp, numFrames, state->resampleTemp);
+                t.bufferProvider->releaseBuffer(&t.buffer);
+            }
+        }
+    }
+
+    ditherAndClamp(out, outTemp, numFrames);
+}
+
+// one track, 16 bits stereo without resampling is the most common case
+void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state, void* output)
+{
+    const int i = 31 - __builtin_clz(state->enabledTracks);
+    const track_t& t = state->tracks[i];
+
+    AudioBufferProvider::Buffer& b(t.buffer);
+    t.bufferProvider->getNextBuffer(&b);
+    int16_t const *in = t.buffer.i16;
+
+    // in == NULL can happen if the track was flushed just after having
+    // been enabled for mixing.
+    if (in == NULL) {
+        memset(output, 0, state->frameCount*MAX_NUM_CHANNELS*sizeof(int16_t));
+        return;
+    }
+    
+    int32_t* out = static_cast<int32_t*>(output);
+    size_t numFrames = state->frameCount;
+    const int16_t vl = t.volume[0];
+    const int16_t vr = t.volume[1];
+    const uint32_t vrl = t.volumeRL;
+    if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
+        // volume is boosted, so we might need to clamp even though
+        // we process only one track.
+        do {
+            uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
+            in += 2;
+            int32_t l = mulRL(1, rl, vrl) >> 12;
+            int32_t r = mulRL(0, rl, vrl) >> 12;
+            // clamping...
+            l = clamp16(l);
+            r = clamp16(r);
+            *out++ = (r<<16) | (l & 0xFFFF);
+        } while (--numFrames);
+    } else {
+        do {
+            uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
+            in += 2;
+            int32_t l = mulRL(1, rl, vrl) >> 12;
+            int32_t r = mulRL(0, rl, vrl) >> 12;
+            *out++ = (r<<16) | (l & 0xFFFF);
+        } while (--numFrames);
+    }
+
+    t.bufferProvider->releaseBuffer(&b);
+}
+
+// 2 tracks is also a common case
+void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state, void* output)
+{
+    int i;
+    uint32_t en = state->enabledTracks;
+
+    i = 31 - __builtin_clz(en);
+    const track_t& t0 = state->tracks[i];
+    AudioBufferProvider::Buffer& b0(t0.buffer);
+    t0.bufferProvider->getNextBuffer(&b0);
+
+    en &= ~(1<<i);
+    i = 31 - __builtin_clz(en);
+    const track_t& t1 = state->tracks[i];
+    AudioBufferProvider::Buffer& b1(t1.buffer);
+    t1.bufferProvider->getNextBuffer(&b1);
+
+    int16_t const *in0;
+    const int16_t vl0 = t0.volume[0];
+    const int16_t vr0 = t0.volume[1];
+    int16_t const *in1;
+    const int16_t vl1 = t1.volume[0];
+    const int16_t vr1 = t1.volume[1];
+    size_t numFrames = state->frameCount;
+    int32_t* out = static_cast<int32_t*>(output);
+
+    // t0/1.buffer.i16 == NULL can happen if the track was flushed just after having
+    // been enabled for mixing.
+    if (t0.buffer.i16 != NULL) {
+        in0 = t0.buffer.i16;
+        if (t1.buffer.i16 != NULL) {
+            in1 = t1.buffer.i16;
+        } else {
+            in1 = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
+            memset((void *)in1, 0, state->frameCount*MAX_NUM_CHANNELS*sizeof(int16_t));
+        }
+    } else {
+        in0 = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
+        memset((void *)in0, 0, state->frameCount*MAX_NUM_CHANNELS*sizeof(int16_t));
+        if (t1.buffer.i16 != NULL) {
+            in1 = t1.buffer.i16;
+        } else {
+            in1 = in0;
+        }
+    }
+    
+    do {
+        int32_t l0 = *in0++;
+        int32_t r0 = *in0++;
+        l0 = mul(l0, vl0);
+        r0 = mul(r0, vr0);
+        int32_t l = *in1++;
+        int32_t r = *in1++;
+        l = mulAdd(l, vl1, l0) >> 12;
+        r = mulAdd(r, vr1, r0) >> 12;
+        // clamping...
+        l = clamp16(l);
+        r = clamp16(r);
+        *out++ = (r<<16) | (l & 0xFFFF);
+    } while (--numFrames);
+
+    
+    if (t0.buffer.i16 != NULL) {
+        t0.bufferProvider->releaseBuffer(&b0);
+        if (t1.buffer.i16 != NULL) {
+            t1.bufferProvider->releaseBuffer(&b1);
+        } else {
+            delete [] in1;
+        }
+    } else {
+        delete [] in0;
+        if (t1.buffer.i16 != NULL) {
+            t1.bufferProvider->releaseBuffer(&b1);
+        }
+    }
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+