diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /WebCore/platform/audio/AudioBus.cpp | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'WebCore/platform/audio/AudioBus.cpp')
-rw-r--r-- | WebCore/platform/audio/AudioBus.cpp | 365 |
1 files changed, 0 insertions, 365 deletions
diff --git a/WebCore/platform/audio/AudioBus.cpp b/WebCore/platform/audio/AudioBus.cpp deleted file mode 100644 index dd4746d..0000000 --- a/WebCore/platform/audio/AudioBus.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(WEB_AUDIO) - -#include "AudioBus.h" - -#include "VectorMath.h" -#include <algorithm> -#include <assert.h> -#include <math.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> - -namespace WebCore { - -using namespace VectorMath; - -AudioBus::AudioBus(unsigned numberOfChannels, size_t length, bool allocate) - : m_length(length) - , m_busGain(1.0) - , m_isFirstTime(true) - , m_sampleRate(0.0) -{ - m_channels.reserveInitialCapacity(numberOfChannels); - - for (unsigned i = 0; i < numberOfChannels; ++i) { - PassOwnPtr<AudioChannel> channel = allocate ? adoptPtr(new AudioChannel(length)) : adoptPtr(new AudioChannel(0, length)); - m_channels.append(channel); - } - - m_layout = LayoutCanonical; // for now this is the only layout we define -} - -void AudioBus::setChannelMemory(unsigned channelIndex, float* storage, size_t length) -{ - if (channelIndex < m_channels.size()) { - channel(channelIndex)->set(storage, length); - m_length = length; // FIXME: verify that this length matches all the other channel lengths - } -} - -void AudioBus::zero() -{ - for (unsigned i = 0; i < m_channels.size(); ++i) - m_channels[i]->zero(); -} - -AudioChannel* AudioBus::channelByType(unsigned channelType) -{ - // For now we only support canonical channel layouts... - if (m_layout != LayoutCanonical) - return 0; - - switch (numberOfChannels()) { - case 1: // mono - if (channelType == ChannelMono || channelType == ChannelLeft) - return channel(0); - return 0; - - case 2: // stereo - switch (channelType) { - case ChannelLeft: return channel(0); - case ChannelRight: return channel(1); - default: return 0; - } - - case 4: // quad - switch (channelType) { - case ChannelLeft: return channel(0); - case ChannelRight: return channel(1); - case ChannelSurroundLeft: return channel(2); - case ChannelSurroundRight: return channel(3); - default: return 0; - } - - case 5: // 5.0 - switch (channelType) { - case ChannelLeft: return channel(0); - case ChannelRight: return channel(1); - case ChannelCenter: return channel(2); - case ChannelSurroundLeft: return channel(3); - case ChannelSurroundRight: return channel(4); - default: return 0; - } - - case 6: // 5.1 - switch (channelType) { - case ChannelLeft: return channel(0); - case ChannelRight: return channel(1); - case ChannelCenter: return channel(2); - case ChannelLFE: return channel(3); - case ChannelSurroundLeft: return channel(4); - case ChannelSurroundRight: return channel(5); - default: return 0; - } - } - - ASSERT_NOT_REACHED(); - return 0; -} - -// Returns true if the channel count and frame-size match. -bool AudioBus::topologyMatches(const AudioBus& bus) const -{ - if (numberOfChannels() != bus.numberOfChannels()) - return false; // channel mismatch - - // Make sure source bus has enough frames. - if (length() > bus.length()) - return false; // frame-size mismatch - - return true; -} - -PassOwnPtr<AudioBus> AudioBus::createBufferFromRange(AudioBus* sourceBuffer, unsigned startFrame, unsigned endFrame) -{ - size_t numberOfSourceFrames = sourceBuffer->length(); - unsigned numberOfChannels = sourceBuffer->numberOfChannels(); - - // Sanity checking - bool isRangeSafe = startFrame < endFrame && endFrame <= numberOfSourceFrames; - ASSERT(isRangeSafe); - if (!isRangeSafe) - return 0; - - size_t rangeLength = endFrame - startFrame; - - OwnPtr<AudioBus> audioBus = adoptPtr(new AudioBus(numberOfChannels, rangeLength)); - audioBus->setSampleRate(sourceBuffer->sampleRate()); - - for (unsigned i = 0; i < numberOfChannels; ++i) - audioBus->channel(i)->copyFromRange(sourceBuffer->channel(i), startFrame, endFrame); - - return audioBus.release(); -} - -float AudioBus::maxAbsValue() const -{ - float max = 0.0f; - for (unsigned i = 0; i < numberOfChannels(); ++i) { - const AudioChannel* channel = this->channel(i); - max = std::max(max, channel->maxAbsValue()); - } - - return max; -} - -void AudioBus::normalize() -{ - float max = maxAbsValue(); - if (max) - scale(1.0f / max); -} - -void AudioBus::scale(double scale) -{ - for (unsigned i = 0; i < numberOfChannels(); ++i) - channel(i)->scale(scale); -} - -// Just copies the samples from the source bus to this one. -// This is just a simple copy if the number of channels match, otherwise a mixup or mixdown is done. -// For now, we just support a mixup from mono -> stereo. -void AudioBus::copyFrom(const AudioBus& sourceBus) -{ - if (&sourceBus == this) - return; - - if (numberOfChannels() == sourceBus.numberOfChannels()) { - for (unsigned i = 0; i < numberOfChannels(); ++i) - channel(i)->copyFrom(sourceBus.channel(i)); - } else if (numberOfChannels() == 2 && sourceBus.numberOfChannels() == 1) { - // Handle mono -> stereo case (for now simply copy mono channel into both left and right) - // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center... - const AudioChannel* sourceChannel = sourceBus.channel(0); - channel(0)->copyFrom(sourceChannel); - channel(1)->copyFrom(sourceChannel); - } else { - // Case not handled - ASSERT_NOT_REACHED(); - } -} - -void AudioBus::sumFrom(const AudioBus &sourceBus) -{ - if (numberOfChannels() == sourceBus.numberOfChannels()) { - for (unsigned i = 0; i < numberOfChannels(); ++i) - channel(i)->sumFrom(sourceBus.channel(i)); - } else if (numberOfChannels() == 2 && sourceBus.numberOfChannels() == 1) { - // Handle mono -> stereo case (for now simply sum mono channel into both left and right) - // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center... - const AudioChannel* sourceChannel = sourceBus.channel(0); - channel(0)->sumFrom(sourceChannel); - channel(1)->sumFrom(sourceChannel); - } else { - // Case not handled - ASSERT_NOT_REACHED(); - } -} - -void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus) -{ - // We don't want to suddenly change the gain from mixing one time slice to the next, - // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain. - - // FIXME: optimize this method (SSE, etc.) - // FIXME: Need fast path here when gain has converged on targetGain. In this case, de-zippering is no longer needed. - // FIXME: Need fast path when this==sourceBus && lastMixGain==targetGain==1.0 && sumToBus==false (this is a NOP) - - // Take master bus gain into account as well as the targetGain. - double totalDesiredGain = m_busGain * targetGain; - - // First time, snap directly to totalDesiredGain. - double gain = m_isFirstTime ? totalDesiredGain : *lastMixGain; - m_isFirstTime = false; - - int numberOfSourceChannels = sourceBus.numberOfChannels(); - int numberOfDestinationChannels = numberOfChannels(); - - AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus); - const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data(); - const float* sourceR = numberOfSourceChannels > 1 ? sourceBusSafe.channelByType(ChannelRight)->data() : 0; - - float* destinationL = channelByType(ChannelLeft)->data(); - float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->data() : 0; - - const double DezipperRate = 0.005; - int framesToProcess = length(); - - if (sumToBus) { - // Sum to our bus - if (sourceR && destinationR) { - // Stereo - while (framesToProcess--) { - float sampleL = *sourceL++; - float sampleR = *sourceR++; - *destinationL++ += static_cast<float>(gain * sampleL); - *destinationR++ += static_cast<float>(gain * sampleR); - - // Slowly change gain to desired gain. - gain += (totalDesiredGain - gain) * DezipperRate; - } - } else if (destinationR) { - // Mono -> stereo (mix equally into L and R) - // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center... - while (framesToProcess--) { - float sample = *sourceL++; - *destinationL++ += static_cast<float>(gain * sample); - *destinationR++ += static_cast<float>(gain * sample); - - // Slowly change gain to desired gain. - gain += (totalDesiredGain - gain) * DezipperRate; - } - } else { - // Mono - while (framesToProcess--) { - float sampleL = *sourceL++; - *destinationL++ += static_cast<float>(gain * sampleL); - - // Slowly change gain to desired gain. - gain += (totalDesiredGain - gain) * DezipperRate; - } - } - } else { - // Process directly (without summing) to our bus - if (sourceR && destinationR) { - // Stereo - while (framesToProcess--) { - float sampleL = *sourceL++; - float sampleR = *sourceR++; - *destinationL++ = static_cast<float>(gain * sampleL); - *destinationR++ = static_cast<float>(gain * sampleR); - - // Slowly change gain to desired gain. - gain += (totalDesiredGain - gain) * DezipperRate; - } - } else if (destinationR) { - // Mono -> stereo (mix equally into L and R) - // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center... - while (framesToProcess--) { - float sample = *sourceL++; - *destinationL++ = static_cast<float>(gain * sample); - *destinationR++ = static_cast<float>(gain * sample); - - // Slowly change gain to desired gain. - gain += (totalDesiredGain - gain) * DezipperRate; - } - } else { - // Mono - while (framesToProcess--) { - float sampleL = *sourceL++; - *destinationL++ = static_cast<float>(gain * sampleL); - - // Slowly change gain to desired gain. - gain += (totalDesiredGain - gain) * DezipperRate; - } - } - } - - // Save the target gain as the starting point for next time around. - *lastMixGain = gain; -} - -void AudioBus::processWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus) -{ - // Make sure we're summing from same type of bus. - // We *are* able to sum from mono -> stereo - if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) - return; - - // Dispatch for different channel layouts - switch (numberOfChannels()) { - case 1: // mono - case 2: // stereo - processWithGainFromMonoStereo(sourceBus, lastMixGain, targetGain, sumToBus); - break; - case 4: // FIXME: implement quad - case 5: // FIXME: implement 5.0 - default: - ASSERT_NOT_REACHED(); - break; - } -} - -void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain) -{ - processWithGainFrom(sourceBus, lastMixGain, targetGain, false); -} - -void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain) -{ - processWithGainFrom(sourceBus, lastMixGain, targetGain, true); -} - -} // WebCore - -#endif // ENABLE(WEB_AUDIO) |