Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Side by Side Diff: third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp

Issue 2389253002: reflow comments in modules/{webaudio,vr} (Closed)
Patch Set: . Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 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 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 23 matching lines...) Expand all
34 #include "modules/webaudio/PeriodicWave.h" 34 #include "modules/webaudio/PeriodicWave.h"
35 #include "modules/webaudio/PeriodicWaveOptions.h" 35 #include "modules/webaudio/PeriodicWaveOptions.h"
36 #include "platform/audio/FFTFrame.h" 36 #include "platform/audio/FFTFrame.h"
37 #include "platform/audio/VectorMath.h" 37 #include "platform/audio/VectorMath.h"
38 #include "wtf/PtrUtil.h" 38 #include "wtf/PtrUtil.h"
39 #include <algorithm> 39 #include <algorithm>
40 #include <memory> 40 #include <memory>
41 41
42 namespace blink { 42 namespace blink {
43 43
44 // The number of bands per octave. Each octave will have this many entries in t he wave tables. 44 // The number of bands per octave. Each octave will have this many entries in
45 // the wave tables.
45 const unsigned kNumberOfOctaveBands = 3; 46 const unsigned kNumberOfOctaveBands = 3;
46 47
47 // The max length of a periodic wave. This must be a power of two greater than o r equal to 2048 and 48 // The max length of a periodic wave. This must be a power of two greater than
48 // must be supported by the FFT routines. 49 // or equal to 2048 and must be supported by the FFT routines.
49 const unsigned kMaxPeriodicWaveSize = 16384; 50 const unsigned kMaxPeriodicWaveSize = 16384;
50 51
51 const float CentsPerRange = 1200 / kNumberOfOctaveBands; 52 const float CentsPerRange = 1200 / kNumberOfOctaveBands;
52 53
53 using namespace VectorMath; 54 using namespace VectorMath;
54 55
55 PeriodicWave* PeriodicWave::create(BaseAudioContext& context, 56 PeriodicWave* PeriodicWave::create(BaseAudioContext& context,
56 size_t realLength, 57 size_t realLength,
57 const float* real, 58 const float* real,
58 size_t imagLength, 59 size_t imagLength,
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 return periodicWave; 150 return periodicWave;
150 } 151 }
151 152
152 PeriodicWave::PeriodicWave(float sampleRate) 153 PeriodicWave::PeriodicWave(float sampleRate)
153 : m_v8ExternalMemory(0), 154 : m_v8ExternalMemory(0),
154 m_sampleRate(sampleRate), 155 m_sampleRate(sampleRate),
155 m_centsPerRange(CentsPerRange) { 156 m_centsPerRange(CentsPerRange) {
156 float nyquist = 0.5 * m_sampleRate; 157 float nyquist = 0.5 * m_sampleRate;
157 m_lowestFundamentalFrequency = nyquist / maxNumberOfPartials(); 158 m_lowestFundamentalFrequency = nyquist / maxNumberOfPartials();
158 m_rateScale = periodicWaveSize() / m_sampleRate; 159 m_rateScale = periodicWaveSize() / m_sampleRate;
159 // Compute the number of ranges needed to cover the entire frequency range, as suming 160 // Compute the number of ranges needed to cover the entire frequency range,
160 // kNumberOfOctaveBands per octave. 161 // assuming kNumberOfOctaveBands per octave.
161 m_numberOfRanges = 0.5 + kNumberOfOctaveBands * log2f(periodicWaveSize()); 162 m_numberOfRanges = 0.5 + kNumberOfOctaveBands * log2f(periodicWaveSize());
162 } 163 }
163 164
164 PeriodicWave::~PeriodicWave() { 165 PeriodicWave::~PeriodicWave() {
165 adjustV8ExternalMemory(-static_cast<int64_t>(m_v8ExternalMemory)); 166 adjustV8ExternalMemory(-static_cast<int64_t>(m_v8ExternalMemory));
166 } 167 }
167 168
168 unsigned PeriodicWave::periodicWaveSize() const { 169 unsigned PeriodicWave::periodicWaveSize() const {
169 // Choose an appropriate wave size for the given sample rate. This allows us to use shorter 170 // Choose an appropriate wave size for the given sample rate. This allows us
170 // FFTs when possible to limit the complexity. The breakpoints here are somew hat arbitrary, but 171 // to use shorter FFTs when possible to limit the complexity. The breakpoints
171 // we want sample rates around 44.1 kHz or so to have a size of 4096 to preser ve backward 172 // here are somewhat arbitrary, but we want sample rates around 44.1 kHz or so
172 // compatibility. 173 // to have a size of 4096 to preserve backward compatibility.
173 if (m_sampleRate <= 24000) { 174 if (m_sampleRate <= 24000) {
174 return 2048; 175 return 2048;
175 } 176 }
176 177
177 if (m_sampleRate <= 88200) { 178 if (m_sampleRate <= 88200) {
178 return 4096; 179 return 4096;
179 } 180 }
180 181
181 return kMaxPeriodicWaveSize; 182 return kMaxPeriodicWaveSize;
182 } 183 }
183 184
184 unsigned PeriodicWave::maxNumberOfPartials() const { 185 unsigned PeriodicWave::maxNumberOfPartials() const {
185 return periodicWaveSize() / 2; 186 return periodicWaveSize() / 2;
186 } 187 }
187 188
188 void PeriodicWave::waveDataForFundamentalFrequency( 189 void PeriodicWave::waveDataForFundamentalFrequency(
189 float fundamentalFrequency, 190 float fundamentalFrequency,
190 float*& lowerWaveData, 191 float*& lowerWaveData,
191 float*& higherWaveData, 192 float*& higherWaveData,
192 float& tableInterpolationFactor) { 193 float& tableInterpolationFactor) {
193 // Negative frequencies are allowed, in which case we alias to the positive fr equency. 194 // Negative frequencies are allowed, in which case we alias to the positive
195 // frequency.
194 fundamentalFrequency = fabsf(fundamentalFrequency); 196 fundamentalFrequency = fabsf(fundamentalFrequency);
195 197
196 // Calculate the pitch range. 198 // Calculate the pitch range.
197 float ratio = fundamentalFrequency > 0 199 float ratio = fundamentalFrequency > 0
198 ? fundamentalFrequency / m_lowestFundamentalFrequency 200 ? fundamentalFrequency / m_lowestFundamentalFrequency
199 : 0.5; 201 : 0.5;
200 float centsAboveLowestFrequency = log2f(ratio) * 1200; 202 float centsAboveLowestFrequency = log2f(ratio) * 1200;
201 203
202 // Add one to round-up to the next range just in time to truncate partials bef ore aliasing occurs. 204 // Add one to round-up to the next range just in time to truncate partials
205 // before aliasing occurs.
203 float pitchRange = 1 + centsAboveLowestFrequency / m_centsPerRange; 206 float pitchRange = 1 + centsAboveLowestFrequency / m_centsPerRange;
204 207
205 pitchRange = std::max(pitchRange, 0.0f); 208 pitchRange = std::max(pitchRange, 0.0f);
206 pitchRange = std::min(pitchRange, static_cast<float>(numberOfRanges() - 1)); 209 pitchRange = std::min(pitchRange, static_cast<float>(numberOfRanges() - 1));
207 210
208 // The words "lower" and "higher" refer to the table data having the lower and higher numbers of partials. 211 // The words "lower" and "higher" refer to the table data having the lower and
209 // It's a little confusing since the range index gets larger the more partials we cull out. 212 // higher numbers of partials. It's a little confusing since the range index
210 // So the lower table data will have a larger range index. 213 // gets larger the more partials we cull out. So the lower table data will
214 // have a larger range index.
211 unsigned rangeIndex1 = static_cast<unsigned>(pitchRange); 215 unsigned rangeIndex1 = static_cast<unsigned>(pitchRange);
212 unsigned rangeIndex2 = 216 unsigned rangeIndex2 =
213 rangeIndex1 < numberOfRanges() - 1 ? rangeIndex1 + 1 : rangeIndex1; 217 rangeIndex1 < numberOfRanges() - 1 ? rangeIndex1 + 1 : rangeIndex1;
214 218
215 lowerWaveData = m_bandLimitedTables[rangeIndex2]->data(); 219 lowerWaveData = m_bandLimitedTables[rangeIndex2]->data();
216 higherWaveData = m_bandLimitedTables[rangeIndex1]->data(); 220 higherWaveData = m_bandLimitedTables[rangeIndex1]->data();
217 221
218 // Ranges from 0 -> 1 to interpolate between lower -> higher. 222 // Ranges from 0 -> 1 to interpolate between lower -> higher.
219 tableInterpolationFactor = pitchRange - rangeIndex1; 223 tableInterpolationFactor = pitchRange - rangeIndex1;
220 } 224 }
221 225
222 unsigned PeriodicWave::numberOfPartialsForRange(unsigned rangeIndex) const { 226 unsigned PeriodicWave::numberOfPartialsForRange(unsigned rangeIndex) const {
223 // Number of cents below nyquist where we cull partials. 227 // Number of cents below nyquist where we cull partials.
224 float centsToCull = rangeIndex * m_centsPerRange; 228 float centsToCull = rangeIndex * m_centsPerRange;
225 229
226 // A value from 0 -> 1 representing what fraction of the partials to keep. 230 // A value from 0 -> 1 representing what fraction of the partials to keep.
227 float cullingScale = pow(2, -centsToCull / 1200); 231 float cullingScale = pow(2, -centsToCull / 1200);
228 232
229 // The very top range will have all the partials culled. 233 // The very top range will have all the partials culled.
230 unsigned numberOfPartials = cullingScale * maxNumberOfPartials(); 234 unsigned numberOfPartials = cullingScale * maxNumberOfPartials();
231 235
232 return numberOfPartials; 236 return numberOfPartials;
233 } 237 }
234 238
235 // Tell V8 about the memory we're using so it can properly schedule garbage coll ects. 239 // Tell V8 about the memory we're using so it can properly schedule garbage
240 // collects.
236 void PeriodicWave::adjustV8ExternalMemory(int delta) { 241 void PeriodicWave::adjustV8ExternalMemory(int delta) {
237 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(delta); 242 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(delta);
238 m_v8ExternalMemory += delta; 243 m_v8ExternalMemory += delta;
239 } 244 }
240 245
241 // Convert into time-domain wave buffers. 246 // Convert into time-domain wave buffers. One table is created for each range
242 // One table is created for each range for non-aliasing playback at different pl ayback rates. 247 // for non-aliasing playback at different playback rates. Thus, higher ranges
243 // Thus, higher ranges have more high-frequency partials culled out. 248 // have more high-frequency partials culled out.
244 void PeriodicWave::createBandLimitedTables(const float* realData, 249 void PeriodicWave::createBandLimitedTables(const float* realData,
245 const float* imagData, 250 const float* imagData,
246 unsigned numberOfComponents, 251 unsigned numberOfComponents,
247 bool disableNormalization) { 252 bool disableNormalization) {
248 // TODO(rtoy): Figure out why this needs to be 0.5 when normalization is disab led. 253 // TODO(rtoy): Figure out why this needs to be 0.5 when normalization is
254 // disabled.
249 float normalizationScale = 0.5; 255 float normalizationScale = 0.5;
250 256
251 unsigned fftSize = periodicWaveSize(); 257 unsigned fftSize = periodicWaveSize();
252 unsigned halfSize = fftSize / 2; 258 unsigned halfSize = fftSize / 2;
253 unsigned i; 259 unsigned i;
254 260
255 numberOfComponents = std::min(numberOfComponents, halfSize); 261 numberOfComponents = std::min(numberOfComponents, halfSize);
256 262
257 m_bandLimitedTables.reserveCapacity(numberOfRanges()); 263 m_bandLimitedTables.reserveCapacity(numberOfRanges());
258 264
259 FFTFrame frame(fftSize); 265 FFTFrame frame(fftSize);
260 for (unsigned rangeIndex = 0; rangeIndex < numberOfRanges(); ++rangeIndex) { 266 for (unsigned rangeIndex = 0; rangeIndex < numberOfRanges(); ++rangeIndex) {
261 // This FFTFrame is used to cull partials (represented by frequency bins). 267 // This FFTFrame is used to cull partials (represented by frequency bins).
262 float* realP = frame.realData(); 268 float* realP = frame.realData();
263 float* imagP = frame.imagData(); 269 float* imagP = frame.imagData();
264 270
265 // Copy from loaded frequency data and generate the complex conjugate becaus e of the way the 271 // Copy from loaded frequency data and generate the complex conjugate
266 // inverse FFT is defined versus the values in the arrays. Need to scale th e data by 272 // because of the way the inverse FFT is defined versus the values in the
267 // fftSize to remove the scaling that the inverse IFFT would do. 273 // arrays. Need to scale the data by fftSize to remove the scaling that the
274 // inverse IFFT would do.
268 float scale = fftSize; 275 float scale = fftSize;
269 vsmul(realData, 1, &scale, realP, 1, numberOfComponents); 276 vsmul(realData, 1, &scale, realP, 1, numberOfComponents);
270 scale = -scale; 277 scale = -scale;
271 vsmul(imagData, 1, &scale, imagP, 1, numberOfComponents); 278 vsmul(imagData, 1, &scale, imagP, 1, numberOfComponents);
272 279
273 // Find the starting bin where we should start culling. We need to clear ou t the highest 280 // Find the starting bin where we should start culling. We need to clear
274 // frequencies to band-limit the waveform. 281 // out the highest frequencies to band-limit the waveform.
275 unsigned numberOfPartials = numberOfPartialsForRange(rangeIndex); 282 unsigned numberOfPartials = numberOfPartialsForRange(rangeIndex);
276 283
277 // If fewer components were provided than 1/2 FFT size, then clear the remai ning bins. 284 // If fewer components were provided than 1/2 FFT size, then clear the
278 // We also need to cull the aliasing partials for this pitch range. 285 // remaining bins. We also need to cull the aliasing partials for this
286 // pitch range.
279 for (i = std::min(numberOfComponents, numberOfPartials + 1); i < halfSize; 287 for (i = std::min(numberOfComponents, numberOfPartials + 1); i < halfSize;
280 ++i) { 288 ++i) {
281 realP[i] = 0; 289 realP[i] = 0;
282 imagP[i] = 0; 290 imagP[i] = 0;
283 } 291 }
284 292
285 // Clear packed-nyquist and any DC-offset. 293 // Clear packed-nyquist and any DC-offset.
286 realP[0] = 0; 294 realP[0] = 0;
287 imagP[0] = 0; 295 imagP[0] = 0;
288 296
289 // Create the band-limited table. 297 // Create the band-limited table.
290 unsigned waveSize = periodicWaveSize(); 298 unsigned waveSize = periodicWaveSize();
291 std::unique_ptr<AudioFloatArray> table = 299 std::unique_ptr<AudioFloatArray> table =
292 wrapUnique(new AudioFloatArray(waveSize)); 300 wrapUnique(new AudioFloatArray(waveSize));
293 adjustV8ExternalMemory(waveSize * sizeof(float)); 301 adjustV8ExternalMemory(waveSize * sizeof(float));
294 m_bandLimitedTables.append(std::move(table)); 302 m_bandLimitedTables.append(std::move(table));
295 303
296 // Apply an inverse FFT to generate the time-domain table data. 304 // Apply an inverse FFT to generate the time-domain table data.
297 float* data = m_bandLimitedTables[rangeIndex]->data(); 305 float* data = m_bandLimitedTables[rangeIndex]->data();
298 frame.doInverseFFT(data); 306 frame.doInverseFFT(data);
299 307
300 // For the first range (which has the highest power), calculate its peak val ue then compute normalization scale. 308 // For the first range (which has the highest power), calculate its peak
309 // value then compute normalization scale.
301 if (!disableNormalization) { 310 if (!disableNormalization) {
302 if (!rangeIndex) { 311 if (!rangeIndex) {
303 float maxValue; 312 float maxValue;
304 vmaxmgv(data, 1, &maxValue, fftSize); 313 vmaxmgv(data, 1, &maxValue, fftSize);
305 314
306 if (maxValue) 315 if (maxValue)
307 normalizationScale = 1.0f / maxValue; 316 normalizationScale = 1.0f / maxValue;
308 } 317 }
309 } 318 }
310 319
(...skipping 11 matching lines...) Expand all
322 float* realP = real.data(); 331 float* realP = real.data();
323 float* imagP = imag.data(); 332 float* imagP = imag.data();
324 333
325 // Clear DC and Nyquist. 334 // Clear DC and Nyquist.
326 realP[0] = 0; 335 realP[0] = 0;
327 imagP[0] = 0; 336 imagP[0] = 0;
328 337
329 for (unsigned n = 1; n < halfSize; ++n) { 338 for (unsigned n = 1; n < halfSize; ++n) {
330 float piFactor = 2 / (n * piFloat); 339 float piFactor = 2 / (n * piFloat);
331 340
332 // All waveforms are odd functions with a positive slope at time 0. Hence th e coefficients 341 // All waveforms are odd functions with a positive slope at time 0. Hence
333 // for cos() are always 0. 342 // the coefficients for cos() are always 0.
334 343
335 // Fourier coefficients according to standard definition: 344 // Fourier coefficients according to standard definition:
336 // b = 1/pi*integrate(f(x)*sin(n*x), x, -pi, pi) 345 // b = 1/pi*integrate(f(x)*sin(n*x), x, -pi, pi)
337 // = 2/pi*integrate(f(x)*sin(n*x), x, 0, pi) 346 // = 2/pi*integrate(f(x)*sin(n*x), x, 0, pi)
338 // since f(x) is an odd function. 347 // since f(x) is an odd function.
339 348
340 float b; // Coefficient for sin(). 349 float b; // Coefficient for sin().
341 350
342 // Calculate Fourier coefficients depending on the shape. Note that the over all scaling 351 // Calculate Fourier coefficients depending on the shape. Note that the
343 // (magnitude) of the waveforms is normalized in createBandLimitedTables(). 352 // overall scaling (magnitude) of the waveforms is normalized in
353 // createBandLimitedTables().
344 switch (shape) { 354 switch (shape) {
345 case OscillatorHandler::SINE: 355 case OscillatorHandler::SINE:
346 // Standard sine wave function. 356 // Standard sine wave function.
347 b = (n == 1) ? 1 : 0; 357 b = (n == 1) ? 1 : 0;
348 break; 358 break;
349 case OscillatorHandler::SQUARE: 359 case OscillatorHandler::SQUARE:
350 // Square-shaped waveform with the first half its maximum value and the second half its 360 // Square-shaped waveform with the first half its maximum value and the
351 // minimum value. 361 // second half its minimum value.
352 // 362 //
353 // See http://mathworld.wolfram.com/FourierSeriesSquareWave.html 363 // See http://mathworld.wolfram.com/FourierSeriesSquareWave.html
354 // 364 //
355 // b[n] = 2/n/pi*(1-(-1)^n) 365 // b[n] = 2/n/pi*(1-(-1)^n)
356 // = 4/n/pi for n odd and 0 otherwise. 366 // = 4/n/pi for n odd and 0 otherwise.
357 // = 2*(2/(n*pi)) for n odd 367 // = 2*(2/(n*pi)) for n odd
358 b = (n & 1) ? 2 * piFactor : 0; 368 b = (n & 1) ? 2 * piFactor : 0;
359 break; 369 break;
360 case OscillatorHandler::SAWTOOTH: 370 case OscillatorHandler::SAWTOOTH:
361 // Sawtooth-shaped waveform with the first half ramping from zero to max imum and the 371 // Sawtooth-shaped waveform with the first half ramping from zero to
362 // second half from minimum to zero. 372 // maximum and the second half from minimum to zero.
363 // 373 //
364 // b[n] = -2*(-1)^n/pi/n 374 // b[n] = -2*(-1)^n/pi/n
365 // = (2/(n*pi))*(-1)^(n+1) 375 // = (2/(n*pi))*(-1)^(n+1)
366 b = piFactor * ((n & 1) ? 1 : -1); 376 b = piFactor * ((n & 1) ? 1 : -1);
367 break; 377 break;
368 case OscillatorHandler::TRIANGLE: 378 case OscillatorHandler::TRIANGLE:
369 // Triangle-shaped waveform going from 0 at time 0 to 1 at time pi/2 and back to 0 at 379 // Triangle-shaped waveform going from 0 at time 0 to 1 at time pi/2 and
370 // time pi. 380 // back to 0 at time pi.
371 // 381 //
372 // See http://mathworld.wolfram.com/FourierSeriesTriangleWave.html 382 // See http://mathworld.wolfram.com/FourierSeriesTriangleWave.html
373 // 383 //
374 // b[n] = 8*sin(pi*k/2)/(pi*k)^2 384 // b[n] = 8*sin(pi*k/2)/(pi*k)^2
375 // = 8/pi^2/n^2*(-1)^((n-1)/2) for n odd and 0 otherwise 385 // = 8/pi^2/n^2*(-1)^((n-1)/2) for n odd and 0 otherwise
376 // = 2*(2/(n*pi))^2 * (-1)^((n-1)/2) 386 // = 2*(2/(n*pi))^2 * (-1)^((n-1)/2)
377 if (n & 1) { 387 if (n & 1) {
378 b = 2 * (piFactor * piFactor) * ((((n - 1) >> 1) & 1) ? -1 : 1); 388 b = 2 * (piFactor * piFactor) * ((((n - 1) >> 1) & 1) ? -1 : 1);
379 } else { 389 } else {
380 b = 0; 390 b = 0;
381 } 391 }
382 break; 392 break;
383 default: 393 default:
384 ASSERT_NOT_REACHED(); 394 ASSERT_NOT_REACHED();
385 b = 0; 395 b = 0;
386 break; 396 break;
387 } 397 }
388 398
389 realP[n] = 0; 399 realP[n] = 0;
390 imagP[n] = b; 400 imagP[n] = b;
391 } 401 }
392 402
393 createBandLimitedTables(realP, imagP, halfSize, false); 403 createBandLimitedTables(realP, imagP, halfSize, false);
394 } 404 }
395 405
396 } // namespace blink 406 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698