Visualizer: replace the FFT implementation with a faster one.

This implementation uses fixed points instead of floating points. It
is slightly inaccurate compared to the old one but still perfect for
visualization purpose. It runs 40% faster on passion, 5 times faster
on sholes, and of course 14 times faster on sapphire.

Change-Id: I1e868417bcffda091becf106a7b941d02813faec
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
index 32cdb49..39552b6 100644
--- a/media/libmedia/Visualizer.cpp
+++ b/media/libmedia/Visualizer.cpp
@@ -26,10 +26,7 @@
 
 #include <media/Visualizer.h>
 
-extern "C" {
-#define FLOATING_POINT 1
-#include "fftwrap.h"
-}
+extern void fixed_fft_real(int n, int32_t *v);
 
 namespace android {
 
@@ -47,18 +44,10 @@
         mCaptureCbkUser(NULL)
 {
     initCaptureSize();
-    if (mCaptureSize != 0) {
-        mFftTable = spx_fft_init(mCaptureSize);
-    } else {
-        mFftTable = NULL;
-    }
 }
 
 Visualizer::~Visualizer()
 {
-    if (mFftTable != NULL) {
-        spx_fft_destroy(mFftTable);
-    }
 }
 
 status_t Visualizer::setEnabled(bool enabled)
@@ -163,11 +152,6 @@
     }
     if (status == NO_ERROR) {
         mCaptureSize = size;
-        if (mFftTable != NULL) {
-            spx_fft_destroy(mFftTable);
-        }
-        mFftTable = spx_fft_init(mCaptureSize);
-        LOGV("setCaptureSize size %d mFftTable %p", mCaptureSize, mFftTable);
     }
 
     return status;
@@ -219,19 +203,24 @@
 
 status_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform)
 {
-    if (mFftTable == NULL) {
-        return NO_INIT;
+    int32_t workspace[mCaptureSize >> 1];
+    int32_t nonzero = 0;
+
+    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
+        workspace[i >> 1] = (waveform[i] ^ 0x80) << 23;
+        workspace[i >> 1] |= (waveform[i + 1] ^ 0x80) << 7;
+        nonzero |= workspace[i >> 1];
     }
 
-    float fsrc[mCaptureSize];
-    for (uint32_t i = 0; i < mCaptureSize; i++) {
-        fsrc[i] = (int16_t)(waveform[i] ^ 0x80) << 8;
+    if (nonzero) {
+        fixed_fft_real(mCaptureSize >> 1, workspace);
     }
-    float fdst[mCaptureSize];
-    spx_fft_float(mFftTable, fsrc, fdst);
-    for (uint32_t i = 0; i < mCaptureSize; i++) {
-        fft[i] = (uint8_t)((int32_t)fdst[i] >> 8);
+
+    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
+        fft[i] = workspace[i >> 1] >> 23;
+        fft[i + 1] = workspace[i >> 1] >> 7;
     }
+
     return NO_ERROR;
 }