Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / webaudio / BiquadProcessor.cpp
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 "modules/webaudio/BiquadProcessor.h"
30
31 #include "modules/webaudio/BiquadDSPKernel.h"
32
33 namespace blink {
34
35 BiquadProcessor::BiquadProcessor(AudioContext* context, float sampleRate, size_t numberOfChannels, bool autoInitialize)
36     : AudioDSPKernelProcessor(sampleRate, numberOfChannels)
37     , m_type(LowPass)
38     , m_parameter1(nullptr)
39     , m_parameter2(nullptr)
40     , m_parameter3(nullptr)
41     , m_parameter4(nullptr)
42     , m_filterCoefficientsDirty(true)
43     , m_hasSampleAccurateValues(false)
44 {
45     // Create parameters for BiquadFilterNode.
46     m_parameter1 = AudioParam::create(context, 350.0);
47     m_parameter2 = AudioParam::create(context, 1);
48     m_parameter3 = AudioParam::create(context, 0.0);
49     m_parameter4 = AudioParam::create(context, 0.0);
50
51     if (autoInitialize)
52         initialize();
53 }
54
55 BiquadProcessor::~BiquadProcessor()
56 {
57     if (isInitialized())
58         uninitialize();
59 }
60
61 void BiquadProcessor::trace(Visitor* visitor)
62 {
63     visitor->trace(m_parameter1);
64     visitor->trace(m_parameter2);
65     visitor->trace(m_parameter3);
66     visitor->trace(m_parameter4);
67     AudioDSPKernelProcessor::trace(visitor);
68 }
69
70 PassOwnPtr<AudioDSPKernel> BiquadProcessor::createKernel()
71 {
72     return adoptPtr(new BiquadDSPKernel(this));
73 }
74
75 void BiquadProcessor::checkForDirtyCoefficients()
76 {
77     // Deal with smoothing / de-zippering. Start out assuming filter parameters are not changing.
78
79     // The BiquadDSPKernel objects rely on this value to see if they need to re-compute their internal filter coefficients.
80     m_filterCoefficientsDirty = false;
81     m_hasSampleAccurateValues = false;
82
83     if (m_parameter1->hasSampleAccurateValues() || m_parameter2->hasSampleAccurateValues() || m_parameter3->hasSampleAccurateValues() || m_parameter4->hasSampleAccurateValues()) {
84         m_filterCoefficientsDirty = true;
85         m_hasSampleAccurateValues = true;
86     } else {
87         if (m_hasJustReset) {
88             // Snap to exact values first time after reset, then smooth for subsequent changes.
89             m_parameter1->resetSmoothedValue();
90             m_parameter2->resetSmoothedValue();
91             m_parameter3->resetSmoothedValue();
92             m_parameter4->resetSmoothedValue();
93             m_filterCoefficientsDirty = true;
94             m_hasJustReset = false;
95         } else {
96             // Smooth all of the filter parameters. If they haven't yet converged to their target value then mark coefficients as dirty.
97             bool isStable1 = m_parameter1->smooth();
98             bool isStable2 = m_parameter2->smooth();
99             bool isStable3 = m_parameter3->smooth();
100             bool isStable4 = m_parameter4->smooth();
101             if (!(isStable1 && isStable2 && isStable3 && isStable4))
102                 m_filterCoefficientsDirty = true;
103         }
104     }
105 }
106
107 void BiquadProcessor::process(const AudioBus* source, AudioBus* destination, size_t framesToProcess)
108 {
109     if (!isInitialized()) {
110         destination->zero();
111         return;
112     }
113
114     checkForDirtyCoefficients();
115
116     // For each channel of our input, process using the corresponding BiquadDSPKernel into the output channel.
117     for (unsigned i = 0; i < m_kernels.size(); ++i)
118         m_kernels[i]->process(source->channel(i)->data(), destination->channel(i)->mutableData(), framesToProcess);
119 }
120
121 void BiquadProcessor::setType(FilterType type)
122 {
123     if (type != m_type) {
124         m_type = type;
125         reset(); // The filter state must be reset only if the type has changed.
126     }
127 }
128
129 void BiquadProcessor::getFrequencyResponse(int nFrequencies,
130                                            const float* frequencyHz,
131                                            float* magResponse,
132                                            float* phaseResponse)
133 {
134     // Compute the frequency response on a separate temporary kernel
135     // to avoid interfering with the processing running in the audio
136     // thread on the main kernels.
137
138     OwnPtr<BiquadDSPKernel> responseKernel = adoptPtr(new BiquadDSPKernel(this));
139
140     responseKernel->getFrequencyResponse(nFrequencies, frequencyHz, magResponse, phaseResponse);
141 }
142
143 } // namespace blink
144
145 #endif // ENABLE(WEB_AUDIO)