audioflinger: use resample coefficients from audio-resampler library.

-Add a separate quality VERY_HIGH_QUALITY in resampler
-Use resample coefficients audio-resampler library for
 quality VERY_HIGH_QUALITY.
-This improves the quality of resampled output.

Bug: 7024293
Change-Id: Ia44142413bed5f5963d7eab7846eec877a2415e4
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 66759d1..b9e32381 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -18,8 +18,8 @@
     AudioMixer.cpp.arm          \
     AudioResampler.cpp.arm      \
     AudioPolicyService.cpp      \
-    ServiceUtilities.cpp
-#   AudioResamplerSinc.cpp.arm
+    ServiceUtilities.cpp        \
+    AudioResamplerSinc.cpp.arm
 #   AudioResamplerCubic.cpp.arm
 
 LOCAL_SRC_FILES += StateQueue.cpp
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index fbb54cf..5c1c905 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -23,8 +23,8 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 #include "AudioResampler.h"
-#if 0
 #include "AudioResamplerSinc.h"
+#if 0
 #include "AudioResamplerCubic.h"
 #endif
 
@@ -106,11 +106,14 @@
         ALOGV("Create cubic Resampler");
         resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate);
         break;
-    case HIGH_QUALITY:
-        ALOGV("Create sinc Resampler");
-        resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate);
-        break;
 #endif
+    case HIGH_QUALITY:
+        ALOGV("Create HIGH_QUALITY sinc Resampler");
+        resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate);
+    case VERY_HIGH_QUALITY:
+        ALOGV("Create VERY_HIGH_QUALITY sinc Resampler = %d",quality);
+        resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate, quality);
+        break;
     }
 
     // initialize resampler
diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h
index dc696d8..71cdfda 100644
--- a/services/audioflinger/AudioResampler.h
+++ b/services/audioflinger/AudioResampler.h
@@ -38,7 +38,8 @@
         DEFAULT=0,
         LOW_QUALITY=1,
         MED_QUALITY=2,
-        HIGH_QUALITY=3
+        HIGH_QUALITY=3,
+        VERY_HIGH_QUALITY=255
     };
 
     static AudioResampler* create(int bitDepth, int inChannelCount,
diff --git a/services/audioflinger/AudioResamplerSinc.cpp b/services/audioflinger/AudioResamplerSinc.cpp
index 76662d8..0ae4b64 100644
--- a/services/audioflinger/AudioResamplerSinc.cpp
+++ b/services/audioflinger/AudioResamplerSinc.cpp
@@ -14,8 +14,15 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "AudioResamplerSinc"
+//#define LOG_NDEBUG 0
+
 #include <string.h>
 #include "AudioResamplerSinc.h"
+#include <dlfcn.h>
+#include <cutils/properties.h>
+#include <stdlib.h>
+#include <utils/Log.h>
 
 namespace android {
 // ----------------------------------------------------------------------------
@@ -57,6 +64,14 @@
         0x00000000 // this one is needed for lerping the last coefficient
 };
 
+//Define the static variables
+int AudioResamplerSinc::coefsBits;
+int  AudioResamplerSinc::cShift;
+uint32_t  AudioResamplerSinc::cMask;
+int AudioResamplerSinc::pShift;
+uint32_t AudioResamplerSinc::pMask;
+unsigned int AudioResamplerSinc::halfNumCoefs;
+
 // ----------------------------------------------------------------------------
 
 static inline
@@ -133,7 +148,7 @@
 // ----------------------------------------------------------------------------
 
 AudioResamplerSinc::AudioResamplerSinc(int bitDepth,
-        int inChannelCount, int32_t sampleRate)
+        int inChannelCount, int32_t sampleRate, int32_t quality)
     : AudioResampler(bitDepth, inChannelCount, sampleRate),
     mState(0)
 {
@@ -153,26 +168,89 @@
      *
      */
 
-    const size_t numCoefs = 2*halfNumCoefs;
-    const size_t stateSize = numCoefs * inChannelCount * 2;
-    mState = new int16_t[stateSize];
-    memset(mState, 0, sizeof(int16_t)*stateSize);
-    mImpulse = mState + (halfNumCoefs-1)*inChannelCount;
-    mRingFull = mImpulse + (numCoefs+1)*inChannelCount;
+    mResampleCoeffLib = NULL;
+    //Intialize the parameters for resampler coefficients
+    //for high quality
+    coefsBits = RESAMPLE_FIR_LERP_INT_BITS;
+    cShift = kNumPhaseBits - coefsBits;
+    cMask  = ((1<< coefsBits)-1) <<  cShift;
+
+    pShift = kNumPhaseBits -  coefsBits - pLerpBits;
+    pMask  = ((1<< pLerpBits)-1) <<  pShift;
+
+    halfNumCoefs = RESAMPLE_FIR_NUM_COEF;
+
+    //Check if qcom highest quality can be used
+    char value[PROPERTY_VALUE_MAX];
+    //Open the dll to get the coefficients for VERY_HIGH_QUALITY
+    if (quality == VERY_HIGH_QUALITY ) {
+        mResampleCoeffLib = dlopen("libaudio-resampler.so", RTLD_NOW);
+        ALOGV("Open libaudio-resampler library = %p",mResampleCoeffLib);
+        if (mResampleCoeffLib == NULL) {
+            ALOGE("Could not open audio-resampler library: %s", dlerror());
+            return;
+        }
+        mReadResampleCoefficients = (readCoefficientsFn)dlsym(mResampleCoeffLib, "readResamplerCoefficients");
+        mReadResampleFirNumCoeff = (readResampleFirNumCoeffFn)dlsym(mResampleCoeffLib, "readResampleFirNumCoeff");
+        mReadResampleFirLerpIntBits = (readResampleFirLerpIntBitsFn)dlsym(mResampleCoeffLib,"readResampleFirLerpIntBits");
+        if (!mReadResampleCoefficients  || !mReadResampleFirNumCoeff || !mReadResampleFirLerpIntBits) {
+            mReadResampleCoefficients = NULL;
+            mReadResampleFirNumCoeff = NULL;
+            mReadResampleFirLerpIntBits = NULL;
+            dlclose(mResampleCoeffLib);
+            mResampleCoeffLib = NULL;
+            ALOGE("Could not find convert symbol: %s", dlerror());
+            return;
+        }
+        // we have 16 coefs samples per zero-crossing
+        coefsBits = mReadResampleFirLerpIntBits();
+        ALOGV("coefsBits = %d",coefsBits);
+        cShift = kNumPhaseBits - coefsBits;
+        cMask  = ((1<<coefsBits)-1) << cShift;
+        pShift = kNumPhaseBits - coefsBits - pLerpBits;
+        pMask  = ((1<<pLerpBits)-1) << pShift;
+        // number of zero-crossing on each side
+        halfNumCoefs = mReadResampleFirNumCoeff();
+        ALOGV("halfNumCoefs = %d",halfNumCoefs);
+    }
 }
 
+
 AudioResamplerSinc::~AudioResamplerSinc()
 {
+    if(mResampleCoeffLib) {
+        ALOGV("close the libaudio-resampler library");
+        dlclose(mResampleCoeffLib);
+        mResampleCoeffLib = NULL;
+        mReadResampleCoefficients = NULL;
+        mReadResampleFirNumCoeff = NULL;
+        mReadResampleFirLerpIntBits = NULL;
+    }
     delete [] mState;
 }
 
 void AudioResamplerSinc::init() {
+
+    const size_t numCoefs = 2*halfNumCoefs;
+    const size_t stateSize = numCoefs * mChannelCount * 2;
+    mState = new int16_t[stateSize];
+    memset(mState, 0, sizeof(int16_t)*stateSize);
+    mImpulse = mState + (halfNumCoefs-1)*mChannelCount;
+    mRingFull = mImpulse + (numCoefs+1)*mChannelCount;
 }
 
 void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount,
             AudioBufferProvider* provider)
 {
-    mFirCoefs = (mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown;
+
+    if(mResampleCoeffLib){
+        ALOGV("get coefficient from libmm-audio resampler library");
+        mFirCoefs =  (mInSampleRate <= mSampleRate) ? mReadResampleCoefficients(true) : mReadResampleCoefficients(false);
+    }
+    else {
+        ALOGV("Use default coefficients");
+        mFirCoefs = (mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown;
+    }
 
     // select the appropriate resampler
     switch (mChannelCount) {
@@ -183,6 +261,7 @@
         resample<2>(out, outFrameCount, provider);
         break;
     }
+
 }
 
 
@@ -352,6 +431,5 @@
         r = l = mulAdd(samples[0], sinc, l);
     }
 }
-
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/audioflinger/AudioResamplerSinc.h b/services/audioflinger/AudioResamplerSinc.h
index f0a07b8..c53c66d 100644
--- a/services/audioflinger/AudioResamplerSinc.h
+++ b/services/audioflinger/AudioResamplerSinc.h
@@ -25,11 +25,16 @@
 
 namespace android {
 
+
+typedef const int32_t * (*readCoefficientsFn)(bool upDownSample);
+typedef int32_t  (*readResampleFirNumCoeffFn)();
+typedef int32_t  (*readResampleFirLerpIntBitsFn)();
+
 // ----------------------------------------------------------------------------
 
 class AudioResamplerSinc : public AudioResampler {
 public:
-    AudioResamplerSinc(int bitDepth, int inChannelCount, int32_t sampleRate);
+    AudioResamplerSinc(int bitDepth, int inChannelCount, int32_t sampleRate, int32_t quality = HIGH_QUALITY);
 
     virtual ~AudioResamplerSinc();
 
@@ -55,6 +60,10 @@
     inline void read(int16_t*& impulse, uint32_t& phaseFraction,
             const int16_t* in, size_t inputIndex);
 
+    readCoefficientsFn mReadResampleCoefficients ;
+    readResampleFirNumCoeffFn mReadResampleFirNumCoeff;
+    readResampleFirLerpIntBitsFn mReadResampleFirLerpIntBits;
+
     int16_t *mState;
     int16_t *mImpulse;
     int16_t *mRingFull;
@@ -63,23 +72,24 @@
     static const int32_t mFirCoefsDown[];
     static const int32_t mFirCoefsUp[];
 
+    void * mResampleCoeffLib;
     // ----------------------------------------------------------------------------
     static const int32_t RESAMPLE_FIR_NUM_COEF       = 8;
     static const int32_t RESAMPLE_FIR_LERP_INT_BITS  = 4;
 
     // we have 16 coefs samples per zero-crossing
-    static const int coefsBits = RESAMPLE_FIR_LERP_INT_BITS;        // 4
-    static const int cShift = kNumPhaseBits - coefsBits;            // 26
-    static const uint32_t cMask  = ((1<<coefsBits)-1) << cShift;    // 0xf<<26 = 3c00 0000
+    static int coefsBits;
+    static int cShift;
+    static uint32_t cMask;
 
     // and we use 15 bits to interpolate between these samples
     // this cannot change because the mul below rely on it.
     static const int pLerpBits = 15;
-    static const int pShift = kNumPhaseBits - coefsBits - pLerpBits;    // 11
-    static const uint32_t pMask  = ((1<<pLerpBits)-1) << pShift;    // 0x7fff << 11
+    static int pShift;
+    static uint32_t pMask;
 
     // number of zero-crossing on each side
-    static const unsigned int halfNumCoefs = RESAMPLE_FIR_NUM_COEF;
+    static  unsigned int halfNumCoefs;
 };
 
 // ----------------------------------------------------------------------------