Merge "Add support for scaling mode parameter"
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
index 02dfc1b..05d834d 100644
--- a/include/media/AudioEffect.h
+++ b/include/media/AudioEffect.h
@@ -402,6 +402,15 @@
      int32_t                 mId;                // system wide unique effect engine instance ID
      Mutex                   mLock;               // Mutex for mEnabled access
 
+     // IEffectClient
+     virtual void controlStatusChanged(bool controlGranted);
+     virtual void enableStatusChanged(bool enabled);
+     virtual void commandExecuted(uint32_t cmdCode,
+             uint32_t cmdSize,
+             void *pCmdData,
+             uint32_t replySize,
+             void *pReplyData);
+
 private:
 
      // Implements the IEffectClient interface
@@ -433,20 +442,8 @@
         AudioEffect *mEffect;
     };
 
-
-    friend class EffectClient;
-
-    // IEffectClient
-    void controlStatusChanged(bool controlGranted);
-    void enableStatusChanged(bool enabled);
-    void commandExecuted(uint32_t cmdCode,
-                         uint32_t cmdSize,
-                         void *pCmdData,
-                         uint32_t replySize,
-                         void *pReplyData);
     void binderDied();
 
-
     sp<IEffect>             mIEffect;           // IEffect binder interface
     sp<EffectClient>        mIEffectClient;     // IEffectClient implementation
     sp<IMemory>             mCblkMemory;        // shared memory for deferred parameter setting
diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h
index 60fa15b..fdec5ee 100644
--- a/include/media/Visualizer.h
+++ b/include/media/Visualizer.h
@@ -108,6 +108,12 @@
     // returns the sampling rate of the audio being captured
     uint32_t getSamplingRate() { return mSampleRate; }
 
+    // set the way volume affects the captured data
+    // mode must one of VISUALIZER_SCALING_MODE_NORMALIZED,
+    //  VISUALIZER_SCALING_MODE_AS_PLAYED
+    status_t setScalingMode(uint32_t mode);
+    uint32_t getScalingMode() { return mScalingMode; }
+
     // return a capture in PCM 8 bit unsigned format. The size of the capture is equal to
     // getCaptureSize()
     status_t getWaveForm(uint8_t *waveform);
@@ -117,6 +123,10 @@
     // are returned
     status_t getFft(uint8_t *fft);
 
+protected:
+    // from IEffectClient
+    virtual void controlStatusChanged(bool controlGranted);
+
 private:
 
     static const uint32_t CAPTURE_RATE_MAX = 20000;
@@ -147,6 +157,7 @@
     uint32_t mCaptureRate;
     uint32_t mCaptureSize;
     uint32_t mSampleRate;
+    uint32_t mScalingMode;
     capture_cbk_t mCaptureCallBack;
     void *mCaptureCbkUser;
     sp<CaptureThread> mCaptureThread;
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index bdb1a1c..44d05cd 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "Visualizer"
+#define LOG_TAG "EffectVisualizer"
 //#define LOG_NDEBUG 0
 #include <cutils/log.h>
 #include <assert.h>
@@ -57,6 +57,7 @@
     effect_config_t mConfig;
     uint32_t mCaptureIdx;
     uint32_t mCaptureSize;
+    uint32_t mScalingMode;
     uint8_t mState;
     uint8_t mCurrentBuf;
     uint8_t mLastBuf;
@@ -164,6 +165,7 @@
     pContext->mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
 
     pContext->mCaptureSize = VISUALIZER_CAPTURE_SIZE_MAX;
+    pContext->mScalingMode = VISUALIZER_SCALING_MODE_NORMALIZED;
 
     Visualizer_setConfig(pContext, &pContext->mConfig);
 
@@ -285,26 +287,32 @@
     }
 
     // all code below assumes stereo 16 bit PCM output and input
+    int32_t shift;
 
-    // derive capture scaling factor from peak value in current buffer
-    // this gives more interesting captures for display.
-    int32_t shift = 32;
-    int len = inBuffer->frameCount * 2;
-    for (int i = 0; i < len; i++) {
-        int32_t smp = inBuffer->s16[i];
-        if (smp < 0) smp = -smp - 1; // take care to keep the max negative in range
-        int32_t clz = __builtin_clz(smp);
-        if (shift > clz) shift = clz;
+    if (pContext->mScalingMode == VISUALIZER_SCALING_MODE_NORMALIZED) {
+        // derive capture scaling factor from peak value in current buffer
+        // this gives more interesting captures for display.
+        shift = 32;
+        int len = inBuffer->frameCount * 2;
+        for (int i = 0; i < len; i++) {
+            int32_t smp = inBuffer->s16[i];
+            if (smp < 0) smp = -smp - 1; // take care to keep the max negative in range
+            int32_t clz = __builtin_clz(smp);
+            if (shift > clz) shift = clz;
+        }
+        // A maximum amplitude signal will have 17 leading zeros, which we want to
+        // translate to a shift of 8 (for converting 16 bit to 8 bit)
+        shift = 25 - shift;
+        // Never scale by less than 8 to avoid returning unaltered PCM signal.
+        if (shift < 3) {
+            shift = 3;
+        }
+        // add one to combine the division by 2 needed after summing left and right channels below
+        shift++;
+    } else {
+        assert(pContext->mScalingMode == VISUALIZER_SCALING_MODE_AS_PLAYED);
+        shift = 9;
     }
-    // A maximum amplitude signal will have 17 leading zeros, which we want to
-    // translate to a shift of 8 (for converting 16 bit to 8 bit)
-     shift = 25 - shift;
-    // Never scale by less than 8 to avoid returning unaltered PCM signal.
-    if (shift < 3) {
-        shift = 3;
-    }
-    // add one to combine the division by 2 needed after summing left and right channels below
-    shift++;
 
     uint32_t captIdx;
     uint32_t inIdx;
@@ -414,15 +422,26 @@
         effect_param_t *p = (effect_param_t *)pReplyData;
         p->status = 0;
         *replySize = sizeof(effect_param_t) + sizeof(uint32_t);
-        if (p->psize != sizeof(uint32_t) ||
-            *(uint32_t *)p->data != VISUALIZER_PARAM_CAPTURE_SIZE) {
+        if (p->psize != sizeof(uint32_t)) {
             p->status = -EINVAL;
             break;
         }
-        ALOGV("get mCaptureSize = %d", pContext->mCaptureSize);
-        *((uint32_t *)p->data + 1) = pContext->mCaptureSize;
-        p->vsize = sizeof(uint32_t);
-        *replySize += sizeof(uint32_t);
+        switch (*(uint32_t *)p->data) {
+        case VISUALIZER_PARAM_CAPTURE_SIZE:
+            ALOGV("get mCaptureSize = %d", pContext->mCaptureSize);
+            *((uint32_t *)p->data + 1) = pContext->mCaptureSize;
+            p->vsize = sizeof(uint32_t);
+            *replySize += sizeof(uint32_t);
+            break;
+        case VISUALIZER_PARAM_SCALING_MODE:
+            ALOGV("get mScalingMode = %d", pContext->mScalingMode);
+            *((uint32_t *)p->data + 1) = pContext->mScalingMode;
+            p->vsize = sizeof(uint32_t);
+            *replySize += sizeof(uint32_t);
+            break;
+        default:
+            p->status = -EINVAL;
+        }
         } break;
     case EFFECT_CMD_SET_PARAM: {
         if (pCmdData == NULL ||
@@ -432,14 +451,22 @@
         }
         *(int32_t *)pReplyData = 0;
         effect_param_t *p = (effect_param_t *)pCmdData;
-        if (p->psize != sizeof(uint32_t) ||
-            p->vsize != sizeof(uint32_t) ||
-            *(uint32_t *)p->data != VISUALIZER_PARAM_CAPTURE_SIZE) {
+        if (p->psize != sizeof(uint32_t) || p->vsize != sizeof(uint32_t)) {
             *(int32_t *)pReplyData = -EINVAL;
-            break;;
+            break;
         }
-        pContext->mCaptureSize = *((uint32_t *)p->data + 1);
-        ALOGV("set mCaptureSize = %d", pContext->mCaptureSize);
+        switch (*(uint32_t *)p->data) {
+        case VISUALIZER_PARAM_CAPTURE_SIZE:
+            pContext->mCaptureSize = *((uint32_t *)p->data + 1);
+            ALOGV("set mCaptureSize = %d", pContext->mCaptureSize);
+            break;
+        case VISUALIZER_PARAM_SCALING_MODE:
+            pContext->mScalingMode = *((uint32_t *)p->data + 1);
+            ALOGV("set mScalingMode = %d", pContext->mScalingMode);
+            break;
+        default:
+            *(int32_t *)pReplyData = -EINVAL;
+        }
         } break;
     case EFFECT_CMD_SET_DEVICE:
     case EFFECT_CMD_SET_VOLUME:
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
index bcd6ae4..de0bf7d 100644
--- a/media/libmedia/Visualizer.cpp
+++ b/media/libmedia/Visualizer.cpp
@@ -41,6 +41,7 @@
         mCaptureRate(CAPTURE_RATE_DEF),
         mCaptureSize(CAPTURE_SIZE_DEF),
         mSampleRate(44100000),
+        mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED),
         mCaptureCallBack(NULL),
         mCaptureCbkUser(NULL)
 {
@@ -146,9 +147,38 @@
 
     if (status == NO_ERROR) {
         status = p->status;
+        if (status == NO_ERROR) {
+            mCaptureSize = size;
+        }
     }
+
+    return status;
+}
+
+status_t Visualizer::setScalingMode(uint32_t mode) {
+    if ((mode != VISUALIZER_SCALING_MODE_NORMALIZED)
+            && (mode != VISUALIZER_SCALING_MODE_AS_PLAYED)) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mCaptureLock);
+
+    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+    effect_param_t *p = (effect_param_t *)buf32;
+
+    p->psize = sizeof(uint32_t);
+    p->vsize = sizeof(uint32_t);
+    *(int32_t *)p->data = VISUALIZER_PARAM_SCALING_MODE;
+    *((int32_t *)p->data + 1)= mode;
+    status_t status = setParameter(p);
+
+    ALOGV("setScalingMode mode %d  status %d p->status %d", mode, status, p->status);
+
     if (status == NO_ERROR) {
-        mCaptureSize = size;
+        status = p->status;
+        if (status == NO_ERROR) {
+            mScalingMode = mode;
+        }
     }
 
     return status;
@@ -289,6 +319,19 @@
     return size;
 }
 
+void Visualizer::controlStatusChanged(bool controlGranted) {
+    if (controlGranted) {
+        // this Visualizer instance regained control of the effect, reset the scaling mode
+        //   and capture size as has been cached through it.
+        ALOGV("controlStatusChanged(true) causes effect parameter reset:");
+        ALOGV("    scaling mode reset to %d", mScalingMode);
+        setScalingMode(mScalingMode);
+        ALOGV("    capture size reset to %d", mCaptureSize);
+        setCaptureSize(mCaptureSize);
+    }
+    AudioEffect::controlStatusChanged(controlGranted);
+}
+
 //-------------------------------------------------------------------------
 
 Visualizer::CaptureThread::CaptureThread(Visualizer& receiver, uint32_t captureRate, bool bCanCallJava)