Visualizer.cpp revision 40bc906252974d0b389ae4a147232d0c9a97193f
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>
311ab85ec401801ef9a9184650d0f5a1639b45eeb9Glenn Kasten#include <utils/Thread.h>
32da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
33da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentnamespace android {
34da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
35da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// ---------------------------------------------------------------------------
36da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
37da7581b7b61b84f15e8d671c86fd117c322b009eEric LaurentVisualizer::Visualizer (int32_t priority,
38da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent         effect_callback_t cbf,
39da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent         void* user,
40da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent         int sessionId)
41da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    :   AudioEffect(SL_IID_VISUALIZATION, NULL, priority, cbf, user, sessionId),
42da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureRate(CAPTURE_RATE_DEF),
43da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureSize(CAPTURE_SIZE_DEF),
44da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mSampleRate(44100000),
453476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED),
4609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        mMeasurementMode(MEASUREMENT_MODE_NONE),
47da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureCallBack(NULL),
48da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureCbkUser(NULL)
49da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
50da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    initCaptureSize();
51da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
52da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
53da7581b7b61b84f15e8d671c86fd117c322b009eEric LaurentVisualizer::~Visualizer()
54da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
5563f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George    ALOGV("Visualizer::~Visualizer()");
5663f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George    if (mCaptureThread != NULL) {
5763f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George        mCaptureThread->requestExitAndWait();
5863f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George        mCaptureThread.clear();
5963f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George    }
6063f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George    mCaptureCallBack = NULL;
6163f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George    mCaptureFlags = 0;
62da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
63da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
64da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::setEnabled(bool enabled)
65da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
66a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
67da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
68da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    sp<CaptureThread> t = mCaptureThread;
69da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (t != 0) {
70da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (enabled) {
71da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            if (t->exitPending()) {
72da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                if (t->requestExitAndWait() == WOULD_BLOCK) {
7329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Visualizer::enable() called from thread");
74da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                    return INVALID_OPERATION;
75da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                }
76da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            }
77da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
78da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        t->mLock.lock();
79e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten    }
80da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
81da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = AudioEffect::setEnabled(enabled);
82da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
83da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
84da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (t != 0) {
85da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            if (enabled) {
869096f3471434d7f0d2419ac0ee2a618045489718Glenn Kasten                t->run("Visualizer");
87da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            } else {
88da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                t->requestExit();
89da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            }
90da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
91da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
92da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
93da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (t != 0) {
94da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        t->mLock.unlock();
95da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
96da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
97da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
98da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
99da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
10085ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kastenstatus_t Visualizer::setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags,
10185ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten        uint32_t rate)
102da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
103da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (rate > CAPTURE_RATE_MAX) {
104da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
105da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
106a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
107da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
108da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mEnabled) {
109da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return INVALID_OPERATION;
110da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
111da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
11263f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George    if (mCaptureThread != 0) {
11363f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George        mCaptureLock.unlock();
11463f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George        mCaptureThread->requestExitAndWait();
11563f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George        mCaptureLock.lock();
116da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
11763f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George
118da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureThread.clear();
119da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureCallBack = cbk;
120da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureCbkUser = user;
121da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureFlags = flags;
122da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureRate = rate;
123da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
124da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (cbk != NULL) {
125da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureThread = new CaptureThread(*this, rate, ((flags & CAPTURE_CALL_JAVA) != 0));
126da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
1273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setCaptureCallBack() rate: %d thread %p flags 0x%08x",
128da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            rate, mCaptureThread.get(), mCaptureFlags);
129da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return NO_ERROR;
130da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
131da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
132da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::setCaptureSize(uint32_t size)
133da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
134da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (size > VISUALIZER_CAPTURE_SIZE_MAX ||
135da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        size < VISUALIZER_CAPTURE_SIZE_MIN ||
136fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        popcount(size) != 1) {
137da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
138da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
139da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
140a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
141da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mEnabled) {
142da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return INVALID_OPERATION;
143da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
144da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
145da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
146da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    effect_param_t *p = (effect_param_t *)buf32;
147da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
148da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->psize = sizeof(uint32_t);
149da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->vsize = sizeof(uint32_t);
1506d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
151da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    *((int32_t *)p->data + 1)= size;
152da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = setParameter(p);
153da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
1543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setCaptureSize size %d  status %d p->status %d", size, status, p->status);
155da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
156da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
157da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        status = p->status;
1583476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        if (status == NO_ERROR) {
1593476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi            mCaptureSize = size;
1603476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        }
161da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
1623476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1633476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    return status;
1643476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi}
1653476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1663476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivistatus_t Visualizer::setScalingMode(uint32_t mode) {
1673476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    if ((mode != VISUALIZER_SCALING_MODE_NORMALIZED)
1683476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi            && (mode != VISUALIZER_SCALING_MODE_AS_PLAYED)) {
1693476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        return BAD_VALUE;
1703476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    }
1713476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1723476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    Mutex::Autolock _l(mCaptureLock);
1733476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1743476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
1753476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    effect_param_t *p = (effect_param_t *)buf32;
1763476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1773476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    p->psize = sizeof(uint32_t);
1783476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    p->vsize = sizeof(uint32_t);
1793476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    *(int32_t *)p->data = VISUALIZER_PARAM_SCALING_MODE;
1803476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    *((int32_t *)p->data + 1)= mode;
1813476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    status_t status = setParameter(p);
1823476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1833476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    ALOGV("setScalingMode mode %d  status %d p->status %d", mode, status, p->status);
1843476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
185da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
1863476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        status = p->status;
1873476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        if (status == NO_ERROR) {
1883476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi            mScalingMode = mode;
1893476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        }
190da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
191da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
192da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
193da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
194da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
19509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivistatus_t Visualizer::setMeasurementMode(uint32_t mode) {
19609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if ((mode != MEASUREMENT_MODE_NONE)
19709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            //Note: needs to be handled as a mask when more measurement modes are added
19809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            && ((mode & MEASUREMENT_MODE_PEAK_RMS) != mode)) {
19909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        return BAD_VALUE;
20009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
20109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
20209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    Mutex::Autolock _l(mCaptureLock);
20309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
20409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
20509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    effect_param_t *p = (effect_param_t *)buf32;
20609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
20709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    p->psize = sizeof(uint32_t);
20809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    p->vsize = sizeof(uint32_t);
20909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    *(int32_t *)p->data = VISUALIZER_PARAM_MEASUREMENT_MODE;
21009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    *((int32_t *)p->data + 1)= mode;
21109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    status_t status = setParameter(p);
21209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
21309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    ALOGV("setMeasurementMode mode %d  status %d p->status %d", mode, status, p->status);
21409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
21509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if (status == NO_ERROR) {
21609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        status = p->status;
21709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        if (status == NO_ERROR) {
21809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            mMeasurementMode = mode;
21909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        }
22009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
22109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    return status;
22209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi}
22309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
22409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivistatus_t Visualizer::getIntMeasurements(uint32_t type, uint32_t number, int32_t *measurements) {
22509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if (mMeasurementMode == MEASUREMENT_MODE_NONE) {
22609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        ALOGE("Cannot retrieve int measurements, no measurement mode set");
22709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        return INVALID_OPERATION;
22809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
22909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if (!(mMeasurementMode & type)) {
23009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        // measurement type has not been set on this Visualizer
23109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        ALOGE("Cannot retrieve int measurements, requested measurement mode 0x%x not set(0x%x)",
23209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi                type, mMeasurementMode);
23309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        return INVALID_OPERATION;
23409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
23509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    // only peak+RMS measurement supported
23609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if ((type != MEASUREMENT_MODE_PEAK_RMS)
23709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            // for peak+RMS measurement, the results are 2 int32_t values
23809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            || (number != 2)) {
23909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        ALOGE("Cannot retrieve int measurements, MEASUREMENT_MODE_PEAK_RMS returns 2 ints, not %d",
24009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi                        number);
24109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        return BAD_VALUE;
24209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
24309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
24409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    status_t status = NO_ERROR;
24509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if (mEnabled) {
24609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        uint32_t replySize = number * sizeof(int32_t);
24709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        status = command(VISUALIZER_CMD_MEASURE,
24809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi                sizeof(uint32_t)  /*cmdSize*/,
24909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi                &type /*cmdData*/,
25009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi                &replySize, measurements);
25109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        ALOGV("getMeasurements() command returned %d", status);
25209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        if ((status == NO_ERROR) && (replySize == 0)) {
25309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            status = NOT_ENOUGH_DATA;
25409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        }
25509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    } else {
25609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        ALOGV("getMeasurements() disabled");
25709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        return INVALID_OPERATION;
25809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
25909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    return status;
26009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi}
26109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
262da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::getWaveForm(uint8_t *waveform)
263da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
264da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (waveform == NULL) {
265da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
266da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
267da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mCaptureSize == 0) {
268da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return NO_INIT;
269da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
270da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
271da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = NO_ERROR;
272da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mEnabled) {
27325f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent        uint32_t replySize = mCaptureSize;
2746d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent        status = command(VISUALIZER_CMD_CAPTURE, 0, NULL, &replySize, waveform);
2753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("getWaveForm() command returned %d", status);
276af7d8189f91c45ab919a6c9ac386b268c8d91168John Grossman        if ((status == NO_ERROR) && (replySize == 0)) {
277da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            status = NOT_ENOUGH_DATA;
278da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
279da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    } else {
2803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("getWaveForm() disabled");
281da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        memset(waveform, 0x80, mCaptureSize);
282da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
283da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
284da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
285da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
286da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::getFft(uint8_t *fft)
287da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
288da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (fft == NULL) {
289da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
290da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
291da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mCaptureSize == 0) {
292da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return NO_INIT;
293da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
294da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
295da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = NO_ERROR;
296da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mEnabled) {
297da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t buf[mCaptureSize];
2980fa449cc475580d995e9d56756c3da5507d2b6f6Eric Laurent        status = getWaveForm(buf);
299da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (status == NO_ERROR) {
300da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            status = doFft(fft, buf);
301da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
302da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    } else {
303da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        memset(fft, 0, mCaptureSize);
304da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
305da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
306da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
307da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
308da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform)
309da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
310dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    int32_t workspace[mCaptureSize >> 1];
311dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    int32_t nonzero = 0;
312dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh
313dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
3146b6a736ec71c692c165952fe653a7766075e94bbChia-chi Yeh        workspace[i >> 1] =
3156b6a736ec71c692c165952fe653a7766075e94bbChia-chi Yeh                ((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8);
316dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh        nonzero |= workspace[i >> 1];
317da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
318da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
319dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    if (nonzero) {
320dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh        fixed_fft_real(mCaptureSize >> 1, workspace);
321da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
322dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh
323dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
324209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        short tmp = workspace[i >> 1] >> 21;
325209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        while (tmp > 127 || tmp < -128) tmp >>= 1;
326209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        fft[i] = tmp;
327209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        tmp = workspace[i >> 1];
328209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        tmp >>= 5;
329209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        while (tmp > 127 || tmp < -128) tmp >>= 1;
330209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        fft[i + 1] = tmp;
331da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
332dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh
333da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return NO_ERROR;
334da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
335da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
336da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentvoid Visualizer::periodicCapture()
337da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
338a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
3393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("periodicCapture() %p mCaptureCallBack %p mCaptureFlags 0x%08x",
340da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            this, mCaptureCallBack, mCaptureFlags);
341da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mCaptureCallBack != NULL &&
342da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        (mCaptureFlags & (CAPTURE_WAVEFORM|CAPTURE_FFT)) &&
343da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureSize != 0) {
344da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t waveform[mCaptureSize];
345da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        status_t status = getWaveForm(waveform);
346da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (status != NO_ERROR) {
347da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            return;
348da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
349da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t fft[mCaptureSize];
350da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (mCaptureFlags & CAPTURE_FFT) {
351da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            status = doFft(fft, waveform);
352da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
353da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (status != NO_ERROR) {
354da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            return;
355da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
356da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t *wavePtr = NULL;
357da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t *fftPtr = NULL;
358da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint32_t waveSize = 0;
359da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint32_t fftSize = 0;
360da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (mCaptureFlags & CAPTURE_WAVEFORM) {
361da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            wavePtr = waveform;
362da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            waveSize = mCaptureSize;
363da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
364da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (mCaptureFlags & CAPTURE_FFT) {
365da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            fftPtr = fft;
366da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            fftSize = mCaptureSize;
367da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
368da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureCallBack(mCaptureCbkUser, waveSize, wavePtr, fftSize, fftPtr, mSampleRate);
369da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
370da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
371da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
372da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentuint32_t Visualizer::initCaptureSize()
373da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
374da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
375da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    effect_param_t *p = (effect_param_t *)buf32;
376da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
377da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->psize = sizeof(uint32_t);
378da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->vsize = sizeof(uint32_t);
3796d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
380da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = getParameter(p);
381da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
382da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
383da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        status = p->status;
384da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
385da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
386da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t size = 0;
387da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
388da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        size = *((int32_t *)p->data + 1);
389da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
390da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureSize = size;
391da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
3923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initCaptureSize size %d status %d", mCaptureSize, status);
393da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
394da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return size;
395da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
396da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
3973476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivivoid Visualizer::controlStatusChanged(bool controlGranted) {
3983476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    if (controlGranted) {
3993476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        // this Visualizer instance regained control of the effect, reset the scaling mode
4003476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        //   and capture size as has been cached through it.
4013476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        ALOGV("controlStatusChanged(true) causes effect parameter reset:");
4023476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        ALOGV("    scaling mode reset to %d", mScalingMode);
4033476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        setScalingMode(mScalingMode);
4043476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        ALOGV("    capture size reset to %d", mCaptureSize);
4053476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        setCaptureSize(mCaptureSize);
4063476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    }
4073476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    AudioEffect::controlStatusChanged(controlGranted);
4083476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi}
4093476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
410da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//-------------------------------------------------------------------------
411da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
41285ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn KastenVisualizer::CaptureThread::CaptureThread(Visualizer& receiver, uint32_t captureRate,
41385ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten        bool bCanCallJava)
414da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    : Thread(bCanCallJava), mReceiver(receiver)
415da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
416da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mSleepTimeUs = 1000000000 / captureRate;
4173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("CaptureThread cstor %p captureRate %d mSleepTimeUs %d", this, captureRate, mSleepTimeUs);
418da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
419da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
420da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentbool Visualizer::CaptureThread::threadLoop()
421da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
4223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("CaptureThread %p enter", this);
423da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    while (!exitPending())
424da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    {
425da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        usleep(mSleepTimeUs);
426da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mReceiver.periodicCapture();
427da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
4283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("CaptureThread %p exiting", this);
429da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return false;
430da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
431da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
43240bc906252974d0b389ae4a147232d0c9a97193fGlenn Kasten} // namespace android
433