Home | History | Annotate | Download | only in audio
      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  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14  *     its contributors may be used to endorse or promote products derived
     15  *     from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #ifndef AudioBus_h
     30 #define AudioBus_h
     31 
     32 #include "AudioChannel.h"
     33 #include <wtf/Noncopyable.h>
     34 #include <wtf/PassOwnPtr.h>
     35 #include <wtf/Vector.h>
     36 
     37 namespace WebCore {
     38 
     39 // An AudioBus represents a collection of one or more AudioChannels.
     40 // The data layout is "planar" as opposed to "interleaved".
     41 // An AudioBus with one channel is mono, an AudioBus with two channels is stereo, etc.
     42 class AudioBus {
     43     WTF_MAKE_NONCOPYABLE(AudioBus);
     44 public:
     45     enum {
     46         ChannelLeft = 0,
     47         ChannelRight = 1,
     48         ChannelCenter = 2, // center and mono are the same
     49         ChannelMono = 2,
     50         ChannelLFE = 3,
     51         ChannelSurroundLeft = 4,
     52         ChannelSurroundRight = 5,
     53     };
     54 
     55     enum {
     56         LayoutCanonical = 0
     57         // Can define non-standard layouts here
     58     };
     59 
     60     // allocate indicates whether or not to initially have the AudioChannels created with managed storage.
     61     // Normal usage is to pass true here, in which case the AudioChannels will memory-manage their own storage.
     62     // If allocate is false then setChannelMemory() has to be called later on for each channel before the AudioBus is useable...
     63     AudioBus(unsigned numberOfChannels, size_t length, bool allocate = true);
     64 
     65     // Tells the given channel to use an externally allocated buffer.
     66     void setChannelMemory(unsigned channelIndex, float* storage, size_t length);
     67 
     68     // Channels
     69     unsigned numberOfChannels() const { return m_channels.size(); }
     70 
     71     AudioChannel* channel(unsigned channel) { return m_channels[channel].get(); }
     72     const AudioChannel* channel(unsigned channel) const { return const_cast<AudioBus*>(this)->m_channels[channel].get(); }
     73     AudioChannel* channelByType(unsigned type);
     74 
     75     // Number of sample-frames
     76     size_t length() const { return m_length; }
     77 
     78     // Sample-rate : 0.0 if unknown or "don't care"
     79     double sampleRate() const { return m_sampleRate; }
     80     void setSampleRate(double sampleRate) { m_sampleRate = sampleRate; }
     81 
     82     // Zeroes all channels.
     83     void zero();
     84 
     85     // Returns true if the channel count and frame-size match.
     86     bool topologyMatches(const AudioBus &sourceBus) const;
     87 
     88     // Creates a new buffer from a range in the source buffer.
     89     // 0 may be returned if the range does not fit in the sourceBuffer
     90     static PassOwnPtr<AudioBus> createBufferFromRange(AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame);
     91 
     92 
     93 #if !PLATFORM(MAC)
     94     // Creates a new AudioBus by sample-rate converting sourceBus to the newSampleRate.
     95     // setSampleRate() must have been previously called on sourceBus.
     96     // Note: sample-rate conversion is already handled in the file-reading code for the mac port, so we don't need this.
     97     static PassOwnPtr<AudioBus> createBySampleRateConverting(AudioBus* sourceBus, bool mixToMono, double newSampleRate);
     98 #endif
     99 
    100     // Creates a new AudioBus by mixing all the channels down to mono.
    101     // If sourceBus is already mono, then the returned AudioBus will simply be a copy.
    102     static PassOwnPtr<AudioBus> createByMixingToMono(AudioBus* sourceBus);
    103 
    104     // Scales all samples by the same amount.
    105     void scale(double scale);
    106 
    107     // Master gain for this bus - used with sumWithGainFrom() below
    108     void setGain(double gain) { m_busGain = gain; }
    109     double gain() { return m_busGain; }
    110 
    111     void reset() { m_isFirstTime = true; } // for de-zippering
    112 
    113     // Assuming sourceBus has the same topology, copies sample data from each channel of sourceBus to our corresponding channel.
    114     void copyFrom(const AudioBus &sourceBus);
    115 
    116     // Sums the sourceBus into our bus with unity gain.
    117     // Our own internal gain m_busGain is ignored.
    118     void sumFrom(const AudioBus &sourceBus);
    119 
    120     // Copy or sum each channel from sourceBus into our corresponding channel.
    121     // We scale by targetGain (and our own internal gain m_busGain), performing "de-zippering" to smoothly change from *lastMixGain to (targetGain*m_busGain).
    122     // 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     // This represents the dezippering memory.
    124     void copyWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain);
    125     void sumWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain);
    126 
    127     // Returns maximum absolute value across all channels (useful for normalization).
    128     float maxAbsValue() const;
    129 
    130     // Makes maximum absolute value == 1.0 (if possible).
    131     void normalize();
    132 
    133     static PassOwnPtr<AudioBus> loadPlatformResource(const char* name, double sampleRate);
    134 
    135 protected:
    136     AudioBus() { };
    137 
    138     void processWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus);
    139     void processWithGainFromMonoStereo(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus);
    140 
    141     size_t m_length;
    142 
    143     Vector<OwnPtr<AudioChannel> > m_channels;
    144 
    145     int m_layout;
    146 
    147     double m_busGain;
    148     bool m_isFirstTime;
    149     double m_sampleRate; // 0.0 if unknown or N/A
    150 };
    151 
    152 } // WebCore
    153 
    154 #endif // AudioBus_h
    155