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