OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010, Google Inc. All rights reserved. | 2 * Copyright (C) 2010, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 22 matching lines...) Expand all Loading... |
33 #include "platform/audio/VectorMath.h" | 33 #include "platform/audio/VectorMath.h" |
34 | 34 |
35 #include <algorithm> | 35 #include <algorithm> |
36 #include <limits.h> | 36 #include <limits.h> |
37 #include "wtf/Complex.h" | 37 #include "wtf/Complex.h" |
38 #include "wtf/Float32Array.h" | 38 #include "wtf/Float32Array.h" |
39 #include "wtf/MainThread.h" | 39 #include "wtf/MainThread.h" |
40 #include "wtf/MathExtras.h" | 40 #include "wtf/MathExtras.h" |
41 #include "wtf/Uint8Array.h" | 41 #include "wtf/Uint8Array.h" |
42 | 42 |
43 using namespace std; | |
44 | |
45 namespace WebCore { | 43 namespace WebCore { |
46 | 44 |
47 const double RealtimeAnalyser::DefaultSmoothingTimeConstant = 0.8; | 45 const double RealtimeAnalyser::DefaultSmoothingTimeConstant = 0.8; |
48 const double RealtimeAnalyser::DefaultMinDecibels = -100; | 46 const double RealtimeAnalyser::DefaultMinDecibels = -100; |
49 const double RealtimeAnalyser::DefaultMaxDecibels = -30; | 47 const double RealtimeAnalyser::DefaultMaxDecibels = -30; |
50 | 48 |
51 const unsigned RealtimeAnalyser::DefaultFFTSize = 2048; | 49 const unsigned RealtimeAnalyser::DefaultFFTSize = 2048; |
52 // All FFT implementations are expected to handle power-of-two sizes MinFFTSize
<= size <= MaxFFTSize. | 50 // All FFT implementations are expected to handle power-of-two sizes MinFFTSize
<= size <= MaxFFTSize. |
53 const unsigned RealtimeAnalyser::MinFFTSize = 32; | 51 const unsigned RealtimeAnalyser::MinFFTSize = 32; |
54 const unsigned RealtimeAnalyser::MaxFFTSize = 2048; | 52 const unsigned RealtimeAnalyser::MaxFFTSize = 2048; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 float* imagP = m_analysisFrame->imagData(); | 172 float* imagP = m_analysisFrame->imagData(); |
175 | 173 |
176 // Blow away the packed nyquist component. | 174 // Blow away the packed nyquist component. |
177 imagP[0] = 0; | 175 imagP[0] = 0; |
178 | 176 |
179 // Normalize so than an input sine wave at 0dBfs registers as 0dBfs (undo FF
T scaling factor). | 177 // Normalize so than an input sine wave at 0dBfs registers as 0dBfs (undo FF
T scaling factor). |
180 const double magnitudeScale = 1.0 / fftSize; | 178 const double magnitudeScale = 1.0 / fftSize; |
181 | 179 |
182 // A value of 0 does no averaging with the previous result. Larger values p
roduce slower, but smoother changes. | 180 // A value of 0 does no averaging with the previous result. Larger values p
roduce slower, but smoother changes. |
183 double k = m_smoothingTimeConstant; | 181 double k = m_smoothingTimeConstant; |
184 k = max(0.0, k); | 182 k = std::max(0.0, k); |
185 k = min(1.0, k); | 183 k = std::min(1.0, k); |
186 | 184 |
187 // Convert the analysis data from complex to magnitude and average with the
previous result. | 185 // Convert the analysis data from complex to magnitude and average with the
previous result. |
188 float* destination = magnitudeBuffer().data(); | 186 float* destination = magnitudeBuffer().data(); |
189 size_t n = magnitudeBuffer().size(); | 187 size_t n = magnitudeBuffer().size(); |
190 for (size_t i = 0; i < n; ++i) { | 188 for (size_t i = 0; i < n; ++i) { |
191 Complex c(realP[i], imagP[i]); | 189 Complex c(realP[i], imagP[i]); |
192 double scalarMagnitude = abs(c) * magnitudeScale; | 190 double scalarMagnitude = abs(c) * magnitudeScale; |
193 destination[i] = float(k * destination[i] + (1 - k) * scalarMagnitude); | 191 destination[i] = float(k * destination[i] + (1 - k) * scalarMagnitude); |
194 } | 192 } |
195 } | 193 } |
196 | 194 |
197 void RealtimeAnalyser::getFloatFrequencyData(Float32Array* destinationArray) | 195 void RealtimeAnalyser::getFloatFrequencyData(Float32Array* destinationArray) |
198 { | 196 { |
199 ASSERT(isMainThread()); | 197 ASSERT(isMainThread()); |
200 | 198 |
201 if (!destinationArray) | 199 if (!destinationArray) |
202 return; | 200 return; |
203 | 201 |
204 doFFTAnalysis(); | 202 doFFTAnalysis(); |
205 | 203 |
206 // Convert from linear magnitude to floating-point decibels. | 204 // Convert from linear magnitude to floating-point decibels. |
207 const double minDecibels = m_minDecibels; | 205 const double minDecibels = m_minDecibels; |
208 unsigned sourceLength = magnitudeBuffer().size(); | 206 unsigned sourceLength = magnitudeBuffer().size(); |
209 size_t len = min(sourceLength, destinationArray->length()); | 207 size_t len = std::min(sourceLength, destinationArray->length()); |
210 if (len > 0) { | 208 if (len > 0) { |
211 const float* source = magnitudeBuffer().data(); | 209 const float* source = magnitudeBuffer().data(); |
212 float* destination = destinationArray->data(); | 210 float* destination = destinationArray->data(); |
213 | 211 |
214 for (unsigned i = 0; i < len; ++i) { | 212 for (unsigned i = 0; i < len; ++i) { |
215 float linearValue = source[i]; | 213 float linearValue = source[i]; |
216 double dbMag = !linearValue ? minDecibels : AudioUtilities::linearTo
Decibels(linearValue); | 214 double dbMag = !linearValue ? minDecibels : AudioUtilities::linearTo
Decibels(linearValue); |
217 destination[i] = float(dbMag); | 215 destination[i] = float(dbMag); |
218 } | 216 } |
219 } | 217 } |
220 } | 218 } |
221 | 219 |
222 void RealtimeAnalyser::getByteFrequencyData(Uint8Array* destinationArray) | 220 void RealtimeAnalyser::getByteFrequencyData(Uint8Array* destinationArray) |
223 { | 221 { |
224 ASSERT(isMainThread()); | 222 ASSERT(isMainThread()); |
225 | 223 |
226 if (!destinationArray) | 224 if (!destinationArray) |
227 return; | 225 return; |
228 | 226 |
229 doFFTAnalysis(); | 227 doFFTAnalysis(); |
230 | 228 |
231 // Convert from linear magnitude to unsigned-byte decibels. | 229 // Convert from linear magnitude to unsigned-byte decibels. |
232 unsigned sourceLength = magnitudeBuffer().size(); | 230 unsigned sourceLength = magnitudeBuffer().size(); |
233 size_t len = min(sourceLength, destinationArray->length()); | 231 size_t len = std::min(sourceLength, destinationArray->length()); |
234 if (len > 0) { | 232 if (len > 0) { |
235 const double rangeScaleFactor = m_maxDecibels == m_minDecibels ? 1 : 1 /
(m_maxDecibels - m_minDecibels); | 233 const double rangeScaleFactor = m_maxDecibels == m_minDecibels ? 1 : 1 /
(m_maxDecibels - m_minDecibels); |
236 const double minDecibels = m_minDecibels; | 234 const double minDecibels = m_minDecibels; |
237 | 235 |
238 const float* source = magnitudeBuffer().data(); | 236 const float* source = magnitudeBuffer().data(); |
239 unsigned char* destination = destinationArray->data(); | 237 unsigned char* destination = destinationArray->data(); |
240 | 238 |
241 for (unsigned i = 0; i < len; ++i) { | 239 for (unsigned i = 0; i < len; ++i) { |
242 float linearValue = source[i]; | 240 float linearValue = source[i]; |
243 double dbMag = !linearValue ? minDecibels : AudioUtilities::linearTo
Decibels(linearValue); | 241 double dbMag = !linearValue ? minDecibels : AudioUtilities::linearTo
Decibels(linearValue); |
(...skipping 13 matching lines...) Expand all Loading... |
257 } | 255 } |
258 | 256 |
259 void RealtimeAnalyser::getFloatTimeDomainData(Float32Array* destinationArray) | 257 void RealtimeAnalyser::getFloatTimeDomainData(Float32Array* destinationArray) |
260 { | 258 { |
261 ASSERT(isMainThread()); | 259 ASSERT(isMainThread()); |
262 | 260 |
263 if (!destinationArray) | 261 if (!destinationArray) |
264 return; | 262 return; |
265 | 263 |
266 unsigned fftSize = this->fftSize(); | 264 unsigned fftSize = this->fftSize(); |
267 size_t len = min(fftSize, destinationArray->length()); | 265 size_t len = std::min(fftSize, destinationArray->length()); |
268 if (len > 0) { | 266 if (len > 0) { |
269 bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_in
putBuffer.size() > fftSize; | 267 bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_in
putBuffer.size() > fftSize; |
270 ASSERT(isInputBufferGood); | 268 ASSERT(isInputBufferGood); |
271 if (!isInputBufferGood) | 269 if (!isInputBufferGood) |
272 return; | 270 return; |
273 | 271 |
274 float* inputBuffer = m_inputBuffer.data(); | 272 float* inputBuffer = m_inputBuffer.data(); |
275 float* destination = destinationArray->data(); | 273 float* destination = destinationArray->data(); |
276 | 274 |
277 unsigned writeIndex = m_writeIndex; | 275 unsigned writeIndex = m_writeIndex; |
278 | 276 |
279 for (unsigned i = 0; i < len; ++i) { | 277 for (unsigned i = 0; i < len; ++i) { |
280 // Buffer access is protected due to modulo operation. | 278 // Buffer access is protected due to modulo operation. |
281 float value = inputBuffer[(i + writeIndex - fftSize + InputBufferSiz
e) % InputBufferSize]; | 279 float value = inputBuffer[(i + writeIndex - fftSize + InputBufferSiz
e) % InputBufferSize]; |
282 | 280 |
283 destination[i] = value; | 281 destination[i] = value; |
284 } | 282 } |
285 } | 283 } |
286 } | 284 } |
287 | 285 |
288 void RealtimeAnalyser::getByteTimeDomainData(Uint8Array* destinationArray) | 286 void RealtimeAnalyser::getByteTimeDomainData(Uint8Array* destinationArray) |
289 { | 287 { |
290 ASSERT(isMainThread()); | 288 ASSERT(isMainThread()); |
291 | 289 |
292 if (!destinationArray) | 290 if (!destinationArray) |
293 return; | 291 return; |
294 | 292 |
295 unsigned fftSize = this->fftSize(); | 293 unsigned fftSize = this->fftSize(); |
296 size_t len = min(fftSize, destinationArray->length()); | 294 size_t len = std::min(fftSize, destinationArray->length()); |
297 if (len > 0) { | 295 if (len > 0) { |
298 bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_in
putBuffer.size() > fftSize; | 296 bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_in
putBuffer.size() > fftSize; |
299 ASSERT(isInputBufferGood); | 297 ASSERT(isInputBufferGood); |
300 if (!isInputBufferGood) | 298 if (!isInputBufferGood) |
301 return; | 299 return; |
302 | 300 |
303 float* inputBuffer = m_inputBuffer.data(); | 301 float* inputBuffer = m_inputBuffer.data(); |
304 unsigned char* destination = destinationArray->data(); | 302 unsigned char* destination = destinationArray->data(); |
305 | 303 |
306 unsigned writeIndex = m_writeIndex; | 304 unsigned writeIndex = m_writeIndex; |
(...skipping 12 matching lines...) Expand all Loading... |
319 scaledValue = UCHAR_MAX; | 317 scaledValue = UCHAR_MAX; |
320 | 318 |
321 destination[i] = static_cast<unsigned char>(scaledValue); | 319 destination[i] = static_cast<unsigned char>(scaledValue); |
322 } | 320 } |
323 } | 321 } |
324 } | 322 } |
325 | 323 |
326 } // namespace WebCore | 324 } // namespace WebCore |
327 | 325 |
328 #endif // ENABLE(WEB_AUDIO) | 326 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |