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