Changeset 116596 in webkit
- Timestamp:
- May 9, 2012 7:32:46 PM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r116595 r116596 1 2012-05-09 Raymond Liu <raymond.liu@intel.com> 2 3 Add multi-channels support for CopyWithGainFrom in AudioBus 4 https://bugs.webkit.org/show_bug.cgi?id=80675 5 6 Reviewed by Chris Rogers. 7 8 * platform/audio/AudioBus.cpp: 9 (WebCore): 10 (WebCore::AudioBus::AudioBus): 11 (WebCore::AudioBus::copyWithGainFrom): 12 * platform/audio/AudioBus.h: 13 (AudioBus): 14 1 15 2012-05-09 Jessie Berlin <jberlin@apple.com> 2 16 -
trunk/Source/WebCore/platform/audio/AudioBus.cpp
r113728 r116596 46 46 47 47 using namespace VectorMath; 48 48 49 const unsigned MaxBusChannels = 32; 50 49 51 AudioBus::AudioBus(unsigned numberOfChannels, size_t length, bool allocate) 50 52 : m_length(length) … … 53 55 , m_sampleRate(0) 54 56 { 57 ASSERT(numberOfChannels <= MaxBusChannels); 58 if (numberOfChannels > MaxBusChannels) 59 return; 60 55 61 m_channels.reserveInitialCapacity(numberOfChannels); 56 62 … … 308 314 } 309 315 310 // Slowly change gain to desired gain. 311 #define GAIN_DEZIPPER \ 312 gain += (totalDesiredGain - gain) * DezipperRate; \ 313 gain = DenormalDisabler::flushDenormalFloatToZero(gain); 314 315 // De-zipper for the first framesToDezipper frames and skip de-zippering for the remaining frames 316 // because the gain is close enough to the target gain. 317 #define PROCESS_WITH_GAIN(OP) \ 318 for (k = 0; k < framesToDezipper; ++k) { \ 319 OP \ 320 GAIN_DEZIPPER \ 321 } \ 322 if (!framesToDezipper) \ 323 gain = totalDesiredGain; \ 324 OP##_V 325 326 #define STEREO_SUM \ 327 { \ 328 float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \ 329 float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + gain * *sourceR++); \ 330 *destinationL++ = sumL; \ 331 *destinationR++ = sumR; \ 332 } 333 334 #define STEREO_SUM_V \ 335 { \ 336 vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \ 337 vsma(sourceR, 1, &gain, destinationR, 1, framesToProcess - k); \ 338 } 339 340 // Mono -> stereo (mix equally into L and R) 341 // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center... 342 #define MONO2STEREO_SUM \ 343 { \ 344 float scaled = gain * *sourceL++; \ 345 float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + scaled); \ 346 float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + scaled); \ 347 *destinationL++ = sumL; \ 348 *destinationR++ = sumR; \ 349 } 350 351 #define MONO2STEREO_SUM_V \ 352 { \ 353 vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \ 354 vsma(sourceL, 1, &gain, destinationR, 1, framesToProcess - k); \ 355 } 356 357 #define MONO_SUM \ 358 { \ 359 float sum = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \ 360 *destinationL++ = sum; \ 361 } 362 363 #define MONO_SUM_V \ 364 { \ 365 vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \ 366 } 367 368 #define STEREO_NO_SUM \ 369 { \ 370 float sampleL = *sourceL++; \ 371 float sampleR = *sourceR++; \ 372 *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \ 373 *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleR); \ 374 } 375 376 #define STEREO_NO_SUM_V \ 377 { \ 378 vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \ 379 vsmul(sourceR, 1, &gain, destinationR, 1, framesToProcess - k); \ 380 } 381 382 // Mono -> stereo (mix equally into L and R) 383 // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center... 384 #define MONO2STEREO_NO_SUM \ 385 { \ 386 float sample = *sourceL++; \ 387 *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample); \ 388 *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample); \ 389 } 390 391 #define MONO2STEREO_NO_SUM_V \ 392 { \ 393 vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \ 394 vsmul(sourceL, 1, &gain, destinationR, 1, framesToProcess - k); \ 395 } 396 397 #define MONO_NO_SUM \ 398 { \ 399 float sampleL = *sourceL++; \ 400 *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \ 401 } 402 403 #define MONO_NO_SUM_V \ 404 { \ 405 vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \ 406 } 407 408 void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus) 409 { 316 void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain) 317 { 318 if (!topologyMatches(sourceBus)) { 319 ASSERT_NOT_REACHED(); 320 zero(); 321 return; 322 } 323 324 if (sourceBus.isSilent()) { 325 zero(); 326 return; 327 } 328 329 unsigned numberOfChannels = this->numberOfChannels(); 330 ASSERT(numberOfChannels <= MaxBusChannels); 331 if (numberOfChannels > MaxBusChannels) 332 return; 333 334 // If it is copying from the same bus and no need to change gain, just return. 335 if (this == &sourceBus && *lastMixGain == targetGain && targetGain == 1) 336 return; 337 338 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus); 339 const float* sources[MaxBusChannels]; 340 float* destinations[MaxBusChannels]; 341 342 for (unsigned i = 0; i < numberOfChannels; ++i) { 343 sources[i] = sourceBusSafe.channel(i)->data(); 344 destinations[i] = channel(i)->mutableData(); 345 } 346 410 347 // We don't want to suddenly change the gain from mixing one time slice to the next, 411 348 // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain. … … 418 355 m_isFirstTime = false; 419 356 420 int numberOfSourceChannels = sourceBus.numberOfChannels();421 int numberOfDestinationChannels = numberOfChannels();422 423 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);424 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();425 const float* sourceR = numberOfSourceChannels > 1 ? sourceBusSafe.channelByType(ChannelRight)->data() : 0;426 427 if (sourceBusSafe.isSilent()) {428 if (!sumToBus)429 zero();430 return;431 }432 433 float* destinationL = channelByType(ChannelLeft)->mutableData();434 float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->mutableData() : 0;435 436 357 const float DezipperRate = 0.005f; 437 intframesToProcess = length();358 unsigned framesToProcess = length(); 438 359 439 360 // If the gain is within epsilon of totalDesiredGain, we can skip dezippering. … … 443 364 444 365 // Number of frames to de-zipper before we are close enough to the target gain. 445 int framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess; 446 447 int k = 0; 448 449 if (sumToBus) { 450 // Sum to our bus 451 if (sourceR && destinationR) { 452 // Stereo 453 PROCESS_WITH_GAIN(STEREO_SUM) 454 } else if (destinationR) { 455 // Mono -> stereo 456 PROCESS_WITH_GAIN(MONO2STEREO_SUM) 457 } else { 458 // Mono 459 PROCESS_WITH_GAIN(MONO_SUM) 460 } 461 } else { 462 // Process directly (without summing) to our bus 463 if (sourceR && destinationR) { 464 // Stereo 465 PROCESS_WITH_GAIN(STEREO_NO_SUM) 466 } else if (destinationR) { 467 // Mono -> stereo 468 PROCESS_WITH_GAIN(MONO2STEREO_NO_SUM) 469 } else { 470 // Mono 471 PROCESS_WITH_GAIN(MONO_NO_SUM) 472 } 366 // FIXME: framesToDezipper could be smaller when target gain is close enough within this process loop. 367 unsigned framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess; 368 369 if (framesToDezipper) { 370 if (!m_dezipperGainValues.get() || m_dezipperGainValues->size() < framesToDezipper) 371 m_dezipperGainValues = adoptPtr(new AudioFloatArray(framesToDezipper)); 372 373 float* gainValues = m_dezipperGainValues->data(); 374 for (unsigned i = 0; i < framesToDezipper; ++i) { 375 gain += (totalDesiredGain - gain) * DezipperRate; 376 377 // FIXME: If we are clever enough in calculating the framesToDezipper value, we can probably get 378 // rid of this DenormalDisabler::flushDenormalFloatToZero() call. 379 gain = DenormalDisabler::flushDenormalFloatToZero(gain); 380 *gainValues++ = gain; 381 } 382 383 for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) { 384 vmul(sources[channelIndex], 1, m_dezipperGainValues->data(), 1, destinations[channelIndex], 1, framesToDezipper); 385 sources[channelIndex] += framesToDezipper; 386 destinations[channelIndex] += framesToDezipper; 387 } 388 } else 389 gain = totalDesiredGain; 390 391 // Apply constant gain after de-zippering has converged on target gain. 392 if (framesToDezipper < framesToProcess) { 393 for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) 394 vsmul(sources[channelIndex], 1, &gain, destinations[channelIndex], 1, framesToProcess - framesToDezipper); 473 395 } 474 396 475 397 // Save the target gain as the starting point for next time around. 476 398 *lastMixGain = gain; 477 }478 479 void AudioBus::processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)480 {481 // Make sure we're summing from same type of bus.482 // We *are* able to sum from mono -> stereo483 if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {484 ASSERT_NOT_REACHED();485 return;486 }487 // If it is copying from the same bus and no need to change gain, just return488 if (!sumToBus && this == &sourceBus && *lastMixGain == targetGain && targetGain == 1.0)489 return;490 491 // Dispatch for different channel layouts492 switch (numberOfChannels()) {493 case 1: // mono494 case 2: // stereo495 processWithGainFromMonoStereo(sourceBus, lastMixGain, targetGain, sumToBus);496 break;497 case 4: // FIXME: implement quad498 case 5: // FIXME: implement 5.0499 default:500 ASSERT_NOT_REACHED();501 break;502 }503 399 } 504 400 … … 530 426 vmul(source, 1, gainValues, 1, destination, 1, numberOfGainValues); 531 427 } 532 }533 534 void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)535 {536 processWithGainFrom(sourceBus, lastMixGain, targetGain, false);537 }538 539 void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)540 {541 processWithGainFrom(sourceBus, lastMixGain, targetGain, true);542 428 } 543 429 -
trunk/Source/WebCore/platform/audio/AudioBus.h
r113728 r116596 110 110 void scale(float scale); 111 111 112 // Master gain for this bus - used with sumWithGainFrom() below113 void setGain(float gain) { m_busGain = gain; }114 float gain() const { return m_busGain; }115 116 112 void reset() { m_isFirstTime = true; } // for de-zippering 117 113 … … 123 119 void sumFrom(const AudioBus &sourceBus); 124 120 125 // Copy or sumeach channel from sourceBus into our corresponding channel.121 // Copy each channel from sourceBus into our corresponding channel. 126 122 // We scale by targetGain (and our own internal gain m_busGain), performing "de-zippering" to smoothly change from *lastMixGain to (targetGain*m_busGain). 127 // The caller is responsible for setting up lastMixGain to point to storage which is unique for every "stream" which will be summed to this bus.123 // The caller is responsible for setting up lastMixGain to point to storage which is unique for every "stream" which will be applied to this bus. 128 124 // This represents the dezippering memory. 129 125 void copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain); 130 void sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain);131 126 132 127 // Copies the sourceBus by scaling with sample-accurate gain values. … … 144 139 AudioBus() { }; 145 140 146 void processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus);147 void processWithGainFromMonoStereo(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus);148 149 141 size_t m_length; 150 151 142 Vector<OwnPtr<AudioChannel> > m_channels; 152 153 143 int m_layout; 154 155 144 float m_busGain; 145 OwnPtr<AudioFloatArray> m_dezipperGainValues; 156 146 bool m_isFirstTime; 157 147 float m_sampleRate; // 0.0 if unknown or N/A
Note: See TracChangeset
for help on using the changeset viewer.