Changeset 109076 in webkit


Ignore:
Timestamp:
Feb 27, 2012 10:03:41 PM (12 years ago)
Author:
commit-queue@webkit.org
Message:

Multi-Channel support in AudioBufferSourceNode
https://bugs.webkit.org/show_bug.cgi?id=79202

Patch by Wei James <james.wei@intel.com> on 2012-02-27
Reviewed by Chris Rogers.

Source/WebCore:

Test: webaudio/audiobuffersource-multi-channels.html

  • webaudio/AudioBufferSourceNode.cpp:

(WebCore::AudioBufferSourceNode::renderSilenceAndFinishIfNotLooping):
(WebCore::AudioBufferSourceNode::renderFromBuffer):
(WebCore::AudioBufferSourceNode::setBuffer):

  • webaudio/AudioBufferSourceNode.h:

(AudioBufferSourceNode):

LayoutTests:

  • webaudio/audiobuffersource-channels-expected.txt:
  • webaudio/audiobuffersource-channels.html:
  • webaudio/audiobuffersource-multi-channels-expected.wav: Added.
  • webaudio/audiobuffersource-multi-channels.html: Added.
Location:
trunk
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r109073 r109076  
     12012-02-27  Wei James  <james.wei@intel.com>
     2
     3        Multi-Channel support in AudioBufferSourceNode
     4        https://bugs.webkit.org/show_bug.cgi?id=79202
     5
     6        Reviewed by Chris Rogers.
     7
     8        * webaudio/audiobuffersource-channels-expected.txt:
     9        * webaudio/audiobuffersource-channels.html:
     10        * webaudio/audiobuffersource-multi-channels-expected.wav: Added.
     11        * webaudio/audiobuffersource-multi-channels.html: Added.
     12
    1132012-02-27  Emil A Eklund  <eae@chromium.org>
    214
  • trunk/LayoutTests/webaudio/audiobuffersource-channels-expected.txt

    r94878 r109076  
    66PASS Mono buffer can be set.
    77PASS Stereo buffer can be set.
    8 PASS 3 channel buffer is not settable.
    9 PASS 4 channel buffer is not settable.
    10 PASS 5 channel buffer is not settable.
    11 PASS 6 channel buffer is not settable.
    12 PASS 7 channel buffer is not settable.
    13 PASS 8 channel buffer is not settable.
    14 PASS 9 channel buffer is not settable.
     8PASS 3 channels buffer can be set.
     9PASS 4 channels buffer can be set.
     10PASS 5 channels buffer can be set.
     11PASS 6 channels buffer can be set.
     12PASS 7 channels buffer can be set.
     13PASS 8 channels buffer can be set.
     14PASS 9 channels buffer can be set.
    1515PASS successfullyParsed is true
    1616
  • trunk/LayoutTests/webaudio/audiobuffersource-channels.html

    r99258 r109076  
    4949    }
    5050   
    51     // Check a few buffers with more than two channels and check for failure.
    52     // (for now the implementation will only work with mono and stereo buffers)
     51    // Check buffers with more than two channels.
    5352    for (var i = 3; i < 10; ++i) {
    5453        try {
    5554            var buffer = context.createBuffer(i, 1024, context.sampleRate);
    5655            source.buffer = buffer;
    57             var message = i + " channel buffer should not be settable.";
     56            var message = i + " channels buffer can be set.";
     57            testPassed(message);
     58        } catch(e) {
     59            var message = i + " channels buffer can not be set.";
    5860            testFailed(message);
    59         } catch(e) {
    60             var message = i + " channel buffer is not settable.";
    61             testPassed(message);
    6261        }
    6362    }
  • trunk/Source/WebCore/ChangeLog

    r109074 r109076  
     12012-02-27  Wei James  <james.wei@intel.com>
     2
     3        Multi-Channel support in AudioBufferSourceNode
     4        https://bugs.webkit.org/show_bug.cgi?id=79202
     5
     6        Reviewed by Chris Rogers.
     7
     8        Test: webaudio/audiobuffersource-multi-channels.html
     9
     10        * webaudio/AudioBufferSourceNode.cpp:
     11        (WebCore::AudioBufferSourceNode::renderSilenceAndFinishIfNotLooping):
     12        (WebCore::AudioBufferSourceNode::renderFromBuffer):
     13        (WebCore::AudioBufferSourceNode::setBuffer):
     14        * webaudio/AudioBufferSourceNode.h:
     15        (AudioBufferSourceNode):
     16
    1172012-02-27  Leo Yang  <leo.yang@torchmobile.com.cn>
    218
  • trunk/Source/WebCore/webaudio/AudioBufferSourceNode.cpp

    r106162 r109076  
    127127        size_t bufferFramesToProcess = framesToProcess - quantumFrameOffset;
    128128
     129        for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i)
     130            m_destinationChannels[i] = outputBus->channel(i)->mutableData();
     131
    129132        // Render by reading directly from the buffer.
    130133        renderFromBuffer(outputBus, quantumFrameOffset, bufferFramesToProcess);
     
    145148            if (isSafe) {
    146149                for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i)
    147                     memset(outputBus->channel(i)->mutableData() + zeroStartFrame, 0, sizeof(float) * framesToZero);
     150                    memset(m_destinationChannels[i] + zeroStartFrame, 0, sizeof(float) * framesToZero);
    148151            }
    149152
     
    161164
    162165// Returns true if we're finished.
    163 bool AudioBufferSourceNode::renderSilenceAndFinishIfNotLooping(float* destinationL, float* destinationR, size_t framesToProcess)
     166bool AudioBufferSourceNode::renderSilenceAndFinishIfNotLooping(AudioBus*, unsigned index, size_t framesToProcess)
    164167{
    165168    if (!loop()) {
     
    170173            // We're not looping and we've reached the end of the sample data, but we still need to provide more output,
    171174            // so generate silence for the remaining.
    172             memset(destinationL, 0, sizeof(float) * framesToProcess);
    173 
    174             if (destinationR)
    175                 memset(destinationR, 0, sizeof(float) * framesToProcess);
     175            for (unsigned i = 0; i < numberOfChannels(); ++i)
     176                memset(m_destinationChannels[i] + index, 0, sizeof(float) * framesToProcess);
    176177        }
    177178
     
    195196    unsigned busNumberOfChannels = bus->numberOfChannels();
    196197
    197     // FIXME: we can add support for sources with more than two channels, but this is not a common case.
    198     bool channelCountGood = numberOfChannels == busNumberOfChannels && (numberOfChannels == 1 || numberOfChannels == 2);
     198    bool channelCountGood = numberOfChannels && numberOfChannels == busNumberOfChannels;
    199199    ASSERT(channelCountGood);
    200200    if (!channelCountGood)
    201201        return;
    202202
    203     // Get the destination pointers.
    204     float* destinationL = bus->channel(0)->mutableData();
    205     ASSERT(destinationL);
    206     if (!destinationL)
    207         return;
    208     float* destinationR = (numberOfChannels < 2) ? 0 : bus->channel(1)->mutableData();
    209    
    210     bool isStereo = destinationR;
    211    
    212203    // Sanity check destinationFrameOffset, numberOfFrames.
    213204    size_t destinationLength = bus->length();
     
    222213    if (!isOffsetGood)
    223214        return;
    224        
     215
    225216    // Potentially zero out initial frames leading up to the offset.
    226217    if (destinationFrameOffset) {
    227         memset(destinationL, 0, sizeof(float) * destinationFrameOffset);
    228         if (destinationR)
    229             memset(destinationR, 0, sizeof(float) * destinationFrameOffset);
     218        for (unsigned i = 0; i < numberOfChannels; ++i)
     219            memset(m_destinationChannels[i], 0, sizeof(float) * destinationFrameOffset);
    230220    }
    231221
    232222    // Offset the pointers to the correct offset frame.
    233     destinationL += destinationFrameOffset;
    234     if (destinationR)
    235         destinationR += destinationFrameOffset;
     223    unsigned writeIndex = destinationFrameOffset;
    236224
    237225    size_t bufferLength = buffer()->length();
     
    265253        m_virtualReadIndex = startFrame; // reset to start
    266254
    267     // Get pointers to the start of the sample buffer.
    268     float* sourceL = m_buffer->getChannelData(0)->data();
    269     float* sourceR = m_buffer->numberOfChannels() == 2 ? m_buffer->getChannelData(1)->data() : 0;
    270    
    271255    double pitchRate = totalPitchRate();
    272256
     
    276260    // Render loop - reading from the source buffer to the destination using linear interpolation.
    277261    int framesToProcess = numberOfFrames;
     262
     263    const float** sourceChannels = m_sourceChannels.get();
     264    float** destinationChannels = m_destinationChannels.get();
    278265
    279266    // Optimize for the very common case of playing back with pitchRate == 1.
     
    286273            framesThisTime = max(0, framesThisTime);
    287274
    288             memcpy(destinationL, sourceL + readIndex, sizeof(*sourceL) * framesThisTime);
    289             destinationL += framesThisTime;
    290             if (isStereo) {
    291                 memcpy(destinationR, sourceR + readIndex, sizeof(*sourceR) * framesThisTime);
    292                 destinationR += framesThisTime;
    293             }
    294 
     275            for (unsigned i = 0; i < numberOfChannels; ++i)
     276                memcpy(destinationChannels[i] + writeIndex, sourceChannels[i] + readIndex, sizeof(float) * framesThisTime);
     277
     278            writeIndex += framesThisTime;
    295279            readIndex += framesThisTime;
    296280            framesToProcess -= framesThisTime;
     
    299283            if (readIndex >= endFrame) {
    300284                readIndex -= deltaFrames;
    301                 if (renderSilenceAndFinishIfNotLooping(destinationL, destinationR, framesToProcess))
     285                if (renderSilenceAndFinishIfNotLooping(bus, writeIndex, framesToProcess))
    302286                    break;
    303287            }
     
    325309
    326310            // Linear interpolation.
    327             double sampleL1 = sourceL[readIndex];
    328             double sampleL2 = sourceL[readIndex2];
    329             double sampleL = (1.0 - interpolationFactor) * sampleL1 + interpolationFactor * sampleL2;
    330             *destinationL++ = narrowPrecisionToFloat(sampleL);
    331 
    332             if (isStereo) {
    333                 double sampleR1 = sourceR[readIndex];
    334                 double sampleR2 = sourceR[readIndex2];
    335                 double sampleR = (1.0 - interpolationFactor) * sampleR1 + interpolationFactor * sampleR2;
    336                 *destinationR++ = narrowPrecisionToFloat(sampleR);
     311            for (unsigned i = 0; i < numberOfChannels; ++i) {
     312                float* destination = destinationChannels[i];
     313                const float* source = sourceChannels[i];
     314
     315                double sample1 = source[readIndex];
     316                double sample2 = source[readIndex2];
     317                double sample = (1.0 - interpolationFactor) * sample1 + interpolationFactor * sample2;
     318
     319                destination[writeIndex] = narrowPrecisionToFloat(sample);
    337320            }
     321            writeIndex++;
    338322
    339323            virtualReadIndex += pitchRate;
     
    343327                virtualReadIndex -= deltaFrames;
    344328
    345                 if (renderSilenceAndFinishIfNotLooping(destinationL, destinationR, framesToProcess))
     329                if (renderSilenceAndFinishIfNotLooping(bus, writeIndex, framesToProcess))
    346330                    break;
    347331            }
     
    380364        // Do any necesssary re-configuration to the buffer's number of channels.
    381365        unsigned numberOfChannels = buffer->numberOfChannels();
    382         if (!numberOfChannels || numberOfChannels > 2) {
    383             // FIXME: implement multi-channel greater than stereo.
    384             return false;
    385         }
    386366        output(0)->setNumberOfChannels(numberOfChannels);
     367
     368        m_sourceChannels = adoptArrayPtr(new const float* [numberOfChannels]);
     369        m_destinationChannels = adoptArrayPtr(new float* [numberOfChannels]);
     370
     371        for (unsigned i = 0; i < numberOfChannels; ++i)
     372            m_sourceChannels[i] = buffer->getChannelData(i)->data();
    387373    }
    388374
  • trunk/Source/WebCore/webaudio/AudioBufferSourceNode.h

    r104993 r109076  
    3131#include "AudioPannerNode.h"
    3232#include "AudioSourceNode.h"
     33#include <wtf/OwnArrayPtr.h>
    3334#include <wtf/PassRefPtr.h>
    3435#include <wtf/RefPtr.h>
     
    8889    void renderFromBuffer(AudioBus*, unsigned destinationFrameOffset, size_t numberOfFrames);
    8990
    90     inline bool renderSilenceAndFinishIfNotLooping(float* destinationL, float* destinationR, size_t framesToProcess);
     91    // Render silence starting from "index" frame in AudioBus.
     92    inline bool renderSilenceAndFinishIfNotLooping(AudioBus*, unsigned index, size_t framesToProcess);
    9193
    9294    // m_buffer holds the sample data which this node outputs.
    9395    RefPtr<AudioBuffer> m_buffer;
     96
     97    // Pointers for the buffer and destination.
     98    OwnArrayPtr<const float*> m_sourceChannels;
     99    OwnArrayPtr<float*> m_destinationChannels;
    94100
    95101    // Used for the "gain" and "playbackRate" attributes.
Note: See TracChangeset for help on using the changeset viewer.