15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010, Google Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if ENABLE(WEB_AUDIO) 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 291e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/audio/AudioResampler.h" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <algorithm> 327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/MathExtras.h" 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std; 3502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const double AudioResampler::MaxRate = 8.0; 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)AudioResampler::AudioResampler() 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_rate(1.0) 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_kernels.append(adoptPtr(new AudioResamplerKernel(this))); 4481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) m_sourceBus = AudioBus::create(1, 0, false); 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)AudioResampler::AudioResampler(unsigned numberOfChannels) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_rate(1.0) 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < numberOfChannels; ++i) 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_kernels.append(adoptPtr(new AudioResamplerKernel(this))); 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) m_sourceBus = AudioBus::create(numberOfChannels, 0, false); 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void AudioResampler::configureChannels(unsigned numberOfChannels) 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned currentSize = m_kernels.size(); 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (numberOfChannels == currentSize) 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; // already setup 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // First deal with adding or removing kernels. 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (numberOfChannels > currentSize) { 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = currentSize; i < numberOfChannels; ++i) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_kernels.append(adoptPtr(new AudioResamplerKernel(this))); 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_kernels.resize(numberOfChannels); 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Reconfigure our source bus to the new channel size. 7081a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) m_sourceBus = AudioBus::create(numberOfChannels, 0, false); 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void AudioResampler::process(AudioSourceProvider* provider, AudioBus* destinationBus, size_t framesToProcess) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(provider); 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!provider) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 7802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned numberOfChannels = m_kernels.size(); 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Make sure our configuration matches the bus we're rendering to. 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool channelsMatch = (destinationBus && destinationBus->numberOfChannels() == numberOfChannels); 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(channelsMatch); 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!channelsMatch) 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Setup the source bus. 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < numberOfChannels; ++i) { 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Figure out how many frames we need to get from the provider, and a pointer to the buffer. 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t framesNeeded; 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* fillPointer = m_kernels[i]->getSourcePointer(framesToProcess, &framesNeeded); 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(fillPointer); 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!fillPointer) 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 9502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_sourceBus->setChannelMemory(i, fillPointer, framesNeeded); 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Ask the provider to supply the desired number of source frames. 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) provider->provideInput(m_sourceBus.get(), m_sourceBus->length()); 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Now that we have the source data, resample each channel into the destination bus. 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: optimize for the common stereo case where it's faster to process both left/right channels in the same inner loop. 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < numberOfChannels; ++i) { 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* destination = destinationBus->channel(i)->mutableData(); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_kernels[i]->process(destination, framesToProcess); 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void AudioResampler::setRate(double rate) 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (std::isnan(rate) || std::isinf(rate) || rate <= 0.0) 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 11402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_rate = min(AudioResampler::MaxRate, rate); 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void AudioResampler::reset() 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned numberOfChannels = m_kernels.size(); 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < numberOfChannels; ++i) 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_kernels[i]->reset(); 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // ENABLE(WEB_AUDIO) 128