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 "platform/audio/AudioResampler.h" 30 31#include <algorithm> 32#include "wtf/MathExtras.h" 33 34namespace blink { 35 36const double AudioResampler::MaxRate = 8.0; 37 38AudioResampler::AudioResampler() 39 : m_rate(1.0) 40{ 41 m_kernels.append(adoptPtr(new AudioResamplerKernel(this))); 42 m_sourceBus = AudioBus::create(1, 0, false); 43} 44 45AudioResampler::AudioResampler(unsigned numberOfChannels) 46 : m_rate(1.0) 47{ 48 for (unsigned i = 0; i < numberOfChannels; ++i) 49 m_kernels.append(adoptPtr(new AudioResamplerKernel(this))); 50 51 m_sourceBus = AudioBus::create(numberOfChannels, 0, false); 52} 53 54void AudioResampler::configureChannels(unsigned numberOfChannels) 55{ 56 unsigned currentSize = m_kernels.size(); 57 if (numberOfChannels == currentSize) 58 return; // already setup 59 60 // First deal with adding or removing kernels. 61 if (numberOfChannels > currentSize) { 62 for (unsigned i = currentSize; i < numberOfChannels; ++i) 63 m_kernels.append(adoptPtr(new AudioResamplerKernel(this))); 64 } else 65 m_kernels.resize(numberOfChannels); 66 67 // Reconfigure our source bus to the new channel size. 68 m_sourceBus = AudioBus::create(numberOfChannels, 0, false); 69} 70 71void AudioResampler::process(AudioSourceProvider* provider, AudioBus* destinationBus, size_t framesToProcess) 72{ 73 ASSERT(provider); 74 if (!provider) 75 return; 76 77 unsigned numberOfChannels = m_kernels.size(); 78 79 // Make sure our configuration matches the bus we're rendering to. 80 bool channelsMatch = (destinationBus && destinationBus->numberOfChannels() == numberOfChannels); 81 ASSERT(channelsMatch); 82 if (!channelsMatch) 83 return; 84 85 // Setup the source bus. 86 for (unsigned i = 0; i < numberOfChannels; ++i) { 87 // Figure out how many frames we need to get from the provider, and a pointer to the buffer. 88 size_t framesNeeded; 89 float* fillPointer = m_kernels[i]->getSourcePointer(framesToProcess, &framesNeeded); 90 ASSERT(fillPointer); 91 if (!fillPointer) 92 return; 93 94 m_sourceBus->setChannelMemory(i, fillPointer, framesNeeded); 95 } 96 97 // Ask the provider to supply the desired number of source frames. 98 provider->provideInput(m_sourceBus.get(), m_sourceBus->length()); 99 100 // Now that we have the source data, resample each channel into the destination bus. 101 // FIXME: optimize for the common stereo case where it's faster to process both left/right channels in the same inner loop. 102 for (unsigned i = 0; i < numberOfChannels; ++i) { 103 float* destination = destinationBus->channel(i)->mutableData(); 104 m_kernels[i]->process(destination, framesToProcess); 105 } 106} 107 108void AudioResampler::setRate(double rate) 109{ 110 if (std::isnan(rate) || std::isinf(rate) || rate <= 0.0) 111 return; 112 113 m_rate = std::min(AudioResampler::MaxRate, rate); 114} 115 116void AudioResampler::reset() 117{ 118 unsigned numberOfChannels = m_kernels.size(); 119 for (unsigned i = 0; i < numberOfChannels; ++i) 120 m_kernels[i]->reset(); 121} 122 123} // namespace blink 124 125#endif // ENABLE(WEB_AUDIO) 126