Add and enable floating point option for audio resampler

Can be tested with test-resample.

Change-Id: I8339846d7c647444b6025d33cfa145d5d3658121
Signed-off-by: Andy Hung <hunga@google.com>
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index ca98f16..562c4ea 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -234,7 +234,16 @@
     case DYN_MED_QUALITY:
     case DYN_HIGH_QUALITY:
         ALOGV("Create dynamic Resampler = %d", quality);
-        resampler = new AudioResamplerDyn(bitDepth, inChannelCount, sampleRate, quality);
+        if (bitDepth == 32) { /* bitDepth == 32 signals float precision */
+            resampler = new AudioResamplerDyn<float, float, float>(bitDepth, inChannelCount,
+                    sampleRate, quality);
+        } else if (quality == DYN_HIGH_QUALITY) {
+            resampler = new AudioResamplerDyn<int32_t, int16_t, int32_t>(bitDepth, inChannelCount,
+                    sampleRate, quality);
+        } else {
+            resampler = new AudioResamplerDyn<int16_t, int16_t, int32_t>(bitDepth, inChannelCount,
+                    sampleRate, quality);
+        }
         break;
     }
 
diff --git a/services/audioflinger/AudioResamplerDyn.cpp b/services/audioflinger/AudioResamplerDyn.cpp
index 173a243..3abe8fd 100644
--- a/services/audioflinger/AudioResamplerDyn.cpp
+++ b/services/audioflinger/AudioResamplerDyn.cpp
@@ -39,9 +39,9 @@
 namespace android {
 
 // generate a unique resample type compile-time constant (constexpr)
-#define RESAMPLETYPE(CHANNELS, LOCKED, STRIDE, COEFTYPE) \
-    ((((CHANNELS)-1)&1) | !!(LOCKED)<<1 | (COEFTYPE)<<2 \
-    | ((STRIDE)==8 ? 1 : (STRIDE)==16 ? 2 : 0)<<3)
+#define RESAMPLETYPE(CHANNELS, LOCKED, STRIDE) \
+    ((((CHANNELS)-1)&1) | !!(LOCKED)<<1 \
+    | ((STRIDE)==8 ? 1 : (STRIDE)==16 ? 2 : 0)<<2)
 
 /*
  * InBuffer is a type agnostic input buffer.
@@ -59,42 +59,46 @@
  * r = extra space for implementing the ring buffer
  */
 
-template<typename TI>
-AudioResamplerDyn::InBuffer<TI>::InBuffer()
-    : mState(NULL), mImpulse(NULL), mRingFull(NULL), mStateSize(0) {
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::InBuffer::InBuffer()
+    : mState(NULL), mImpulse(NULL), mRingFull(NULL), mStateCount(0)
+{
 }
 
-template<typename TI>
-AudioResamplerDyn::InBuffer<TI>::~InBuffer() {
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::InBuffer::~InBuffer()
+{
     init();
 }
 
-template<typename TI>
-void AudioResamplerDyn::InBuffer<TI>::init() {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::init()
+{
     free(mState);
     mState = NULL;
     mImpulse = NULL;
     mRingFull = NULL;
-    mStateSize = 0;
+    mStateCount = 0;
 }
 
 // resizes the state buffer to accommodate the appropriate filter length
-template<typename TI>
-void AudioResamplerDyn::InBuffer<TI>::resize(int CHANNELS, int halfNumCoefs) {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::resize(int CHANNELS, int halfNumCoefs)
+{
     // calculate desired state size
-    int stateSize = halfNumCoefs * CHANNELS * 2
-            * kStateSizeMultipleOfFilterLength;
+    int stateCount = halfNumCoefs * CHANNELS * 2 * kStateSizeMultipleOfFilterLength;
 
     // check if buffer needs resizing
     if (mState
-            && stateSize == mStateSize
-            && mRingFull-mState == mStateSize-halfNumCoefs*CHANNELS) {
+            && stateCount == mStateCount
+            && mRingFull-mState == mStateCount-halfNumCoefs*CHANNELS) {
         return;
     }
 
     // create new buffer
-    TI* state = (int16_t*)memalign(32, stateSize*sizeof(*state));
-    memset(state, 0, stateSize*sizeof(*state));
+    TI* state;
+    (void)posix_memalign(reinterpret_cast<void**>(&state), 32, stateCount*sizeof(*state));
+    memset(state, 0, stateCount*sizeof(*state));
 
     // attempt to preserve state
     if (mState) {
@@ -106,8 +110,8 @@
             dst += mState-srcLo;
             srcLo = mState;
         }
-        if (srcHi > mState + mStateSize) {
-            srcHi = mState + mStateSize;
+        if (srcHi > mState + mStateCount) {
+            srcHi = mState + mStateCount;
         }
         memcpy(dst, srcLo, (srcHi - srcLo) * sizeof(*srcLo));
         free(mState);
@@ -115,27 +119,29 @@
 
     // set class member vars
     mState = state;
-    mStateSize = stateSize;
-    mImpulse = mState + halfNumCoefs*CHANNELS; // actually one sample greater than needed
-    mRingFull = mState + mStateSize - halfNumCoefs*CHANNELS;
+    mStateCount = stateCount;
+    mImpulse = state + halfNumCoefs*CHANNELS; // actually one sample greater than needed
+    mRingFull = state + mStateCount - halfNumCoefs*CHANNELS;
 }
 
 // copy in the input data into the head (impulse+halfNumCoefs) of the buffer.
-template<typename TI>
+template<typename TC, typename TI, typename TO>
 template<int CHANNELS>
-void AudioResamplerDyn::InBuffer<TI>::readAgain(TI*& impulse, const int halfNumCoefs,
-        const TI* const in, const size_t inputIndex) {
-    int16_t* head = impulse + halfNumCoefs*CHANNELS;
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::readAgain(TI*& impulse, const int halfNumCoefs,
+        const TI* const in, const size_t inputIndex)
+{
+    TI* head = impulse + halfNumCoefs*CHANNELS;
     for (size_t i=0 ; i<CHANNELS ; i++) {
         head[i] = in[inputIndex*CHANNELS + i];
     }
 }
 
 // advance the impulse pointer, and load in data into the head (impulse+halfNumCoefs)
-template<typename TI>
+template<typename TC, typename TI, typename TO>
 template<int CHANNELS>
-void AudioResamplerDyn::InBuffer<TI>::readAdvance(TI*& impulse, const int halfNumCoefs,
-        const TI* const in, const size_t inputIndex) {
+void AudioResamplerDyn<TC, TI, TO>::InBuffer::readAdvance(TI*& impulse, const int halfNumCoefs,
+        const TI* const in, const size_t inputIndex)
+{
     impulse += CHANNELS;
 
     if (CC_UNLIKELY(impulse >= mRingFull)) {
@@ -146,7 +152,8 @@
     readAgain<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
 }
 
-void AudioResamplerDyn::Constants::set(
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::Constants::set(
         int L, int halfNumCoefs, int inSampleRate, int outSampleRate)
 {
     int bits = 0;
@@ -159,10 +166,11 @@
     mHalfNumCoefs = halfNumCoefs;
 }
 
-AudioResamplerDyn::AudioResamplerDyn(int bitDepth,
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::AudioResamplerDyn(int bitDepth,
         int inChannelCount, int32_t sampleRate, src_quality quality)
     : AudioResampler(bitDepth, inChannelCount, sampleRate, quality),
-    mResampleType(0), mFilterSampleRate(0), mFilterQuality(DEFAULT_QUALITY),
+      mResampleFunc(0), mFilterSampleRate(0), mFilterQuality(DEFAULT_QUALITY),
     mCoefBuffer(NULL)
 {
     mVolumeSimd[0] = mVolumeSimd[1] = 0;
@@ -173,33 +181,48 @@
     mConstants.set(128, 8, mSampleRate, mSampleRate); // TODO: set better
 }
 
-AudioResamplerDyn::~AudioResamplerDyn() {
+template<typename TC, typename TI, typename TO>
+AudioResamplerDyn<TC, TI, TO>::~AudioResamplerDyn()
+{
     free(mCoefBuffer);
 }
 
-void AudioResamplerDyn::init() {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::init()
+{
     mFilterSampleRate = 0; // always trigger new filter generation
     mInBuffer.init();
 }
 
-void AudioResamplerDyn::setVolume(int16_t left, int16_t right) {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::setVolume(int16_t left, int16_t right)
+{
     AudioResampler::setVolume(left, right);
-    mVolumeSimd[0] = static_cast<int32_t>(left)<<16;
-    mVolumeSimd[1] = static_cast<int32_t>(right)<<16;
+    // volume is applied on the output type.
+    if (is_same<TO, float>::value || is_same<TO, double>::value) {
+        const TO scale = 1. / (1UL << 12);
+        mVolumeSimd[0] = static_cast<TO>(left) * scale;
+        mVolumeSimd[1] = static_cast<TO>(right) * scale;
+    } else {
+        mVolumeSimd[0] = static_cast<int32_t>(left) << 16;
+        mVolumeSimd[1] = static_cast<int32_t>(right) << 16;
+    }
 }
 
-template <typename T> T max(T a, T b) {return a > b ? a : b;}
+template<typename T> T max(T a, T b) {return a > b ? a : b;}
 
-template <typename T> T absdiff(T a, T b) {return a > b ? a - b : b - a;}
+template<typename T> T absdiff(T a, T b) {return a > b ? a - b : b - a;}
 
-template<typename T>
-void AudioResamplerDyn::createKaiserFir(Constants &c, double stopBandAtten,
-        int inSampleRate, int outSampleRate, double tbwCheat) {
-    T* buf = reinterpret_cast<T*>(memalign(32, (c.mL+1)*c.mHalfNumCoefs*sizeof(T)));
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::createKaiserFir(Constants &c,
+        double stopBandAtten, int inSampleRate, int outSampleRate, double tbwCheat)
+{
+    TC* buf;
     static const double atten = 0.9998;   // to avoid ripple overflow
     double fcr;
     double tbw = firKaiserTbw(c.mHalfNumCoefs, stopBandAtten);
 
+    (void)posix_memalign(reinterpret_cast<void**>(&buf), 32, (c.mL+1)*c.mHalfNumCoefs*sizeof(TC));
     if (inSampleRate < outSampleRate) { // upsample
         fcr = max(0.5*tbwCheat - tbw/2, tbw/2);
     } else { // downsample
@@ -207,7 +230,7 @@
     }
     // create and set filter
     firKaiserGen(buf, c.mL, c.mHalfNumCoefs, stopBandAtten, fcr, atten);
-    c.setBuf(buf);
+    c.mFirCoefs = buf;
     if (mCoefBuffer) {
         free(mCoefBuffer);
     }
@@ -229,7 +252,8 @@
 }
 
 // recursive gcd. Using objdump, it appears the tail recursion is converted to a while loop.
-static int gcd(int n, int m) {
+static int gcd(int n, int m)
+{
     if (m == 0) {
         return n;
     }
@@ -237,7 +261,8 @@
 }
 
 static bool isClose(int32_t newSampleRate, int32_t prevSampleRate,
-        int32_t filterSampleRate, int32_t outSampleRate) {
+        int32_t filterSampleRate, int32_t outSampleRate)
+{
 
     // different upsampling ratios do not need a filter change.
     if (filterSampleRate != 0
@@ -254,7 +279,9 @@
     return pdiff < prevSampleRate>>4 && adiff < filterSampleRate>>3;
 }
 
-void AudioResamplerDyn::setSampleRate(int32_t inSampleRate) {
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::setSampleRate(int32_t inSampleRate)
+{
     if (mInSampleRate == inSampleRate) {
         return;
     }
@@ -358,13 +385,8 @@
 
         // create the filter
         mConstants.set(phases, halfLength, inSampleRate, mSampleRate);
-        if (useS32) {
-            createKaiserFir<int32_t>(mConstants, stopBandAtten,
-                    inSampleRate, mSampleRate, tbwCheat);
-        } else {
-            createKaiserFir<int16_t>(mConstants, stopBandAtten,
-                    inSampleRate, mSampleRate, tbwCheat);
-        }
+        createKaiserFir(mConstants, stopBandAtten,
+                inSampleRate, mSampleRate, tbwCheat);
     } // End Kaiser filter
 
     // update phase and state based on the new filter.
@@ -386,7 +408,7 @@
         mPhaseFraction = mPhaseFraction >> c.mShift << c.mShift; // remove fractional phase
     }
 
-    mResampleType = RESAMPLETYPE(mChannelCount, locked, stride, !!useS32);
+    setResampler(RESAMPLETYPE(mChannelCount, locked, stride));
 #ifdef DEBUG_RESAMPLER
     printf("channels:%d  %s  stride:%d  %s  coef:%d  shift:%d\n",
             mChannelCount, locked ? "locked" : "interpolated",
@@ -394,78 +416,45 @@
 #endif
 }
 
-void AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount,
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::resample(int32_t* out, size_t outFrameCount,
             AudioBufferProvider* provider)
 {
-    // TODO:
-    // 24 cases - this perhaps can be reduced later, as testing might take too long
-    switch (mResampleType) {
+    (this->*mResampleFunc)(reinterpret_cast<TO*>(out), outFrameCount, provider);
+}
 
+template<typename TC, typename TI, typename TO>
+void AudioResamplerDyn<TC, TI, TO>::setResampler(unsigned resampleType)
+{
     // stride 16 (falls back to stride 2 for machines that do not support NEON)
-    case RESAMPLETYPE(1, true, 16, 0):
-        return resample<1, true, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, true, 16, 0):
-        return resample<2, true, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, false, 16, 0):
-        return resample<1, false, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, false, 16, 0):
-        return resample<2, false, 16>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, true, 16, 1):
-        return resample<1, true, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, true, 16, 1):
-        return resample<2, true, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(1, false, 16, 1):
-        return resample<1, false, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, false, 16, 1):
-        return resample<2, false, 16>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-#if 0
-    // TODO: Remove these?
-    // stride 8
-    case RESAMPLETYPE(1, true, 8, 0):
-        return resample<1, true, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, true, 8, 0):
-        return resample<2, true, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, false, 8, 0):
-        return resample<1, false, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, false, 8, 0):
-        return resample<2, false, 8>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, true, 8, 1):
-        return resample<1, true, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, true, 8, 1):
-        return resample<2, true, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(1, false, 8, 1):
-        return resample<1, false, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, false, 8, 1):
-        return resample<2, false, 8>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    // stride 2 (can handle any filter length)
-    case RESAMPLETYPE(1, true, 2, 0):
-        return resample<1, true, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, true, 2, 0):
-        return resample<2, true, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, false, 2, 0):
-        return resample<1, false, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(2, false, 2, 0):
-        return resample<2, false, 2>(out, outFrameCount, mConstants.mFirCoefsS16, provider);
-    case RESAMPLETYPE(1, true, 2, 1):
-        return resample<1, true, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, true, 2, 1):
-        return resample<2, true, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(1, false, 2, 1):
-        return resample<1, false, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-    case RESAMPLETYPE(2, false, 2, 1):
-        return resample<2, false, 2>(out, outFrameCount, mConstants.mFirCoefsS32, provider);
-#endif
+    switch (resampleType) {
+    case RESAMPLETYPE(1, true, 16):
+        mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, true, 16>;
+        return;
+    case RESAMPLETYPE(2, true, 16):
+        mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, true, 16>;
+        return;
+    case RESAMPLETYPE(1, false, 16):
+        mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, false, 16>;
+        return;
+    case RESAMPLETYPE(2, false, 16):
+        mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, false, 16>;
+        return;
     default:
-        ; // error
+        LOG_ALWAYS_FATAL("Invalid resampler type: %u", resampleType);
+        mResampleFunc = NULL;
+        return;
     }
 }
 
-template<int CHANNELS, bool LOCKED, int STRIDE, typename TC>
-void AudioResamplerDyn::resample(int32_t* out, size_t outFrameCount,
-        const TC* const coefs,  AudioBufferProvider* provider)
+template<typename TC, typename TI, typename TO>
+template<int CHANNELS, bool LOCKED, int STRIDE>
+void AudioResamplerDyn<TC, TI, TO>::resample(TO* out, size_t outFrameCount,
+        AudioBufferProvider* provider)
 {
     const Constants& c(mConstants);
-    int16_t* impulse = mInBuffer.getImpulse();
+    const TC* const coefs = mConstants.mFirCoefs;
+    TI* impulse = mInBuffer.getImpulse();
     size_t inputIndex = mInputIndex;
     uint32_t phaseFraction = mPhaseFraction;
     const uint32_t phaseIncrement = mPhaseIncrement;
@@ -491,8 +480,9 @@
                 goto resample_exit;
             }
             if (phaseFraction >= phaseWrapLimit) { // read in data
-                mInBuffer.readAdvance<CHANNELS>(
-                        impulse, c.mHalfNumCoefs, mBuffer.i16, inputIndex);
+                mInBuffer.template readAdvance<CHANNELS>(
+                        impulse, c.mHalfNumCoefs,
+                        reinterpret_cast<TI*>(mBuffer.raw), inputIndex);
                 phaseFraction -= phaseWrapLimit;
                 while (phaseFraction >= phaseWrapLimit) {
                     inputIndex++;
@@ -501,20 +491,21 @@
                         provider->releaseBuffer(&mBuffer);
                         break;
                     }
-                    mInBuffer.readAdvance<CHANNELS>(
-                            impulse, c.mHalfNumCoefs, mBuffer.i16, inputIndex);
+                    mInBuffer.template readAdvance<CHANNELS>(
+                            impulse, c.mHalfNumCoefs,
+                            reinterpret_cast<TI*>(mBuffer.raw), inputIndex);
                     phaseFraction -= phaseWrapLimit;
                 }
             }
         }
-        const int16_t* const in = mBuffer.i16;
+        const TI* const in = reinterpret_cast<const TI*>(mBuffer.raw);
         const size_t frameCount = mBuffer.frameCount;
         const int coefShift = c.mShift;
         const int halfNumCoefs = c.mHalfNumCoefs;
-        const int32_t* const volumeSimd = mVolumeSimd;
+        const TO* const volumeSimd = mVolumeSimd;
 
         // reread the last input in.
-        mInBuffer.readAgain<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
+        mInBuffer.template readAgain<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
 
         // main processing loop
         while (CC_LIKELY(outputIndex < outputSampleCount)) {
@@ -537,7 +528,7 @@
                 if (inputIndex >= frameCount) {
                     goto done;  // need a new buffer
                 }
-                mInBuffer.readAdvance<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
+                mInBuffer.template readAdvance<CHANNELS>(impulse, halfNumCoefs, in, inputIndex);
                 phaseFraction -= phaseWrapLimit;
             }
         }
@@ -556,5 +547,10 @@
     mPhaseFraction = phaseFraction;
 }
 
+/* instantiate templates used by AudioResampler::create */
+template class AudioResamplerDyn<float, float, float>;
+template class AudioResamplerDyn<int16_t, int16_t, int32_t>;
+template class AudioResamplerDyn<int32_t, int16_t, int32_t>;
+
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/audioflinger/AudioResamplerDyn.h b/services/audioflinger/AudioResamplerDyn.h
index df1fdbe..8c56319 100644
--- a/services/audioflinger/AudioResamplerDyn.h
+++ b/services/audioflinger/AudioResamplerDyn.h
@@ -25,10 +25,24 @@
 
 namespace android {
 
+/* AudioResamplerDyn
+ *
+ * This class template is used for floating point and integer resamplers.
+ *
+ * Type variables:
+ * TC = filter coefficient type (one of int16_t, int32_t, or float)
+ * TI = input data type (one of int16_t or float)
+ * TO = output data type (one of int32_t or float)
+ *
+ * For integer input data types TI, the coefficient type TC is either int16_t or int32_t.
+ * For float input data types TI, the coefficient type TC is float.
+ */
+
+template<typename TC, typename TI, typename TO>
 class AudioResamplerDyn: public AudioResampler {
 public:
-    AudioResamplerDyn(int bitDepth, int inChannelCount, int32_t sampleRate,
-            src_quality quality);
+    AudioResamplerDyn(int bitDepth, int inChannelCount,
+            int32_t sampleRate, src_quality quality);
 
     virtual ~AudioResamplerDyn();
 
@@ -46,46 +60,38 @@
     class Constants { // stores the filter constants.
     public:
         Constants() :
-            mL(0), mShift(0), mHalfNumCoefs(0), mFirCoefsS16(NULL)
+            mL(0), mShift(0), mHalfNumCoefs(0), mFirCoefs(NULL)
         {}
         void set(int L, int halfNumCoefs,
                 int inSampleRate, int outSampleRate);
-        inline void setBuf(int16_t* buf) {
-            mFirCoefsS16 = buf;
-        }
-        inline void setBuf(int32_t* buf) {
-            mFirCoefsS32 = buf;
-        }
 
-        int mL;       // interpolation phases in the filter.
-        int mShift;   // right shift to get polyphase index
+                 int mL;            // interpolation phases in the filter.
+                 int mShift;        // right shift to get polyphase index
         unsigned int mHalfNumCoefs; // filter half #coefs
-        union {       // polyphase filter bank
-            const int16_t* mFirCoefsS16;
-            const int32_t* mFirCoefsS32;
-        };
+           const TC* mFirCoefs;     // polyphase filter bank
     };
 
-    // Input buffer management for a given input type TI, now (int16_t)
-    // Is agnostic of the actual type, can work with int32_t and float.
-    template<typename TI>
-    class InBuffer {
+    class InBuffer { // buffer management for input type TI
     public:
         InBuffer();
         ~InBuffer();
         void init();
+
         void resize(int CHANNELS, int halfNumCoefs);
 
         // used for direct management of the mImpulse pointer
         inline TI* getImpulse() {
             return mImpulse;
         }
+
         inline void setImpulse(TI *impulse) {
             mImpulse = impulse;
         }
+
         template<int CHANNELS>
         inline void readAgain(TI*& impulse, const int halfNumCoefs,
                 const TI* const in, const size_t inputIndex);
+
         template<int CHANNELS>
         inline void readAdvance(TI*& impulse, const int halfNumCoefs,
                 const TI* const in, const size_t inputIndex);
@@ -94,31 +100,35 @@
         // tuning parameter guidelines: 2 <= multiple <= 8
         static const int kStateSizeMultipleOfFilterLength = 4;
 
-        TI* mState;    // base pointer for the input buffer storage
-        TI* mImpulse;  // current location of the impulse response (centered)
-        TI* mRingFull; // mState <= mImpulse < mRingFull
         // in general, mRingFull = mState + mStateSize - halfNumCoefs*CHANNELS.
-        size_t mStateSize; // in units of TI.
+           TI* mState;      // base pointer for the input buffer storage
+           TI* mImpulse;    // current location of the impulse response (centered)
+           TI* mRingFull;   // mState <= mImpulse < mRingFull
+        size_t mStateCount; // size of state in units of TI.
     };
 
-    template<int CHANNELS, bool LOCKED, int STRIDE, typename TC>
-    void resample(int32_t* out, size_t outFrameCount,
-            const TC* const coefs, AudioBufferProvider* provider);
-
-    template<typename T>
     void createKaiserFir(Constants &c, double stopBandAtten,
             int inSampleRate, int outSampleRate, double tbwCheat);
 
-    InBuffer<int16_t> mInBuffer;
-    Constants mConstants;  // current set of coefficient parameters
-    int32_t __attribute__ ((aligned (8))) mVolumeSimd[2];
-    int32_t mResampleType; // contains the resample type.
-    int32_t mFilterSampleRate; // designed filter sample rate.
-    src_quality mFilterQuality; // designed filter quality.
-    void* mCoefBuffer; // if a filter is created, this is not null
+    void setResampler(unsigned resampleType);
+
+    template<int CHANNELS, bool LOCKED, int STRIDE>
+    void resample(TO* out, size_t outFrameCount, AudioBufferProvider* provider);
+
+    // declare a pointer to member function for resample
+    typedef void (AudioResamplerDyn<TC, TI, TO>::*resample_ABP_t)(TO* out,
+            size_t outFrameCount, AudioBufferProvider* provider);
+
+    // data - the contiguous storage and layout of these is important.
+           InBuffer mInBuffer;
+          Constants mConstants;        // current set of coefficient parameters
+    TO __attribute__ ((aligned (8))) mVolumeSimd[2]; // must be aligned or NEON may crash
+     resample_ABP_t mResampleFunc;     // called function for resampling
+            int32_t mFilterSampleRate; // designed filter sample rate.
+        src_quality mFilterQuality;    // designed filter quality.
+              void* mCoefBuffer;       // if a filter is created, this is not null
 };
 
-// ----------------------------------------------------------------------------
 }; // namespace android
 
 #endif /*ANDROID_AUDIO_RESAMPLER_DYN_H*/