1da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent/*
2da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent**
3da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent** Copyright 2010, The Android Open Source Project
4da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent**
5da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent** Licensed under the Apache License, Version 2.0 (the "License");
6da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent** you may not use this file except in compliance with the License.
7da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent** You may obtain a copy of the License at
8da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent**
9da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent**     http://www.apache.org/licenses/LICENSE-2.0
10da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent**
11da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent** Unless required by applicable law or agreed to in writing, software
12da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent** distributed under the License is distributed on an "AS IS" BASIS,
13da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent** See the License for the specific language governing permissions and
15da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent** limitations under the License.
16da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent*/
17da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
18da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
19da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//#define LOG_NDEBUG 0
20da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#define LOG_TAG "Visualizer"
21da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <utils/Log.h>
22da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
23da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <stdint.h>
24da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <sys/types.h>
25da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <limits.h>
26da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
27fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin#include <cutils/bitops.h>
28fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin
29da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <media/Visualizer.h>
303f6448e020969be59ad4d8df99c5296f237ffbd9Glenn Kasten#include <audio_utils/fixedfft.h>
31da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
32da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentnamespace android {
33da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
34da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// ---------------------------------------------------------------------------
35da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
36da7581b7b61b84f15e8d671c86fd117c322b009eEric LaurentVisualizer::Visualizer (int32_t priority,
37da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent         effect_callback_t cbf,
38da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent         void* user,
39da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent         int sessionId)
40da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    :   AudioEffect(SL_IID_VISUALIZATION, NULL, priority, cbf, user, sessionId),
41da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureRate(CAPTURE_RATE_DEF),
42da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureSize(CAPTURE_SIZE_DEF),
43da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mSampleRate(44100000),
443476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED),
45da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureCallBack(NULL),
46da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureCbkUser(NULL)
47da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
48da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    initCaptureSize();
49da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
50da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
51da7581b7b61b84f15e8d671c86fd117c322b009eEric LaurentVisualizer::~Visualizer()
52da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
53da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
54da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
55da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::setEnabled(bool enabled)
56da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
57a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
58da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
59da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    sp<CaptureThread> t = mCaptureThread;
60da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (t != 0) {
61da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (enabled) {
62da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            if (t->exitPending()) {
63da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                if (t->requestExitAndWait() == WOULD_BLOCK) {
6429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Visualizer::enable() called from thread");
65da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                    return INVALID_OPERATION;
66da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                }
67da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            }
68da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
69da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        t->mLock.lock();
70e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten    }
71da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
72da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = AudioEffect::setEnabled(enabled);
73da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
74da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
75da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (t != 0) {
76da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            if (enabled) {
779096f3471434d7f0d2419ac0ee2a618045489718Glenn Kasten                t->run("Visualizer");
78da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            } else {
79da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                t->requestExit();
80da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            }
81da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
82da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
83da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
84da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (t != 0) {
85da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        t->mLock.unlock();
86da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
87da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
88da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
89da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
90da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
91da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate)
92da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
93da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (rate > CAPTURE_RATE_MAX) {
94da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
95da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
96a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
97da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
98da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mEnabled) {
99da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return INVALID_OPERATION;
100da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
101da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
102da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    sp<CaptureThread> t = mCaptureThread;
103da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (t != 0) {
104da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        t->mLock.lock();
105da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
106da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureThread.clear();
107da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureCallBack = cbk;
108da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureCbkUser = user;
109da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureFlags = flags;
110da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureRate = rate;
111da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
112da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (t != 0) {
113da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        t->mLock.unlock();
114da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
115da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
116da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (cbk != NULL) {
117da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureThread = new CaptureThread(*this, rate, ((flags & CAPTURE_CALL_JAVA) != 0));
118da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
1193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setCaptureCallBack() rate: %d thread %p flags 0x%08x",
120da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            rate, mCaptureThread.get(), mCaptureFlags);
121da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return NO_ERROR;
122da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
123da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
124da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::setCaptureSize(uint32_t size)
125da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
126da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (size > VISUALIZER_CAPTURE_SIZE_MAX ||
127da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        size < VISUALIZER_CAPTURE_SIZE_MIN ||
128fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        popcount(size) != 1) {
129da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
130da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
131da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
132a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
133da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mEnabled) {
134da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return INVALID_OPERATION;
135da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
136da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
137da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
138da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    effect_param_t *p = (effect_param_t *)buf32;
139da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
140da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->psize = sizeof(uint32_t);
141da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->vsize = sizeof(uint32_t);
1426d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
143da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    *((int32_t *)p->data + 1)= size;
144da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = setParameter(p);
145da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
1463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setCaptureSize size %d  status %d p->status %d", size, status, p->status);
147da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
148da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
149da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        status = p->status;
1503476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        if (status == NO_ERROR) {
1513476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi            mCaptureSize = size;
1523476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        }
153da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
1543476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1553476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    return status;
1563476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi}
1573476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1583476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivistatus_t Visualizer::setScalingMode(uint32_t mode) {
1593476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    if ((mode != VISUALIZER_SCALING_MODE_NORMALIZED)
1603476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi            && (mode != VISUALIZER_SCALING_MODE_AS_PLAYED)) {
1613476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        return BAD_VALUE;
1623476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    }
1633476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1643476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    Mutex::Autolock _l(mCaptureLock);
1653476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1663476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
1673476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    effect_param_t *p = (effect_param_t *)buf32;
1683476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1693476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    p->psize = sizeof(uint32_t);
1703476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    p->vsize = sizeof(uint32_t);
1713476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    *(int32_t *)p->data = VISUALIZER_PARAM_SCALING_MODE;
1723476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    *((int32_t *)p->data + 1)= mode;
1733476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    status_t status = setParameter(p);
1743476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1753476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    ALOGV("setScalingMode mode %d  status %d p->status %d", mode, status, p->status);
1763476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
177da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
1783476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        status = p->status;
1793476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        if (status == NO_ERROR) {
1803476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi            mScalingMode = mode;
1813476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        }
182da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
183da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
184da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
185da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
186da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
187da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::getWaveForm(uint8_t *waveform)
188da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
189da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (waveform == NULL) {
190da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
191da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
192da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mCaptureSize == 0) {
193da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return NO_INIT;
194da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
195da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
196da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = NO_ERROR;
197da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mEnabled) {
19825f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent        uint32_t replySize = mCaptureSize;
1996d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent        status = command(VISUALIZER_CMD_CAPTURE, 0, NULL, &replySize, waveform);
2003856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("getWaveForm() command returned %d", status);
201af7d8189f91c45ab919a6c9ac386b268c8d91168John Grossman        if ((status == NO_ERROR) && (replySize == 0)) {
202da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            status = NOT_ENOUGH_DATA;
203da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
204da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    } else {
2053856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("getWaveForm() disabled");
206da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        memset(waveform, 0x80, mCaptureSize);
207da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
208da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
209da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
210da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
211da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::getFft(uint8_t *fft)
212da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
213da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (fft == NULL) {
214da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
215da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
216da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mCaptureSize == 0) {
217da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return NO_INIT;
218da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
219da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
220da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = NO_ERROR;
221da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mEnabled) {
222da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t buf[mCaptureSize];
2230fa449cc475580d995e9d56756c3da5507d2b6f6Eric Laurent        status = getWaveForm(buf);
224da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (status == NO_ERROR) {
225da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            status = doFft(fft, buf);
226da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
227da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    } else {
228da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        memset(fft, 0, mCaptureSize);
229da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
230da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
231da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
232da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
233da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform)
234da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
235dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    int32_t workspace[mCaptureSize >> 1];
236dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    int32_t nonzero = 0;
237dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh
238dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
2396b6a736ec71c692c165952fe653a7766075e94bbChia-chi Yeh        workspace[i >> 1] =
2406b6a736ec71c692c165952fe653a7766075e94bbChia-chi Yeh                ((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8);
241dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh        nonzero |= workspace[i >> 1];
242da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
243da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
244dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    if (nonzero) {
245dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh        fixed_fft_real(mCaptureSize >> 1, workspace);
246da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
247dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh
248dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
249209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        short tmp = workspace[i >> 1] >> 21;
250209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        while (tmp > 127 || tmp < -128) tmp >>= 1;
251209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        fft[i] = tmp;
252209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        tmp = workspace[i >> 1];
253209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        tmp >>= 5;
254209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        while (tmp > 127 || tmp < -128) tmp >>= 1;
255209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        fft[i + 1] = tmp;
256da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
257dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh
258da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return NO_ERROR;
259da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
260da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
261da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentvoid Visualizer::periodicCapture()
262da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
263a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
2643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("periodicCapture() %p mCaptureCallBack %p mCaptureFlags 0x%08x",
265da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            this, mCaptureCallBack, mCaptureFlags);
266da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mCaptureCallBack != NULL &&
267da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        (mCaptureFlags & (CAPTURE_WAVEFORM|CAPTURE_FFT)) &&
268da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureSize != 0) {
269da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t waveform[mCaptureSize];
270da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        status_t status = getWaveForm(waveform);
271da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (status != NO_ERROR) {
272da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            return;
273da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
274da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t fft[mCaptureSize];
275da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (mCaptureFlags & CAPTURE_FFT) {
276da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            status = doFft(fft, waveform);
277da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
278da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (status != NO_ERROR) {
279da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            return;
280da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
281da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t *wavePtr = NULL;
282da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t *fftPtr = NULL;
283da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint32_t waveSize = 0;
284da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint32_t fftSize = 0;
285da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (mCaptureFlags & CAPTURE_WAVEFORM) {
286da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            wavePtr = waveform;
287da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            waveSize = mCaptureSize;
288da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
289da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (mCaptureFlags & CAPTURE_FFT) {
290da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            fftPtr = fft;
291da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            fftSize = mCaptureSize;
292da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
293da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureCallBack(mCaptureCbkUser, waveSize, wavePtr, fftSize, fftPtr, mSampleRate);
294da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
295da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
296da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
297da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentuint32_t Visualizer::initCaptureSize()
298da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
299da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
300da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    effect_param_t *p = (effect_param_t *)buf32;
301da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
302da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->psize = sizeof(uint32_t);
303da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->vsize = sizeof(uint32_t);
3046d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
305da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = getParameter(p);
306da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
307da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
308da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        status = p->status;
309da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
310da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
311da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t size = 0;
312da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
313da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        size = *((int32_t *)p->data + 1);
314da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
315da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureSize = size;
316da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
3173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initCaptureSize size %d status %d", mCaptureSize, status);
318da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
319da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return size;
320da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
321da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
3223476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivivoid Visualizer::controlStatusChanged(bool controlGranted) {
3233476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    if (controlGranted) {
3243476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        // this Visualizer instance regained control of the effect, reset the scaling mode
3253476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        //   and capture size as has been cached through it.
3263476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        ALOGV("controlStatusChanged(true) causes effect parameter reset:");
3273476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        ALOGV("    scaling mode reset to %d", mScalingMode);
3283476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        setScalingMode(mScalingMode);
3293476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        ALOGV("    capture size reset to %d", mCaptureSize);
3303476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        setCaptureSize(mCaptureSize);
3313476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    }
3323476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    AudioEffect::controlStatusChanged(controlGranted);
3333476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi}
3343476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
335da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//-------------------------------------------------------------------------
336da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
337da7581b7b61b84f15e8d671c86fd117c322b009eEric LaurentVisualizer::CaptureThread::CaptureThread(Visualizer& receiver, uint32_t captureRate, bool bCanCallJava)
338da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    : Thread(bCanCallJava), mReceiver(receiver)
339da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
340da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mSleepTimeUs = 1000000000 / captureRate;
3413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("CaptureThread cstor %p captureRate %d mSleepTimeUs %d", this, captureRate, mSleepTimeUs);
342da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
343da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
344da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentbool Visualizer::CaptureThread::threadLoop()
345da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
3463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("CaptureThread %p enter", this);
347da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    while (!exitPending())
348da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    {
349da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        usleep(mSleepTimeUs);
350da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mReceiver.periodicCapture();
351da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
3523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("CaptureThread %p exiting", this);
353da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return false;
354da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
355da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
356da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}; // namespace android
357