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
37be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet GanovVisualizer::Visualizer (const String16& opPackageName,
38be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov         int32_t priority,
39da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent         effect_callback_t cbf,
40da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent         void* user,
41d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten         audio_session_t sessionId)
42be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov    :   AudioEffect(SL_IID_VISUALIZATION, opPackageName, NULL, priority, cbf, user, sessionId),
43da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureRate(CAPTURE_RATE_DEF),
44da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureSize(CAPTURE_SIZE_DEF),
45da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mSampleRate(44100000),
463476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED),
4709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        mMeasurementMode(MEASUREMENT_MODE_NONE),
48da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureCallBack(NULL),
49da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureCbkUser(NULL)
50da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
51da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    initCaptureSize();
52da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
53da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
54da7581b7b61b84f15e8d671c86fd117c322b009eEric LaurentVisualizer::~Visualizer()
55da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
5663f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George    ALOGV("Visualizer::~Visualizer()");
579b030df5ead9c039e4ebb16c745e2cc40e953d48Ricardo Garcia    setEnabled(false);
589b030df5ead9c039e4ebb16c745e2cc40e953d48Ricardo Garcia    setCaptureCallBack(NULL, NULL, 0, 0, true);
59da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
60da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
61da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::setEnabled(bool enabled)
62da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
63a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
64da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
65da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    sp<CaptureThread> t = mCaptureThread;
66da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (t != 0) {
67da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (enabled) {
68da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            if (t->exitPending()) {
69da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                if (t->requestExitAndWait() == WOULD_BLOCK) {
7029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Visualizer::enable() called from thread");
71da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                    return INVALID_OPERATION;
72da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                }
73da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            }
74da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
75da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        t->mLock.lock();
76e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten    }
77da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
78da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = AudioEffect::setEnabled(enabled);
79da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
80da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
81da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (t != 0) {
82da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            if (enabled) {
839096f3471434d7f0d2419ac0ee2a618045489718Glenn Kasten                t->run("Visualizer");
84da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            } else {
85da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent                t->requestExit();
86da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            }
87da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
88da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
89da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
90da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (t != 0) {
91da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        t->mLock.unlock();
92da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
93da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
94da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
95da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
96da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
9785ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kastenstatus_t Visualizer::setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags,
989b030df5ead9c039e4ebb16c745e2cc40e953d48Ricardo Garcia        uint32_t rate, bool force)
99da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
100da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (rate > CAPTURE_RATE_MAX) {
101da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
102da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
103a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
104da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
1059b030df5ead9c039e4ebb16c745e2cc40e953d48Ricardo Garcia    if (force || mEnabled) {
106da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return INVALID_OPERATION;
107da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
108da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
10963f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George    if (mCaptureThread != 0) {
11063f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George        mCaptureLock.unlock();
11163f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George        mCaptureThread->requestExitAndWait();
11263f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George        mCaptureLock.lock();
113da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
11463f6ffb996a7ffc920012f05c3deca731614373fHaynes Mathew George
115da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureThread.clear();
116da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureCallBack = cbk;
117da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureCbkUser = user;
118da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureFlags = flags;
119da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureRate = rate;
120da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
121da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (cbk != NULL) {
122da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureThread = new CaptureThread(*this, rate, ((flags & CAPTURE_CALL_JAVA) != 0));
123da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
1243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setCaptureCallBack() rate: %d thread %p flags 0x%08x",
125da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            rate, mCaptureThread.get(), mCaptureFlags);
126da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return NO_ERROR;
127da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
128da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
129da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::setCaptureSize(uint32_t size)
130da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
131da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (size > VISUALIZER_CAPTURE_SIZE_MAX ||
132da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        size < VISUALIZER_CAPTURE_SIZE_MIN ||
133fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        popcount(size) != 1) {
134da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
135da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
136da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
137a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
138da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mEnabled) {
139da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return INVALID_OPERATION;
140da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
141da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
142da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
143da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    effect_param_t *p = (effect_param_t *)buf32;
144da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
145da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->psize = sizeof(uint32_t);
146da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->vsize = sizeof(uint32_t);
1476d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
148da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    *((int32_t *)p->data + 1)= size;
149da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = setParameter(p);
150da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
1513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setCaptureSize size %d  status %d p->status %d", size, status, p->status);
152da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
153da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
154da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        status = p->status;
1553476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        if (status == NO_ERROR) {
1563476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi            mCaptureSize = size;
1573476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        }
158da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
1593476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1603476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    return status;
1613476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi}
1623476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1633476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivistatus_t Visualizer::setScalingMode(uint32_t mode) {
1643476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    if ((mode != VISUALIZER_SCALING_MODE_NORMALIZED)
1653476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi            && (mode != VISUALIZER_SCALING_MODE_AS_PLAYED)) {
1663476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        return BAD_VALUE;
1673476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    }
1683476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1693476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    Mutex::Autolock _l(mCaptureLock);
1703476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1713476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
1723476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    effect_param_t *p = (effect_param_t *)buf32;
1733476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1743476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    p->psize = sizeof(uint32_t);
1753476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    p->vsize = sizeof(uint32_t);
1763476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    *(int32_t *)p->data = VISUALIZER_PARAM_SCALING_MODE;
1773476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    *((int32_t *)p->data + 1)= mode;
1783476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    status_t status = setParameter(p);
1793476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
1803476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    ALOGV("setScalingMode mode %d  status %d p->status %d", mode, status, p->status);
1813476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
182da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
1833476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        status = p->status;
1843476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        if (status == NO_ERROR) {
1853476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi            mScalingMode = mode;
1863476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        }
187da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
188da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
189da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
190da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
191da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
19209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivistatus_t Visualizer::setMeasurementMode(uint32_t mode) {
19309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if ((mode != MEASUREMENT_MODE_NONE)
19409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            //Note: needs to be handled as a mask when more measurement modes are added
19509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            && ((mode & MEASUREMENT_MODE_PEAK_RMS) != mode)) {
19609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        return BAD_VALUE;
19709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
19809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
19909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    Mutex::Autolock _l(mCaptureLock);
20009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
20109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
20209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    effect_param_t *p = (effect_param_t *)buf32;
20309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
20409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    p->psize = sizeof(uint32_t);
20509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    p->vsize = sizeof(uint32_t);
20609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    *(int32_t *)p->data = VISUALIZER_PARAM_MEASUREMENT_MODE;
20709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    *((int32_t *)p->data + 1)= mode;
20809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    status_t status = setParameter(p);
20909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
21009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    ALOGV("setMeasurementMode mode %d  status %d p->status %d", mode, status, p->status);
21109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
21209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if (status == NO_ERROR) {
21309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        status = p->status;
21409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        if (status == NO_ERROR) {
21509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            mMeasurementMode = mode;
21609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        }
21709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
21809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    return status;
21909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi}
22009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
22109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivistatus_t Visualizer::getIntMeasurements(uint32_t type, uint32_t number, int32_t *measurements) {
22209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if (mMeasurementMode == MEASUREMENT_MODE_NONE) {
22309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        ALOGE("Cannot retrieve int measurements, no measurement mode set");
22409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        return INVALID_OPERATION;
22509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
22609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if (!(mMeasurementMode & type)) {
22709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        // measurement type has not been set on this Visualizer
22809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        ALOGE("Cannot retrieve int measurements, requested measurement mode 0x%x not set(0x%x)",
22909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi                type, mMeasurementMode);
23009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        return INVALID_OPERATION;
23109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
23209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    // only peak+RMS measurement supported
23309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if ((type != MEASUREMENT_MODE_PEAK_RMS)
23409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            // for peak+RMS measurement, the results are 2 int32_t values
23509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            || (number != 2)) {
23609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        ALOGE("Cannot retrieve int measurements, MEASUREMENT_MODE_PEAK_RMS returns 2 ints, not %d",
23709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi                        number);
23809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        return BAD_VALUE;
23909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
24009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
24109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    status_t status = NO_ERROR;
24209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    if (mEnabled) {
24309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        uint32_t replySize = number * sizeof(int32_t);
24409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        status = command(VISUALIZER_CMD_MEASURE,
24509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi                sizeof(uint32_t)  /*cmdSize*/,
24609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi                &type /*cmdData*/,
24709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi                &replySize, measurements);
24809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        ALOGV("getMeasurements() command returned %d", status);
24909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        if ((status == NO_ERROR) && (replySize == 0)) {
25009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi            status = NOT_ENOUGH_DATA;
25109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        }
25209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    } else {
25309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        ALOGV("getMeasurements() disabled");
25409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi        return INVALID_OPERATION;
25509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    }
25609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi    return status;
25709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi}
25809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi
259da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::getWaveForm(uint8_t *waveform)
260da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
261da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (waveform == NULL) {
262da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
263da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
264da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mCaptureSize == 0) {
265da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return NO_INIT;
266da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
267da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
268da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = NO_ERROR;
269da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mEnabled) {
27025f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent        uint32_t replySize = mCaptureSize;
2716d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent        status = command(VISUALIZER_CMD_CAPTURE, 0, NULL, &replySize, waveform);
2723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("getWaveForm() command returned %d", status);
273af7d8189f91c45ab919a6c9ac386b268c8d91168John Grossman        if ((status == NO_ERROR) && (replySize == 0)) {
274da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            status = NOT_ENOUGH_DATA;
275da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
276da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    } else {
2773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("getWaveForm() disabled");
278da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        memset(waveform, 0x80, mCaptureSize);
279da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
280da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
281da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
282da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
283da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::getFft(uint8_t *fft)
284da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
285da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (fft == NULL) {
286da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return BAD_VALUE;
287da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
288da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mCaptureSize == 0) {
289da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        return NO_INIT;
290da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
291da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
292da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = NO_ERROR;
293da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mEnabled) {
294da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t buf[mCaptureSize];
2950fa449cc475580d995e9d56756c3da5507d2b6f6Eric Laurent        status = getWaveForm(buf);
296da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (status == NO_ERROR) {
297da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            status = doFft(fft, buf);
298da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
299da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    } else {
300da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        memset(fft, 0, mCaptureSize);
301da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
302da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return status;
303da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
304da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
305da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatus_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform)
306da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
307dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    int32_t workspace[mCaptureSize >> 1];
308dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    int32_t nonzero = 0;
309dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh
310dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
3116b6a736ec71c692c165952fe653a7766075e94bbChia-chi Yeh        workspace[i >> 1] =
3126b6a736ec71c692c165952fe653a7766075e94bbChia-chi Yeh                ((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8);
313dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh        nonzero |= workspace[i >> 1];
314da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
315da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
316dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    if (nonzero) {
317dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh        fixed_fft_real(mCaptureSize >> 1, workspace);
318da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
319dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh
320dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
321209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        short tmp = workspace[i >> 1] >> 21;
322209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        while (tmp > 127 || tmp < -128) tmp >>= 1;
323209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        fft[i] = tmp;
324209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        tmp = workspace[i >> 1];
325209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        tmp >>= 5;
326209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        while (tmp > 127 || tmp < -128) tmp >>= 1;
327209821c7b7ead3ac58743d0a6d21dd05a2e77708Marco Nelissen        fft[i + 1] = tmp;
328da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
329dbd2b7e4ebfe7a586b1db4459cf6aa032a7f8719Chia-chi Yeh
330da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return NO_ERROR;
331da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
332da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
333da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentvoid Visualizer::periodicCapture()
334da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
335a9b21c5a7c24fe14d20372263c0bf5faf3d3e348Glenn Kasten    Mutex::Autolock _l(mCaptureLock);
3363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("periodicCapture() %p mCaptureCallBack %p mCaptureFlags 0x%08x",
337da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            this, mCaptureCallBack, mCaptureFlags);
338da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (mCaptureCallBack != NULL &&
339da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        (mCaptureFlags & (CAPTURE_WAVEFORM|CAPTURE_FFT)) &&
340da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureSize != 0) {
341da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t waveform[mCaptureSize];
342da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        status_t status = getWaveForm(waveform);
343da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (status != NO_ERROR) {
344da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            return;
345da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
346da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t fft[mCaptureSize];
347da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (mCaptureFlags & CAPTURE_FFT) {
348da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            status = doFft(fft, waveform);
349da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
350da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (status != NO_ERROR) {
351da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            return;
352da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
353da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t *wavePtr = NULL;
354da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint8_t *fftPtr = NULL;
355da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint32_t waveSize = 0;
356da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        uint32_t fftSize = 0;
357da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (mCaptureFlags & CAPTURE_WAVEFORM) {
358da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            wavePtr = waveform;
359da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            waveSize = mCaptureSize;
360da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
361da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        if (mCaptureFlags & CAPTURE_FFT) {
362da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            fftPtr = fft;
363da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent            fftSize = mCaptureSize;
364da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        }
365da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mCaptureCallBack(mCaptureCbkUser, waveSize, wavePtr, fftSize, fftPtr, mSampleRate);
366da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
367da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
368da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
369da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentuint32_t Visualizer::initCaptureSize()
370da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
371da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
372da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    effect_param_t *p = (effect_param_t *)buf32;
373da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
374da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->psize = sizeof(uint32_t);
375da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    p->vsize = sizeof(uint32_t);
3766d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
377da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    status_t status = getParameter(p);
378da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
379da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
380da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        status = p->status;
381da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
382da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
383da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    uint32_t size = 0;
384da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    if (status == NO_ERROR) {
385da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        size = *((int32_t *)p->data + 1);
386da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
387da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mCaptureSize = size;
388da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
3893856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initCaptureSize size %d status %d", mCaptureSize, status);
390da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
391da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return size;
392da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
393da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
3943476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivivoid Visualizer::controlStatusChanged(bool controlGranted) {
3953476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    if (controlGranted) {
3963476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        // this Visualizer instance regained control of the effect, reset the scaling mode
3973476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        //   and capture size as has been cached through it.
3983476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        ALOGV("controlStatusChanged(true) causes effect parameter reset:");
3993476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        ALOGV("    scaling mode reset to %d", mScalingMode);
4003476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        setScalingMode(mScalingMode);
4013476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        ALOGV("    capture size reset to %d", mCaptureSize);
4023476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi        setCaptureSize(mCaptureSize);
4033476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    }
4043476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi    AudioEffect::controlStatusChanged(controlGranted);
4053476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi}
4063476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi
407da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//-------------------------------------------------------------------------
408da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
40985ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn KastenVisualizer::CaptureThread::CaptureThread(Visualizer& receiver, uint32_t captureRate,
41085ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten        bool bCanCallJava)
411da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    : Thread(bCanCallJava), mReceiver(receiver)
412da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
413da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    mSleepTimeUs = 1000000000 / captureRate;
4143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("CaptureThread cstor %p captureRate %d mSleepTimeUs %d", this, captureRate, mSleepTimeUs);
415da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
416da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
417da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentbool Visualizer::CaptureThread::threadLoop()
418da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{
4193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("CaptureThread %p enter", this);
420da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    while (!exitPending())
421da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    {
422da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        usleep(mSleepTimeUs);
423da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent        mReceiver.periodicCapture();
424da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    }
4253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("CaptureThread %p exiting", this);
426da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent    return false;
427da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}
428da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent
42940bc906252974d0b389ae4a147232d0c9a97193fGlenn Kasten} // namespace android
430