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 "BiquadProcessor.h" 30 31#include "BiquadDSPKernel.h" 32 33namespace WebCore { 34 35BiquadProcessor::BiquadProcessor(FilterType type, double sampleRate, size_t numberOfChannels, bool autoInitialize) 36 : AudioDSPKernelProcessor(sampleRate, numberOfChannels) 37 , m_type(type) 38 , m_parameter1(0) 39 , m_parameter2(0) 40 , m_parameter3(0) 41 , m_filterCoefficientsDirty(true) 42{ 43 double nyquist = 0.5 * this->sampleRate(); 44 45 switch (type) { 46 // Highpass and lowpass share the same parameters and only differ in filter type. 47 case LowPass2: 48 case HighPass2: 49 m_parameter1 = AudioParam::create("frequency", 350.0, 20.0, nyquist); 50 m_parameter2 = AudioParam::create("resonance", 0.0, -20.0, 20.0); 51 m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); 52 break; 53 54 case Peaking: 55 m_parameter1 = AudioParam::create("frequency", 2500.0, 20.0, nyquist); 56 m_parameter2 = AudioParam::create("gain", 0.0, -20.0, 20.0); 57 m_parameter3 = AudioParam::create("Q", 0.5, 0.0, 1000.0); 58 break; 59 case Allpass: 60 m_parameter1 = AudioParam::create("frequency", 2500.0, 20.0, nyquist); 61 m_parameter2 = AudioParam::create("Q", 0.5, 0.0, 1000.0); 62 m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); 63 break; 64 case LowShelf: 65 m_parameter1 = AudioParam::create("frequency", 80.0, 20.0, nyquist); 66 m_parameter2 = AudioParam::create("gain", 0.0, 0.0, 1.0); 67 m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); 68 break; 69 case HighShelf: 70 m_parameter1 = AudioParam::create("frequency", 10000.0, 20.0, nyquist); 71 m_parameter2 = AudioParam::create("gain", 0.0, 0.0, 1.0); 72 m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); 73 break; 74 } 75 76 if (autoInitialize) 77 initialize(); 78} 79 80BiquadProcessor::~BiquadProcessor() 81{ 82 if (isInitialized()) 83 uninitialize(); 84} 85 86PassOwnPtr<AudioDSPKernel> BiquadProcessor::createKernel() 87{ 88 return adoptPtr(new BiquadDSPKernel(this)); 89} 90 91void BiquadProcessor::process(AudioBus* source, AudioBus* destination, size_t framesToProcess) 92{ 93 if (!isInitialized()) { 94 destination->zero(); 95 return; 96 } 97 98 // Deal with smoothing / de-zippering. Start out assuming filter parameters are not changing. 99 // The BiquadDSPKernel objects rely on this value to see if they need to re-compute their internal filter coefficients. 100 m_filterCoefficientsDirty = false; 101 102 if (m_hasJustReset) { 103 // Snap to exact values first time after reset, then smooth for subsequent changes. 104 m_parameter1->resetSmoothedValue(); 105 m_parameter2->resetSmoothedValue(); 106 m_parameter3->resetSmoothedValue(); 107 m_filterCoefficientsDirty = true; 108 m_hasJustReset = false; 109 } else { 110 // Smooth all of the filter parameters. If they haven't yet converged to their target value then mark coefficients as dirty. 111 bool isStable1 = m_parameter1->smooth(); 112 bool isStable2 = m_parameter2->smooth(); 113 bool isStable3 = m_parameter3->smooth(); 114 if (!(isStable1 && isStable2 && isStable3)) 115 m_filterCoefficientsDirty = true; 116 } 117 118 // For each channel of our input, process using the corresponding BiquadDSPKernel into the output channel. 119 for (unsigned i = 0; i < m_kernels.size(); ++i) 120 m_kernels[i]->process(source->channel(i)->data(), destination->channel(i)->data(), framesToProcess); 121} 122 123} // namespace WebCore 124 125#endif // ENABLE(WEB_AUDIO) 126