Source/WebCore/ChangeLog

 12012-03-18 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 NOBODY (OOPS!).
 7
 8 * platform/audio/AudioBus.cpp:
 9 (WebCore):
 10 (WebCore::AudioBus::AudioBus):
 11 (WebCore::AudioBus::setChannelMemory):
 12 (WebCore::AudioBus::copyWithGainFrom):
 13 * platform/audio/AudioBus.h:
 14 (AudioBus):
 15
1162012-03-18 Dana Jansens <danakj@chromium.org>
217
318 [chromium] Transform animation state should be inherited from parents

Source/WebCore/platform/audio/AudioBus.cpp

4545namespace WebCore {
4646
4747using namespace VectorMath;
48 
 48
 49const unsigned MaxBusChannels = 32;
 50
4951AudioBus::AudioBus(unsigned numberOfChannels, size_t length, bool allocate)
5052 : m_length(length)
5153 , m_busGain(1)
5254 , m_isFirstTime(true)
5355 , m_sampleRate(0)
5456{
 57 ASSERT(numberOfChannels <= MaxBusChannels);
 58 if (numberOfChannels > MaxBusChannels)
 59 numberOfChannels = MaxBusChannels;
 60
5561 m_channels.reserveInitialCapacity(numberOfChannels);
5662
5763 for (unsigned i = 0; i < numberOfChannels; ++i) {

@@AudioBus::AudioBus(unsigned numberOfChannels, size_t length, bool allocate)
5965 m_channels.append(channel);
6066 }
6167
 68 m_gainValues = adoptPtr(new AudioFloatArray(length));
 69
6270 m_layout = LayoutCanonical; // for now this is the only layout we define
6371}
6472

@@void AudioBus::setChannelMemory(unsigned channelIndex, float* storage, size_t le
6674{
6775 if (channelIndex < m_channels.size()) {
6876 channel(channelIndex)->set(storage, length);
69  m_length = length; // FIXME: verify that this length matches all the other channel lengths
 77 if (m_length != length) {
 78 // FIXME: verify that this length matches all the other channel lengths
 79 m_length = length;
 80 m_gainValues = adoptPtr(new AudioFloatArray(length));
 81 }
7082 }
7183}
7284

@@void AudioBus::sumFrom(const AudioBus &sourceBus)
307319 }
308320}
309321
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); \
 322void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
 323{
 324 if (!topologyMatches(sourceBus)) {
 325 ASSERT_NOT_REACHED();
 326 zero();
 327 return;
374328 }
375329
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  }
 330 // If it is copying from the same bus and no need to change gain, just return.
 331 if (this == &sourceBus && *lastMixGain == targetGain && targetGain == 1)
 332 return;
381333
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  }
 334 unsigned numberOfChannels = this->numberOfChannels();
390335
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  }
 336 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
 337 const float* sources[MaxBusChannels];
 338 float* destinations[MaxBusChannels];
396339
397 #define MONO_NO_SUM \
398  { \
399  float sampleL = *sourceL++; \
400  *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \
 340 for (unsigned i = 0; i < numberOfChannels; ++i) {
 341 sources[i] = sourceBusSafe.channel(i)->data();
 342 destinations[i] = channel(i)->mutableData();
401343 }
402344
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 {
410345 // We don't want to suddenly change the gain from mixing one time slice to the next,
411346 // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain.
412347

@@void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, float* l
417352 float gain = static_cast<float>(m_isFirstTime ? totalDesiredGain : *lastMixGain);
418353 m_isFirstTime = false;
419354
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  float* destinationL = channelByType(ChannelLeft)->mutableData();
428  float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->mutableData() : 0;
429 
430355 const float DezipperRate = 0.005f;
431  int framesToProcess = length();
 356 unsigned framesToProcess = length();
432357
433358 // If the gain is within epsilon of totalDesiredGain, we can skip dezippering.
434359 // FIXME: this value may need tweaking.

@@void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, float* l
436361 float gainDiff = fabs(totalDesiredGain - gain);
437362
438363 // Number of frames to de-zipper before we are close enough to the target gain.
439  int framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess;
440 
441  int k = 0;
442 
443  if (sumToBus) {
444  // Sum to our bus
445  if (sourceR && destinationR) {
446  // Stereo
447  PROCESS_WITH_GAIN(STEREO_SUM)
448  } else if (destinationR) {
449  // Mono -> stereo
450  PROCESS_WITH_GAIN(MONO2STEREO_SUM)
451  } else {
452  // Mono
453  PROCESS_WITH_GAIN(MONO_SUM)
 364 // FIXME: framesToDezipper could be smaller when target gain is close enough within this process loop.
 365 unsigned framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess;
 366
 367 if (framesToDezipper) {
 368 float* gainValues = m_gainValues->data();
 369 for (unsigned i = 0; i < framesToDezipper; ++i) {
 370 gain += (totalDesiredGain - gain) * DezipperRate;
 371
 372 // FIXME: If we are clever enough in calculating the framesToDezipper value, we can probably get
 373 // rid of this DenormalDisabler::flushDenormalFloatToZero() call.
 374 gain = DenormalDisabler::flushDenormalFloatToZero(gain);
 375 *gainValues++ = gain;
454376 }
455  } else {
456  // Process directly (without summing) to our bus
457  if (sourceR && destinationR) {
458  // Stereo
459  PROCESS_WITH_GAIN(STEREO_NO_SUM)
460  } else if (destinationR) {
461  // Mono -> stereo
462  PROCESS_WITH_GAIN(MONO2STEREO_NO_SUM)
463  } else {
464  // Mono
465  PROCESS_WITH_GAIN(MONO_NO_SUM)
 377
 378 // reset gainVaules to m_gainVaules array head, for it has been modified above.
 379 gainValues = m_gainValues->data();
 380
 381 for (unsigned index = 0; index < numberOfChannels; ++index) {
 382 vmul(sources[index], 1, gainValues, 1, destinations[index], 1, framesToDezipper);
 383 sources[index] += framesToDezipper;
 384 destinations[index] += framesToDezipper;
466385 }
 386 } else
 387 gain = totalDesiredGain;
 388
 389 if (framesToDezipper < framesToProcess) {
 390 for (unsigned index = 0; index < numberOfChannels; ++index)
 391 vsmul(sources[index], 1, &gain, destinations[index], 1, framesToProcess - framesToDezipper);
467392 }
468393
469394 // Save the target gain as the starting point for next time around.
470395 *lastMixGain = gain;
471396}
472397
473 void AudioBus::processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)
474 {
475  // Make sure we're summing from same type of bus.
476  // We *are* able to sum from mono -> stereo
477  if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
478  ASSERT_NOT_REACHED();
479  return;
480  }
481  // If it is copying from the same bus and no need to change gain, just return
482  if (!sumToBus && this == &sourceBus && *lastMixGain == targetGain && targetGain == 1.0)
483  return;
484 
485  // Dispatch for different channel layouts
486  switch (numberOfChannels()) {
487  case 1: // mono
488  case 2: // stereo
489  processWithGainFromMonoStereo(sourceBus, lastMixGain, targetGain, sumToBus);
490  break;
491  case 4: // FIXME: implement quad
492  case 5: // FIXME: implement 5.0
493  default:
494  ASSERT_NOT_REACHED();
495  break;
496  }
497 }
498 
499398void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues)
500399{
501400 // Make sure we're processing from the same type of bus.

@@void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, f
520419 }
521420}
522421
523 void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
524 {
525  processWithGainFrom(sourceBus, lastMixGain, targetGain, false);
526 }
527 
528 void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
529 {
530  processWithGainFrom(sourceBus, lastMixGain, targetGain, true);
531 }
532 
533422PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sourceBus, bool mixToMono, double newSampleRate)
534423{
535424 // sourceBus's sample-rate must be known.

Source/WebCore/platform/audio/AudioBus.h

@@public:
103103 // Scales all samples by the same amount.
104104 void scale(float scale);
105105
106  // Master gain for this bus - used with sumWithGainFrom() below
107  void setGain(float gain) { m_busGain = gain; }
108  float gain() const { return m_busGain; }
109 
110106 void reset() { m_isFirstTime = true; } // for de-zippering
111107
112108 // Assuming sourceBus has the same topology, copies sample data from each channel of sourceBus to our corresponding channel.

@@public:
116112 // Our own internal gain m_busGain is ignored.
117113 void sumFrom(const AudioBus &sourceBus);
118114
119  // Copy or sum each channel from sourceBus into our corresponding channel.
 115 // Copy each channel from sourceBus into our corresponding channel.
120116 // We scale by targetGain (and our own internal gain m_busGain), performing "de-zippering" to smoothly change from *lastMixGain to (targetGain*m_busGain).
121  // 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.
 117 // 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.
122118 // This represents the dezippering memory.
123119 void copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain);
124  void sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain);
125120
126121 // Copies the sourceBus by scaling with sample-accurate gain values.
127122 void copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues);

@@public:
137132protected:
138133 AudioBus() { };
139134
140  void processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus);
141  void processWithGainFromMonoStereo(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus);
142 
143135 size_t m_length;
144 
145136 Vector<OwnPtr<AudioChannel> > m_channels;
146 
147137 int m_layout;
148 
149138 float m_busGain;
 139 OwnPtr<AudioFloatArray> m_gainValues; // Store gain values array for dezipper frames.
150140 bool m_isFirstTime;
151141 float m_sampleRate; // 0.0 if unknown or N/A
152142};