Home | History | Annotate | Download | only in webaudio
      1 /*
      2  * Copyright (C) 2010, Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1.  Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2.  Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23  */
     24 
     25 #include "config.h"
     26 
     27 #if ENABLE(WEB_AUDIO)
     28 
     29 #include "modules/webaudio/AudioBasicProcessorNode.h"
     30 
     31 #include "core/platform/audio/AudioBus.h"
     32 #include "core/platform/audio/AudioProcessor.h"
     33 #include "modules/webaudio/AudioContext.h"
     34 #include "modules/webaudio/AudioNodeInput.h"
     35 #include "modules/webaudio/AudioNodeOutput.h"
     36 
     37 namespace WebCore {
     38 
     39 AudioBasicProcessorNode::AudioBasicProcessorNode(AudioContext* context, float sampleRate)
     40     : AudioNode(context, sampleRate)
     41 {
     42     addInput(adoptPtr(new AudioNodeInput(this)));
     43     addOutput(adoptPtr(new AudioNodeOutput(this, 1)));
     44 
     45     // The subclass must create m_processor.
     46 }
     47 
     48 void AudioBasicProcessorNode::initialize()
     49 {
     50     if (isInitialized())
     51         return;
     52 
     53     ASSERT(processor());
     54     processor()->initialize();
     55 
     56     AudioNode::initialize();
     57 }
     58 
     59 void AudioBasicProcessorNode::uninitialize()
     60 {
     61     if (!isInitialized())
     62         return;
     63 
     64     ASSERT(processor());
     65     processor()->uninitialize();
     66 
     67     AudioNode::uninitialize();
     68 }
     69 
     70 void AudioBasicProcessorNode::process(size_t framesToProcess)
     71 {
     72     AudioBus* destinationBus = output(0)->bus();
     73 
     74     if (!isInitialized() || !processor() || processor()->numberOfChannels() != numberOfChannels())
     75         destinationBus->zero();
     76     else {
     77         AudioBus* sourceBus = input(0)->bus();
     78 
     79         // FIXME: if we take "tail time" into account, then we can avoid calling processor()->process() once the tail dies down.
     80         if (!input(0)->isConnected())
     81             sourceBus->zero();
     82 
     83         processor()->process(sourceBus, destinationBus, framesToProcess);
     84     }
     85 }
     86 
     87 // Nice optimization in the very common case allowing for "in-place" processing
     88 void AudioBasicProcessorNode::pullInputs(size_t framesToProcess)
     89 {
     90     // Render input stream - suggest to the input to render directly into output bus for in-place processing in process() if possible.
     91     input(0)->pull(output(0)->bus(), framesToProcess);
     92 }
     93 
     94 void AudioBasicProcessorNode::reset()
     95 {
     96     if (processor())
     97         processor()->reset();
     98 }
     99 
    100 // As soon as we know the channel count of our input, we can lazily initialize.
    101 // Sometimes this may be called more than once with different channel counts, in which case we must safely
    102 // uninitialize and then re-initialize with the new channel count.
    103 void AudioBasicProcessorNode::checkNumberOfChannelsForInput(AudioNodeInput* input)
    104 {
    105     ASSERT(context()->isAudioThread() && context()->isGraphOwner());
    106 
    107     ASSERT(input == this->input(0));
    108     if (input != this->input(0))
    109         return;
    110 
    111     ASSERT(processor());
    112     if (!processor())
    113         return;
    114 
    115     unsigned numberOfChannels = input->numberOfChannels();
    116 
    117     if (isInitialized() && numberOfChannels != output(0)->numberOfChannels()) {
    118         // We're already initialized but the channel count has changed.
    119         uninitialize();
    120     }
    121 
    122     if (!isInitialized()) {
    123         // This will propagate the channel count to any nodes connected further down the chain...
    124         output(0)->setNumberOfChannels(numberOfChannels);
    125 
    126         // Re-initialize the processor with the new channel count.
    127         processor()->setNumberOfChannels(numberOfChannels);
    128         initialize();
    129     }
    130 
    131     AudioNode::checkNumberOfChannelsForInput(input);
    132 }
    133 
    134 unsigned AudioBasicProcessorNode::numberOfChannels()
    135 {
    136     return output(0)->numberOfChannels();
    137 }
    138 
    139 double AudioBasicProcessorNode::tailTime() const
    140 {
    141     return m_processor->tailTime();
    142 }
    143 
    144 double AudioBasicProcessorNode::latencyTime() const
    145 {
    146     return m_processor->latencyTime();
    147 }
    148 
    149 } // namespace WebCore
    150 
    151 #endif // ENABLE(WEB_AUDIO)
    152