1a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch/* 2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2010, Google Inc. All rights reserved. 3a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 4a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Redistribution and use in source and binary forms, with or without 5a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * modification, are permitted provided that the following conditions 6a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * are met: 7a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 1. Redistributions of source code must retain the above copyright 8a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * notice, this list of conditions and the following disclaimer. 9a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright 10a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * notice, this list of conditions and the following disclaimer in the 11a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * documentation and/or other materials provided with the distribution. 12a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 13a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch */ 24a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 25a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "config.h" 26a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 27a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#if ENABLE(WEB_AUDIO) 28a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 29a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "BiquadProcessor.h" 30a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 31a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "BiquadDSPKernel.h" 32a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 33a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochnamespace WebCore { 34a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 35a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochBiquadProcessor::BiquadProcessor(FilterType type, double sampleRate, size_t numberOfChannels, bool autoInitialize) 36a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch : AudioDSPKernelProcessor(sampleRate, numberOfChannels) 37a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch , m_type(type) 38a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch , m_parameter1(0) 39a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch , m_parameter2(0) 40a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch , m_parameter3(0) 41a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch , m_filterCoefficientsDirty(true) 42a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 43a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch double nyquist = 0.5 * this->sampleRate(); 44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 45a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch switch (type) { 46a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Highpass and lowpass share the same parameters and only differ in filter type. 47a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case LowPass2: 48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case HighPass2: 49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter1 = AudioParam::create("frequency", 350.0, 20.0, nyquist); 50a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter2 = AudioParam::create("resonance", 0.0, -20.0, 20.0); 51a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); 52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 54a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Peaking: 55a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter1 = AudioParam::create("frequency", 2500.0, 20.0, nyquist); 56a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter2 = AudioParam::create("gain", 0.0, -20.0, 20.0); 57a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter3 = AudioParam::create("Q", 0.5, 0.0, 1000.0); 58a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Allpass: 60a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter1 = AudioParam::create("frequency", 2500.0, 20.0, nyquist); 61a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter2 = AudioParam::create("Q", 0.5, 0.0, 1000.0); 62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); 63a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 64a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case LowShelf: 65a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter1 = AudioParam::create("frequency", 80.0, 20.0, nyquist); 66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter2 = AudioParam::create("gain", 0.0, 0.0, 1.0); 67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); 68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case HighShelf: 70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter1 = AudioParam::create("frequency", 10000.0, 20.0, nyquist); 71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter2 = AudioParam::create("gain", 0.0, 0.0, 1.0); 72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); 73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 74a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 75a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 76a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (autoInitialize) 77a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch initialize(); 78a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 79a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 80a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochBiquadProcessor::~BiquadProcessor() 81a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 82a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (isInitialized()) 83a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch uninitialize(); 84a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 85a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 86a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochPassOwnPtr<AudioDSPKernel> BiquadProcessor::createKernel() 87a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 88a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return adoptPtr(new BiquadDSPKernel(this)); 89a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 90a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 91a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid BiquadProcessor::process(AudioBus* source, AudioBus* destination, size_t framesToProcess) 92a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 93a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!isInitialized()) { 94a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch destination->zero(); 95a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 96a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 97a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 98a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Deal with smoothing / de-zippering. Start out assuming filter parameters are not changing. 99a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // The BiquadDSPKernel objects rely on this value to see if they need to re-compute their internal filter coefficients. 100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_filterCoefficientsDirty = false; 101a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 102a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_hasJustReset) { 103a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Snap to exact values first time after reset, then smooth for subsequent changes. 104a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter1->resetSmoothedValue(); 105a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter2->resetSmoothedValue(); 106a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_parameter3->resetSmoothedValue(); 107a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_filterCoefficientsDirty = true; 108a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_hasJustReset = false; 109a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } else { 110a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Smooth all of the filter parameters. If they haven't yet converged to their target value then mark coefficients as dirty. 111a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch bool isStable1 = m_parameter1->smooth(); 112a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch bool isStable2 = m_parameter2->smooth(); 113a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch bool isStable3 = m_parameter3->smooth(); 114a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!(isStable1 && isStable2 && isStable3)) 115a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_filterCoefficientsDirty = true; 116a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 117a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 118a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // For each channel of our input, process using the corresponding BiquadDSPKernel into the output channel. 119a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (unsigned i = 0; i < m_kernels.size(); ++i) 120a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_kernels[i]->process(source->channel(i)->data(), destination->channel(i)->data(), framesToProcess); 121a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 123a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} // namespace WebCore 124a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif // ENABLE(WEB_AUDIO) 126