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