Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 * 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 outputBus->zero(); | 219 outputBus->zero(); |
| 220 return; | 220 return; |
| 221 } | 221 } |
| 222 | 222 |
| 223 ASSERT(framesToProcess <= m_phaseIncrements.size()); | 223 ASSERT(framesToProcess <= m_phaseIncrements.size()); |
| 224 if (framesToProcess > m_phaseIncrements.size()) | 224 if (framesToProcess > m_phaseIncrements.size()) |
| 225 return; | 225 return; |
| 226 | 226 |
| 227 // The audio thread can't block on this lock, so we call tryLock() instead. | 227 // The audio thread can't block on this lock, so we call tryLock() instead. |
| 228 MutexTryLocker tryLocker(m_processLock); | 228 MutexTryLocker tryLocker(m_processLock); |
| 229 if (!tryLocker.locked()) { | 229 if (tryLocker.locked()) { |
| 230 // Too bad - the tryLock() failed. We must be in the middle of changing wave-tables. | 230 |
|
tkent
2015/09/11 00:02:00
Is this change necessary? The scope of tryLocker
| |
| 231 // We must access m_periodicWave only inside the lock. | |
| 232 if (!m_periodicWave.get()) { | |
| 233 outputBus->zero(); | |
| 234 return; | |
| 235 } | |
| 236 | |
| 237 size_t quantumFrameOffset; | |
| 238 size_t nonSilentFramesToProcess; | |
| 239 | |
| 240 updateSchedulingInfo(framesToProcess, outputBus, quantumFrameOffset, non SilentFramesToProcess); | |
| 241 | |
| 242 if (!nonSilentFramesToProcess) { | |
| 243 outputBus->zero(); | |
| 244 return; | |
| 245 } | |
| 246 | |
| 247 unsigned periodicWaveSize = m_periodicWave->periodicWaveSize(); | |
| 248 double invPeriodicWaveSize = 1.0 / periodicWaveSize; | |
| 249 | |
| 250 float* destP = outputBus->channel(0)->mutableData(); | |
| 251 | |
| 252 ASSERT(quantumFrameOffset <= framesToProcess); | |
| 253 | |
| 254 // We keep virtualReadIndex double-precision since we're accumulating va lues. | |
| 255 double virtualReadIndex = m_virtualReadIndex; | |
| 256 | |
| 257 float rateScale = m_periodicWave->rateScale(); | |
| 258 float invRateScale = 1 / rateScale; | |
| 259 bool hasSampleAccurateValues = calculateSampleAccuratePhaseIncrements(fr amesToProcess); | |
| 260 | |
| 261 float frequency = 0; | |
| 262 float* higherWaveData = 0; | |
| 263 float* lowerWaveData = 0; | |
| 264 float tableInterpolationFactor = 0; | |
| 265 | |
| 266 if (!hasSampleAccurateValues) { | |
| 267 frequency = m_frequency->smoothedValue(); | |
| 268 float detune = m_detune->smoothedValue(); | |
| 269 float detuneScale = powf(2, detune / 1200); | |
| 270 frequency *= detuneScale; | |
| 271 m_periodicWave->waveDataForFundamentalFrequency(frequency, lowerWave Data, higherWaveData, tableInterpolationFactor); | |
| 272 } | |
| 273 | |
| 274 float incr = frequency * rateScale; | |
| 275 float* phaseIncrements = m_phaseIncrements.data(); | |
| 276 | |
| 277 unsigned readIndexMask = periodicWaveSize - 1; | |
| 278 | |
| 279 // Start rendering at the correct offset. | |
| 280 destP += quantumFrameOffset; | |
| 281 int n = nonSilentFramesToProcess; | |
| 282 | |
| 283 while (n--) { | |
| 284 unsigned readIndex = static_cast<unsigned>(virtualReadIndex); | |
| 285 unsigned readIndex2 = readIndex + 1; | |
| 286 | |
| 287 // Contain within valid range. | |
| 288 readIndex = readIndex & readIndexMask; | |
| 289 readIndex2 = readIndex2 & readIndexMask; | |
| 290 | |
| 291 if (hasSampleAccurateValues) { | |
| 292 incr = *phaseIncrements++; | |
| 293 | |
| 294 frequency = invRateScale * incr; | |
| 295 m_periodicWave->waveDataForFundamentalFrequency(frequency, lower WaveData, higherWaveData, tableInterpolationFactor); | |
| 296 } | |
| 297 | |
| 298 float sample1Lower = lowerWaveData[readIndex]; | |
| 299 float sample2Lower = lowerWaveData[readIndex2]; | |
| 300 float sample1Higher = higherWaveData[readIndex]; | |
| 301 float sample2Higher = higherWaveData[readIndex2]; | |
| 302 | |
| 303 // Linearly interpolate within each table (lower and higher). | |
| 304 float interpolationFactor = static_cast<float>(virtualReadIndex) - r eadIndex; | |
| 305 float sampleHigher = (1 - interpolationFactor) * sample1Higher + int erpolationFactor * sample2Higher; | |
| 306 float sampleLower = (1 - interpolationFactor) * sample1Lower + inter polationFactor * sample2Lower; | |
| 307 | |
| 308 // Then interpolate between the two tables. | |
| 309 float sample = (1 - tableInterpolationFactor) * sampleHigher + table InterpolationFactor * sampleLower; | |
| 310 | |
| 311 *destP++ = sample; | |
| 312 | |
| 313 // Increment virtual read index and wrap virtualReadIndex into the r ange 0 -> periodicWaveSize. | |
| 314 virtualReadIndex += incr; | |
| 315 virtualReadIndex -= floor(virtualReadIndex * invPeriodicWaveSize) * periodicWaveSize; | |
| 316 } | |
| 317 | |
| 318 m_virtualReadIndex = virtualReadIndex; | |
| 319 | |
| 320 outputBus->clearSilentFlag(); | |
| 321 } else { | |
| 322 // Too bad - the tryLock() failed. We must be in the middle of changing wave-tables or | |
| 323 // updating scheduling. | |
| 231 outputBus->zero(); | 324 outputBus->zero(); |
| 232 return; | 325 return; |
| 233 } | 326 } |
| 234 | |
| 235 // We must access m_periodicWave only inside the lock. | |
| 236 if (!m_periodicWave.get()) { | |
| 237 outputBus->zero(); | |
| 238 return; | |
| 239 } | |
| 240 | |
| 241 size_t quantumFrameOffset; | |
| 242 size_t nonSilentFramesToProcess; | |
| 243 | |
| 244 updateSchedulingInfo(framesToProcess, outputBus, quantumFrameOffset, nonSile ntFramesToProcess); | |
| 245 | |
| 246 if (!nonSilentFramesToProcess) { | |
| 247 outputBus->zero(); | |
| 248 return; | |
| 249 } | |
| 250 | |
| 251 unsigned periodicWaveSize = m_periodicWave->periodicWaveSize(); | |
| 252 double invPeriodicWaveSize = 1.0 / periodicWaveSize; | |
| 253 | |
| 254 float* destP = outputBus->channel(0)->mutableData(); | |
| 255 | |
| 256 ASSERT(quantumFrameOffset <= framesToProcess); | |
| 257 | |
| 258 // We keep virtualReadIndex double-precision since we're accumulating values . | |
| 259 double virtualReadIndex = m_virtualReadIndex; | |
| 260 | |
| 261 float rateScale = m_periodicWave->rateScale(); | |
| 262 float invRateScale = 1 / rateScale; | |
| 263 bool hasSampleAccurateValues = calculateSampleAccuratePhaseIncrements(frames ToProcess); | |
| 264 | |
| 265 float frequency = 0; | |
| 266 float* higherWaveData = 0; | |
| 267 float* lowerWaveData = 0; | |
| 268 float tableInterpolationFactor = 0; | |
| 269 | |
| 270 if (!hasSampleAccurateValues) { | |
| 271 frequency = m_frequency->smoothedValue(); | |
| 272 float detune = m_detune->smoothedValue(); | |
| 273 float detuneScale = powf(2, detune / 1200); | |
| 274 frequency *= detuneScale; | |
| 275 m_periodicWave->waveDataForFundamentalFrequency(frequency, lowerWaveData , higherWaveData, tableInterpolationFactor); | |
| 276 } | |
| 277 | |
| 278 float incr = frequency * rateScale; | |
| 279 float* phaseIncrements = m_phaseIncrements.data(); | |
| 280 | |
| 281 unsigned readIndexMask = periodicWaveSize - 1; | |
| 282 | |
| 283 // Start rendering at the correct offset. | |
| 284 destP += quantumFrameOffset; | |
| 285 int n = nonSilentFramesToProcess; | |
| 286 | |
| 287 while (n--) { | |
| 288 unsigned readIndex = static_cast<unsigned>(virtualReadIndex); | |
| 289 unsigned readIndex2 = readIndex + 1; | |
| 290 | |
| 291 // Contain within valid range. | |
| 292 readIndex = readIndex & readIndexMask; | |
| 293 readIndex2 = readIndex2 & readIndexMask; | |
| 294 | |
| 295 if (hasSampleAccurateValues) { | |
| 296 incr = *phaseIncrements++; | |
| 297 | |
| 298 frequency = invRateScale * incr; | |
| 299 m_periodicWave->waveDataForFundamentalFrequency(frequency, lowerWave Data, higherWaveData, tableInterpolationFactor); | |
| 300 } | |
| 301 | |
| 302 float sample1Lower = lowerWaveData[readIndex]; | |
| 303 float sample2Lower = lowerWaveData[readIndex2]; | |
| 304 float sample1Higher = higherWaveData[readIndex]; | |
| 305 float sample2Higher = higherWaveData[readIndex2]; | |
| 306 | |
| 307 // Linearly interpolate within each table (lower and higher). | |
| 308 float interpolationFactor = static_cast<float>(virtualReadIndex) - readI ndex; | |
| 309 float sampleHigher = (1 - interpolationFactor) * sample1Higher + interpo lationFactor * sample2Higher; | |
| 310 float sampleLower = (1 - interpolationFactor) * sample1Lower + interpola tionFactor * sample2Lower; | |
| 311 | |
| 312 // Then interpolate between the two tables. | |
| 313 float sample = (1 - tableInterpolationFactor) * sampleHigher + tableInte rpolationFactor * sampleLower; | |
| 314 | |
| 315 *destP++ = sample; | |
| 316 | |
| 317 // Increment virtual read index and wrap virtualReadIndex into the range 0 -> periodicWaveSize. | |
| 318 virtualReadIndex += incr; | |
| 319 virtualReadIndex -= floor(virtualReadIndex * invPeriodicWaveSize) * peri odicWaveSize; | |
| 320 } | |
| 321 | |
| 322 m_virtualReadIndex = virtualReadIndex; | |
| 323 | |
| 324 outputBus->clearSilentFlag(); | |
| 325 } | 327 } |
| 326 | 328 |
| 327 void OscillatorHandler::setPeriodicWave(PeriodicWave* periodicWave) | 329 void OscillatorHandler::setPeriodicWave(PeriodicWave* periodicWave) |
| 328 { | 330 { |
| 329 ASSERT(isMainThread()); | 331 ASSERT(isMainThread()); |
| 330 | 332 |
| 331 // This synchronizes with process(). | 333 // This synchronizes with process(). |
| 332 MutexLocker processLocker(m_processLock); | 334 MutexLocker processLocker(m_processLock); |
| 333 m_periodicWave = periodicWave; | 335 m_periodicWave = periodicWave; |
| 334 m_type = CUSTOM; | 336 m_type = CUSTOM; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 389 } | 391 } |
| 390 | 392 |
| 391 void OscillatorNode::setPeriodicWave(PeriodicWave* wave) | 393 void OscillatorNode::setPeriodicWave(PeriodicWave* wave) |
| 392 { | 394 { |
| 393 oscillatorHandler().setPeriodicWave(wave); | 395 oscillatorHandler().setPeriodicWave(wave); |
| 394 } | 396 } |
| 395 | 397 |
| 396 } // namespace blink | 398 } // namespace blink |
| 397 | 399 |
| 398 #endif // ENABLE(WEB_AUDIO) | 400 #endif // ENABLE(WEB_AUDIO) |
| OLD | NEW |