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 namespace blink { 35 36 const double AudioResampler::MaxRate = 8.0; 37 38 AudioResampler::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 45 AudioResampler::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 54 void 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 71 void 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 108 void 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 116 void 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