Changeset 116596 in webkit


Ignore:
Timestamp:
May 9, 2012 7:32:46 PM (12 years ago)
Author:
commit-queue@webkit.org
Message:

Add multi-channels support for CopyWithGainFrom in AudioBus
https://bugs.webkit.org/show_bug.cgi?id=80675

Patch by Raymond Liu <raymond.liu@intel.com> on 2012-05-09
Reviewed by Chris Rogers.

  • platform/audio/AudioBus.cpp:

(WebCore):
(WebCore::AudioBus::AudioBus):
(WebCore::AudioBus::copyWithGainFrom):

  • platform/audio/AudioBus.h:

(AudioBus):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r116595 r116596  
     12012-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
    1152012-05-09  Jessie Berlin  <jberlin@apple.com>
    216
  • trunk/Source/WebCore/platform/audio/AudioBus.cpp

    r113728 r116596  
    4646
    4747using namespace VectorMath;
    48    
     48
     49const unsigned MaxBusChannels = 32;
     50
    4951AudioBus::AudioBus(unsigned numberOfChannels, size_t length, bool allocate)
    5052    : m_length(length)
     
    5355    , m_sampleRate(0)
    5456{
     57    ASSERT(numberOfChannels <= MaxBusChannels);
     58    if (numberOfChannels > MaxBusChannels)
     59        return;
     60
    5561    m_channels.reserveInitialCapacity(numberOfChannels);
    5662
     
    308314}
    309315
    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 {
     316void 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
    410347    // We don't want to suddenly change the gain from mixing one time slice to the next,
    411348    // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain.
     
    418355    m_isFirstTime = false;
    419356
    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 
    436357    const float DezipperRate = 0.005f;
    437     int framesToProcess = length();
     358    unsigned framesToProcess = length();
    438359
    439360    // If the gain is within epsilon of totalDesiredGain, we can skip dezippering.
     
    443364
    444365    // 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);
    473395    }
    474396
    475397    // Save the target gain as the starting point for next time around.
    476398    *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 -> stereo
    483     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 return
    488     if (!sumToBus && this == &sourceBus && *lastMixGain == targetGain && targetGain == 1.0)
    489         return;
    490 
    491     // Dispatch for different channel layouts
    492     switch (numberOfChannels()) {
    493     case 1: // mono
    494     case 2: // stereo
    495         processWithGainFromMonoStereo(sourceBus, lastMixGain, targetGain, sumToBus);
    496         break;
    497     case 4: // FIXME: implement quad
    498     case 5: // FIXME: implement 5.0
    499     default:
    500         ASSERT_NOT_REACHED();
    501         break;
    502     }
    503399}
    504400
     
    530426        vmul(source, 1, gainValues, 1, destination, 1, numberOfGainValues);
    531427    }
    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);
    542428}
    543429
  • trunk/Source/WebCore/platform/audio/AudioBus.h

    r113728 r116596  
    110110    void scale(float scale);
    111111
    112     // Master gain for this bus - used with sumWithGainFrom() below
    113     void setGain(float gain) { m_busGain = gain; }
    114     float gain() const { return m_busGain; }
    115 
    116112    void reset() { m_isFirstTime = true; } // for de-zippering
    117113
     
    123119    void sumFrom(const AudioBus &sourceBus);
    124120
    125     // Copy or sum each channel from sourceBus into our corresponding channel.
     121    // Copy each channel from sourceBus into our corresponding channel.
    126122    // 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.
    128124    // This represents the dezippering memory.
    129125    void copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain);
    130     void sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain);
    131126
    132127    // Copies the sourceBus by scaling with sample-accurate gain values.
     
    144139    AudioBus() { };
    145140
    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 
    149141    size_t m_length;
    150 
    151142    Vector<OwnPtr<AudioChannel> > m_channels;
    152 
    153143    int m_layout;
    154 
    155144    float m_busGain;
     145    OwnPtr<AudioFloatArray> m_dezipperGainValues;
    156146    bool m_isFirstTime;
    157147    float m_sampleRate; // 0.0 if unknown or N/A
Note: See TracChangeset for help on using the changeset viewer.