| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 1 | /* | 
 | 2 | ** | 
 | 3 | ** Copyright 2010, The Android Open Source Project | 
 | 4 | ** | 
 | 5 | ** Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 6 | ** you may not use this file except in compliance with the License. | 
 | 7 | ** You may obtain a copy of the License at | 
 | 8 | ** | 
 | 9 | **     http://www.apache.org/licenses/LICENSE-2.0 | 
 | 10 | ** | 
 | 11 | ** Unless required by applicable law or agreed to in writing, software | 
 | 12 | ** distributed under the License is distributed on an "AS IS" BASIS, | 
 | 13 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 14 | ** See the License for the specific language governing permissions and | 
 | 15 | ** limitations under the License. | 
 | 16 | */ | 
 | 17 |  | 
 | 18 |  | 
 | 19 | //#define LOG_NDEBUG 0 | 
 | 20 | #define LOG_TAG "Visualizer" | 
 | 21 | #include <utils/Log.h> | 
 | 22 |  | 
 | 23 | #include <stdint.h> | 
 | 24 | #include <sys/types.h> | 
 | 25 | #include <limits.h> | 
 | 26 |  | 
 | 27 | #include <media/Visualizer.h> | 
| Glenn Kasten | 3f6448e | 2012-01-16 13:11:50 -0800 | [diff] [blame] | 28 | #include <audio_utils/fixedfft.h> | 
| Glenn Kasten | 1ab85ec | 2013-05-31 09:18:43 -0700 | [diff] [blame] | 29 | #include <utils/Thread.h> | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 30 |  | 
 | 31 | namespace android { | 
 | 32 |  | 
 | 33 | // --------------------------------------------------------------------------- | 
 | 34 |  | 
| Svet Ganov | be71aa2 | 2015-04-28 12:06:02 -0700 | [diff] [blame] | 35 | Visualizer::Visualizer (const String16& opPackageName, | 
 | 36 |          int32_t priority, | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 37 |          effect_callback_t cbf, | 
 | 38 |          void* user, | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 39 |          audio_session_t sessionId) | 
| Svet Ganov | be71aa2 | 2015-04-28 12:06:02 -0700 | [diff] [blame] | 40 |     :   AudioEffect(SL_IID_VISUALIZATION, opPackageName, NULL, priority, cbf, user, sessionId), | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 41 |         mCaptureRate(CAPTURE_RATE_DEF), | 
 | 42 |         mCaptureSize(CAPTURE_SIZE_DEF), | 
 | 43 |         mSampleRate(44100000), | 
| Jean-Michel Trivi | 3476de6 | 2012-04-15 17:15:07 -0700 | [diff] [blame] | 44 |         mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED), | 
| Jean-Michel Trivi | 09647d2 | 2013-09-20 11:58:40 -0700 | [diff] [blame] | 45 |         mMeasurementMode(MEASUREMENT_MODE_NONE), | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 46 |         mCaptureCallBack(NULL), | 
 | 47 |         mCaptureCbkUser(NULL) | 
 | 48 | { | 
 | 49 |     initCaptureSize(); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 50 | } | 
 | 51 |  | 
 | 52 | Visualizer::~Visualizer() | 
 | 53 | { | 
| Haynes Mathew George | 63f6ffb | 2014-09-25 10:33:12 -0700 | [diff] [blame] | 54 |     ALOGV("Visualizer::~Visualizer()"); | 
| Ricardo Garcia | 9b030df | 2015-06-18 21:01:53 -0700 | [diff] [blame] | 55 |     setEnabled(false); | 
| ganxiaolin | 2e5b570 | 2016-01-29 19:57:57 +0800 | [diff] [blame] | 56 |     setCaptureCallBack(NULL, NULL, 0, 0); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 57 | } | 
 | 58 |  | 
| zengjing | 704c577 | 2018-09-29 13:25:35 +0800 | [diff] [blame] | 59 | void Visualizer::release() | 
 | 60 | { | 
 | 61 |     ALOGV("Visualizer::release()"); | 
 | 62 |     setEnabled(false); | 
 | 63 |     Mutex::Autolock _l(mCaptureLock); | 
 | 64 |  | 
 | 65 |     mCaptureThread.clear(); | 
 | 66 |     mCaptureCallBack = NULL; | 
 | 67 |     mCaptureCbkUser = NULL; | 
 | 68 |     mCaptureFlags = 0; | 
 | 69 |     mCaptureRate = 0; | 
 | 70 | } | 
 | 71 |  | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 72 | status_t Visualizer::setEnabled(bool enabled) | 
 | 73 | { | 
| Glenn Kasten | a9b21c5 | 2012-01-17 10:06:38 -0800 | [diff] [blame] | 74 |     Mutex::Autolock _l(mCaptureLock); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 75 |  | 
 | 76 |     sp<CaptureThread> t = mCaptureThread; | 
 | 77 |     if (t != 0) { | 
 | 78 |         if (enabled) { | 
 | 79 |             if (t->exitPending()) { | 
 | 80 |                 if (t->requestExitAndWait() == WOULD_BLOCK) { | 
| Steve Block | 29357bc | 2012-01-06 19:20:56 +0000 | [diff] [blame] | 81 |                     ALOGE("Visualizer::enable() called from thread"); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 82 |                     return INVALID_OPERATION; | 
 | 83 |                 } | 
 | 84 |             } | 
 | 85 |         } | 
 | 86 |         t->mLock.lock(); | 
| Glenn Kasten | e53b9ea | 2012-03-12 16:29:55 -0700 | [diff] [blame] | 87 |     } | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 88 |  | 
 | 89 |     status_t status = AudioEffect::setEnabled(enabled); | 
 | 90 |  | 
| ganxiaolin | 2e5b570 | 2016-01-29 19:57:57 +0800 | [diff] [blame] | 91 |     if (t != 0) { | 
 | 92 |         if (enabled && status == NO_ERROR) { | 
 | 93 |             t->run("Visualizer"); | 
 | 94 |         } else { | 
 | 95 |             t->requestExit(); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 96 |         } | 
 | 97 |     } | 
 | 98 |  | 
 | 99 |     if (t != 0) { | 
 | 100 |         t->mLock.unlock(); | 
 | 101 |     } | 
 | 102 |  | 
 | 103 |     return status; | 
 | 104 | } | 
 | 105 |  | 
| Glenn Kasten | 85ab62c | 2012-11-01 11:11:38 -0700 | [diff] [blame] | 106 | status_t Visualizer::setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, | 
| ganxiaolin | 2e5b570 | 2016-01-29 19:57:57 +0800 | [diff] [blame] | 107 |         uint32_t rate) | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 108 | { | 
 | 109 |     if (rate > CAPTURE_RATE_MAX) { | 
 | 110 |         return BAD_VALUE; | 
 | 111 |     } | 
| Glenn Kasten | a9b21c5 | 2012-01-17 10:06:38 -0800 | [diff] [blame] | 112 |     Mutex::Autolock _l(mCaptureLock); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 113 |  | 
| ganxiaolin | 2e5b570 | 2016-01-29 19:57:57 +0800 | [diff] [blame] | 114 |     if (mEnabled) { | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 115 |         return INVALID_OPERATION; | 
 | 116 |     } | 
 | 117 |  | 
| Haynes Mathew George | 63f6ffb | 2014-09-25 10:33:12 -0700 | [diff] [blame] | 118 |     if (mCaptureThread != 0) { | 
 | 119 |         mCaptureLock.unlock(); | 
 | 120 |         mCaptureThread->requestExitAndWait(); | 
 | 121 |         mCaptureLock.lock(); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 122 |     } | 
| Haynes Mathew George | 63f6ffb | 2014-09-25 10:33:12 -0700 | [diff] [blame] | 123 |  | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 124 |     mCaptureThread.clear(); | 
 | 125 |     mCaptureCallBack = cbk; | 
 | 126 |     mCaptureCbkUser = user; | 
 | 127 |     mCaptureFlags = flags; | 
 | 128 |     mCaptureRate = rate; | 
 | 129 |  | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 130 |     if (cbk != NULL) { | 
| zengjing | 704c577 | 2018-09-29 13:25:35 +0800 | [diff] [blame] | 131 |         mCaptureThread = new CaptureThread(this, rate, ((flags & CAPTURE_CALL_JAVA) != 0)); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 132 |     } | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 133 |     ALOGV("setCaptureCallBack() rate: %d thread %p flags 0x%08x", | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 134 |             rate, mCaptureThread.get(), mCaptureFlags); | 
 | 135 |     return NO_ERROR; | 
 | 136 | } | 
 | 137 |  | 
 | 138 | status_t Visualizer::setCaptureSize(uint32_t size) | 
 | 139 | { | 
 | 140 |     if (size > VISUALIZER_CAPTURE_SIZE_MAX || | 
 | 141 |         size < VISUALIZER_CAPTURE_SIZE_MIN || | 
| Dima Zavin | fce7a47 | 2011-04-19 22:30:36 -0700 | [diff] [blame] | 142 |         popcount(size) != 1) { | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 143 |         return BAD_VALUE; | 
 | 144 |     } | 
 | 145 |  | 
| Glenn Kasten | a9b21c5 | 2012-01-17 10:06:38 -0800 | [diff] [blame] | 146 |     Mutex::Autolock _l(mCaptureLock); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 147 |     if (mEnabled) { | 
 | 148 |         return INVALID_OPERATION; | 
 | 149 |     } | 
 | 150 |  | 
 | 151 |     uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2]; | 
 | 152 |     effect_param_t *p = (effect_param_t *)buf32; | 
 | 153 |  | 
 | 154 |     p->psize = sizeof(uint32_t); | 
 | 155 |     p->vsize = sizeof(uint32_t); | 
| Eric Laurent | 6d8b694 | 2011-06-24 07:01:31 -0700 | [diff] [blame] | 156 |     *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE; | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 157 |     *((int32_t *)p->data + 1)= size; | 
 | 158 |     status_t status = setParameter(p); | 
 | 159 |  | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 160 |     ALOGV("setCaptureSize size %d  status %d p->status %d", size, status, p->status); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 161 |  | 
 | 162 |     if (status == NO_ERROR) { | 
 | 163 |         status = p->status; | 
| Jean-Michel Trivi | 3476de6 | 2012-04-15 17:15:07 -0700 | [diff] [blame] | 164 |         if (status == NO_ERROR) { | 
 | 165 |             mCaptureSize = size; | 
 | 166 |         } | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 167 |     } | 
| Jean-Michel Trivi | 3476de6 | 2012-04-15 17:15:07 -0700 | [diff] [blame] | 168 |  | 
 | 169 |     return status; | 
 | 170 | } | 
 | 171 |  | 
 | 172 | status_t Visualizer::setScalingMode(uint32_t mode) { | 
 | 173 |     if ((mode != VISUALIZER_SCALING_MODE_NORMALIZED) | 
 | 174 |             && (mode != VISUALIZER_SCALING_MODE_AS_PLAYED)) { | 
 | 175 |         return BAD_VALUE; | 
 | 176 |     } | 
 | 177 |  | 
 | 178 |     Mutex::Autolock _l(mCaptureLock); | 
 | 179 |  | 
 | 180 |     uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2]; | 
 | 181 |     effect_param_t *p = (effect_param_t *)buf32; | 
 | 182 |  | 
 | 183 |     p->psize = sizeof(uint32_t); | 
 | 184 |     p->vsize = sizeof(uint32_t); | 
 | 185 |     *(int32_t *)p->data = VISUALIZER_PARAM_SCALING_MODE; | 
 | 186 |     *((int32_t *)p->data + 1)= mode; | 
 | 187 |     status_t status = setParameter(p); | 
 | 188 |  | 
 | 189 |     ALOGV("setScalingMode mode %d  status %d p->status %d", mode, status, p->status); | 
 | 190 |  | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 191 |     if (status == NO_ERROR) { | 
| Jean-Michel Trivi | 3476de6 | 2012-04-15 17:15:07 -0700 | [diff] [blame] | 192 |         status = p->status; | 
 | 193 |         if (status == NO_ERROR) { | 
 | 194 |             mScalingMode = mode; | 
 | 195 |         } | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 196 |     } | 
 | 197 |  | 
 | 198 |     return status; | 
 | 199 | } | 
 | 200 |  | 
| Jean-Michel Trivi | 09647d2 | 2013-09-20 11:58:40 -0700 | [diff] [blame] | 201 | status_t Visualizer::setMeasurementMode(uint32_t mode) { | 
 | 202 |     if ((mode != MEASUREMENT_MODE_NONE) | 
 | 203 |             //Note: needs to be handled as a mask when more measurement modes are added | 
 | 204 |             && ((mode & MEASUREMENT_MODE_PEAK_RMS) != mode)) { | 
 | 205 |         return BAD_VALUE; | 
 | 206 |     } | 
 | 207 |  | 
 | 208 |     Mutex::Autolock _l(mCaptureLock); | 
 | 209 |  | 
 | 210 |     uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2]; | 
 | 211 |     effect_param_t *p = (effect_param_t *)buf32; | 
 | 212 |  | 
 | 213 |     p->psize = sizeof(uint32_t); | 
 | 214 |     p->vsize = sizeof(uint32_t); | 
 | 215 |     *(int32_t *)p->data = VISUALIZER_PARAM_MEASUREMENT_MODE; | 
 | 216 |     *((int32_t *)p->data + 1)= mode; | 
 | 217 |     status_t status = setParameter(p); | 
 | 218 |  | 
 | 219 |     ALOGV("setMeasurementMode mode %d  status %d p->status %d", mode, status, p->status); | 
 | 220 |  | 
 | 221 |     if (status == NO_ERROR) { | 
 | 222 |         status = p->status; | 
 | 223 |         if (status == NO_ERROR) { | 
 | 224 |             mMeasurementMode = mode; | 
 | 225 |         } | 
 | 226 |     } | 
 | 227 |     return status; | 
 | 228 | } | 
 | 229 |  | 
 | 230 | status_t Visualizer::getIntMeasurements(uint32_t type, uint32_t number, int32_t *measurements) { | 
 | 231 |     if (mMeasurementMode == MEASUREMENT_MODE_NONE) { | 
 | 232 |         ALOGE("Cannot retrieve int measurements, no measurement mode set"); | 
 | 233 |         return INVALID_OPERATION; | 
 | 234 |     } | 
 | 235 |     if (!(mMeasurementMode & type)) { | 
 | 236 |         // measurement type has not been set on this Visualizer | 
 | 237 |         ALOGE("Cannot retrieve int measurements, requested measurement mode 0x%x not set(0x%x)", | 
 | 238 |                 type, mMeasurementMode); | 
 | 239 |         return INVALID_OPERATION; | 
 | 240 |     } | 
 | 241 |     // only peak+RMS measurement supported | 
 | 242 |     if ((type != MEASUREMENT_MODE_PEAK_RMS) | 
 | 243 |             // for peak+RMS measurement, the results are 2 int32_t values | 
 | 244 |             || (number != 2)) { | 
 | 245 |         ALOGE("Cannot retrieve int measurements, MEASUREMENT_MODE_PEAK_RMS returns 2 ints, not %d", | 
 | 246 |                         number); | 
 | 247 |         return BAD_VALUE; | 
 | 248 |     } | 
 | 249 |  | 
 | 250 |     status_t status = NO_ERROR; | 
 | 251 |     if (mEnabled) { | 
 | 252 |         uint32_t replySize = number * sizeof(int32_t); | 
 | 253 |         status = command(VISUALIZER_CMD_MEASURE, | 
 | 254 |                 sizeof(uint32_t)  /*cmdSize*/, | 
 | 255 |                 &type /*cmdData*/, | 
 | 256 |                 &replySize, measurements); | 
 | 257 |         ALOGV("getMeasurements() command returned %d", status); | 
 | 258 |         if ((status == NO_ERROR) && (replySize == 0)) { | 
 | 259 |             status = NOT_ENOUGH_DATA; | 
 | 260 |         } | 
 | 261 |     } else { | 
 | 262 |         ALOGV("getMeasurements() disabled"); | 
 | 263 |         return INVALID_OPERATION; | 
 | 264 |     } | 
 | 265 |     return status; | 
 | 266 | } | 
 | 267 |  | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 268 | status_t Visualizer::getWaveForm(uint8_t *waveform) | 
 | 269 | { | 
 | 270 |     if (waveform == NULL) { | 
 | 271 |         return BAD_VALUE; | 
 | 272 |     } | 
 | 273 |     if (mCaptureSize == 0) { | 
 | 274 |         return NO_INIT; | 
 | 275 |     } | 
 | 276 |  | 
 | 277 |     status_t status = NO_ERROR; | 
 | 278 |     if (mEnabled) { | 
| Eric Laurent | 25f4395 | 2010-07-28 05:40:18 -0700 | [diff] [blame] | 279 |         uint32_t replySize = mCaptureSize; | 
| Eric Laurent | 6d8b694 | 2011-06-24 07:01:31 -0700 | [diff] [blame] | 280 |         status = command(VISUALIZER_CMD_CAPTURE, 0, NULL, &replySize, waveform); | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 281 |         ALOGV("getWaveForm() command returned %d", status); | 
| John Grossman | af7d818 | 2012-01-11 12:23:42 -0800 | [diff] [blame] | 282 |         if ((status == NO_ERROR) && (replySize == 0)) { | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 283 |             status = NOT_ENOUGH_DATA; | 
 | 284 |         } | 
 | 285 |     } else { | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 286 |         ALOGV("getWaveForm() disabled"); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 287 |         memset(waveform, 0x80, mCaptureSize); | 
 | 288 |     } | 
 | 289 |     return status; | 
 | 290 | } | 
 | 291 |  | 
 | 292 | status_t Visualizer::getFft(uint8_t *fft) | 
 | 293 | { | 
 | 294 |     if (fft == NULL) { | 
 | 295 |         return BAD_VALUE; | 
 | 296 |     } | 
 | 297 |     if (mCaptureSize == 0) { | 
 | 298 |         return NO_INIT; | 
 | 299 |     } | 
 | 300 |  | 
 | 301 |     status_t status = NO_ERROR; | 
 | 302 |     if (mEnabled) { | 
 | 303 |         uint8_t buf[mCaptureSize]; | 
| Eric Laurent | 0fa449c | 2010-09-24 11:52:04 -0700 | [diff] [blame] | 304 |         status = getWaveForm(buf); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 305 |         if (status == NO_ERROR) { | 
 | 306 |             status = doFft(fft, buf); | 
 | 307 |         } | 
 | 308 |     } else { | 
 | 309 |         memset(fft, 0, mCaptureSize); | 
 | 310 |     } | 
 | 311 |     return status; | 
 | 312 | } | 
 | 313 |  | 
 | 314 | status_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform) | 
 | 315 | { | 
| Chia-chi Yeh | dbd2b7e | 2010-08-19 15:34:10 +0800 | [diff] [blame] | 316 |     int32_t workspace[mCaptureSize >> 1]; | 
 | 317 |     int32_t nonzero = 0; | 
 | 318 |  | 
 | 319 |     for (uint32_t i = 0; i < mCaptureSize; i += 2) { | 
| Chia-chi Yeh | 6b6a736 | 2010-11-01 10:56:45 +0800 | [diff] [blame] | 320 |         workspace[i >> 1] = | 
 | 321 |                 ((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8); | 
| Chia-chi Yeh | dbd2b7e | 2010-08-19 15:34:10 +0800 | [diff] [blame] | 322 |         nonzero |= workspace[i >> 1]; | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 323 |     } | 
 | 324 |  | 
| Chia-chi Yeh | dbd2b7e | 2010-08-19 15:34:10 +0800 | [diff] [blame] | 325 |     if (nonzero) { | 
 | 326 |         fixed_fft_real(mCaptureSize >> 1, workspace); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 327 |     } | 
| Chia-chi Yeh | dbd2b7e | 2010-08-19 15:34:10 +0800 | [diff] [blame] | 328 |  | 
 | 329 |     for (uint32_t i = 0; i < mCaptureSize; i += 2) { | 
| Marco Nelissen | 209821c | 2011-01-18 16:44:28 -0800 | [diff] [blame] | 330 |         short tmp = workspace[i >> 1] >> 21; | 
 | 331 |         while (tmp > 127 || tmp < -128) tmp >>= 1; | 
 | 332 |         fft[i] = tmp; | 
 | 333 |         tmp = workspace[i >> 1]; | 
 | 334 |         tmp >>= 5; | 
 | 335 |         while (tmp > 127 || tmp < -128) tmp >>= 1; | 
 | 336 |         fft[i + 1] = tmp; | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 337 |     } | 
| Chia-chi Yeh | dbd2b7e | 2010-08-19 15:34:10 +0800 | [diff] [blame] | 338 |  | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 339 |     return NO_ERROR; | 
 | 340 | } | 
 | 341 |  | 
 | 342 | void Visualizer::periodicCapture() | 
 | 343 | { | 
| Glenn Kasten | a9b21c5 | 2012-01-17 10:06:38 -0800 | [diff] [blame] | 344 |     Mutex::Autolock _l(mCaptureLock); | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 345 |     ALOGV("periodicCapture() %p mCaptureCallBack %p mCaptureFlags 0x%08x", | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 346 |             this, mCaptureCallBack, mCaptureFlags); | 
 | 347 |     if (mCaptureCallBack != NULL && | 
 | 348 |         (mCaptureFlags & (CAPTURE_WAVEFORM|CAPTURE_FFT)) && | 
 | 349 |         mCaptureSize != 0) { | 
 | 350 |         uint8_t waveform[mCaptureSize]; | 
 | 351 |         status_t status = getWaveForm(waveform); | 
 | 352 |         if (status != NO_ERROR) { | 
 | 353 |             return; | 
 | 354 |         } | 
 | 355 |         uint8_t fft[mCaptureSize]; | 
 | 356 |         if (mCaptureFlags & CAPTURE_FFT) { | 
 | 357 |             status = doFft(fft, waveform); | 
 | 358 |         } | 
 | 359 |         if (status != NO_ERROR) { | 
 | 360 |             return; | 
 | 361 |         } | 
 | 362 |         uint8_t *wavePtr = NULL; | 
 | 363 |         uint8_t *fftPtr = NULL; | 
 | 364 |         uint32_t waveSize = 0; | 
 | 365 |         uint32_t fftSize = 0; | 
 | 366 |         if (mCaptureFlags & CAPTURE_WAVEFORM) { | 
 | 367 |             wavePtr = waveform; | 
 | 368 |             waveSize = mCaptureSize; | 
 | 369 |         } | 
 | 370 |         if (mCaptureFlags & CAPTURE_FFT) { | 
 | 371 |             fftPtr = fft; | 
 | 372 |             fftSize = mCaptureSize; | 
 | 373 |         } | 
 | 374 |         mCaptureCallBack(mCaptureCbkUser, waveSize, wavePtr, fftSize, fftPtr, mSampleRate); | 
 | 375 |     } | 
 | 376 | } | 
 | 377 |  | 
 | 378 | uint32_t Visualizer::initCaptureSize() | 
 | 379 | { | 
 | 380 |     uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2]; | 
 | 381 |     effect_param_t *p = (effect_param_t *)buf32; | 
 | 382 |  | 
 | 383 |     p->psize = sizeof(uint32_t); | 
 | 384 |     p->vsize = sizeof(uint32_t); | 
| Eric Laurent | 6d8b694 | 2011-06-24 07:01:31 -0700 | [diff] [blame] | 385 |     *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE; | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 386 |     status_t status = getParameter(p); | 
 | 387 |  | 
 | 388 |     if (status == NO_ERROR) { | 
 | 389 |         status = p->status; | 
 | 390 |     } | 
 | 391 |  | 
 | 392 |     uint32_t size = 0; | 
 | 393 |     if (status == NO_ERROR) { | 
 | 394 |         size = *((int32_t *)p->data + 1); | 
 | 395 |     } | 
 | 396 |     mCaptureSize = size; | 
 | 397 |  | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 398 |     ALOGV("initCaptureSize size %d status %d", mCaptureSize, status); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 399 |  | 
 | 400 |     return size; | 
 | 401 | } | 
 | 402 |  | 
| Jean-Michel Trivi | 3476de6 | 2012-04-15 17:15:07 -0700 | [diff] [blame] | 403 | void Visualizer::controlStatusChanged(bool controlGranted) { | 
 | 404 |     if (controlGranted) { | 
 | 405 |         // this Visualizer instance regained control of the effect, reset the scaling mode | 
 | 406 |         //   and capture size as has been cached through it. | 
 | 407 |         ALOGV("controlStatusChanged(true) causes effect parameter reset:"); | 
 | 408 |         ALOGV("    scaling mode reset to %d", mScalingMode); | 
 | 409 |         setScalingMode(mScalingMode); | 
 | 410 |         ALOGV("    capture size reset to %d", mCaptureSize); | 
 | 411 |         setCaptureSize(mCaptureSize); | 
 | 412 |     } | 
 | 413 |     AudioEffect::controlStatusChanged(controlGranted); | 
 | 414 | } | 
 | 415 |  | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 416 | //------------------------------------------------------------------------- | 
 | 417 |  | 
| zengjing | 704c577 | 2018-09-29 13:25:35 +0800 | [diff] [blame] | 418 | Visualizer::CaptureThread::CaptureThread(Visualizer* receiver, uint32_t captureRate, | 
| Glenn Kasten | 85ab62c | 2012-11-01 11:11:38 -0700 | [diff] [blame] | 419 |         bool bCanCallJava) | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 420 |     : Thread(bCanCallJava), mReceiver(receiver) | 
 | 421 | { | 
 | 422 |     mSleepTimeUs = 1000000000 / captureRate; | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 423 |     ALOGV("CaptureThread cstor %p captureRate %d mSleepTimeUs %d", this, captureRate, mSleepTimeUs); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 424 | } | 
 | 425 |  | 
 | 426 | bool Visualizer::CaptureThread::threadLoop() | 
 | 427 | { | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 428 |     ALOGV("CaptureThread %p enter", this); | 
| zengjing | 704c577 | 2018-09-29 13:25:35 +0800 | [diff] [blame] | 429 |     sp<Visualizer> receiver = mReceiver.promote(); | 
 | 430 |     if (receiver == NULL) { | 
 | 431 |         return false; | 
 | 432 |     } | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 433 |     while (!exitPending()) | 
 | 434 |     { | 
 | 435 |         usleep(mSleepTimeUs); | 
| zengjing | 704c577 | 2018-09-29 13:25:35 +0800 | [diff] [blame] | 436 |         receiver->periodicCapture(); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 437 |     } | 
| Steve Block | 3856b09 | 2011-10-20 11:56:00 +0100 | [diff] [blame] | 438 |     ALOGV("CaptureThread %p exiting", this); | 
| Eric Laurent | da7581b | 2010-07-02 08:12:41 -0700 | [diff] [blame] | 439 |     return false; | 
 | 440 | } | 
 | 441 |  | 
| Glenn Kasten | 40bc906 | 2015-03-20 09:09:33 -0700 | [diff] [blame] | 442 | } // namespace android |