Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(261)

Side by Side Diff: third_party/WebKit/Source/platform/audio/IIRFilter.cpp

Issue 2384073002: reflow comments in platform/audio (Closed)
Patch Set: comments (heh!) Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "platform/audio/IIRFilter.h" 5 #include "platform/audio/IIRFilter.h"
6 6
7 #include "wtf/MathExtras.h" 7 #include "wtf/MathExtras.h"
8 #include <complex> 8 #include <complex>
9 9
10 namespace blink { 10 namespace blink {
11 11
12 // The length of the memory buffers for the IIR filter. This MUST be a power of two and must be 12 // The length of the memory buffers for the IIR filter. This MUST be a power of
13 // greater than the possible length of the filter coefficients. 13 // two and must be greater than the possible length of the filter coefficients.
14 const int kBufferLength = 32; 14 const int kBufferLength = 32;
15 static_assert(kBufferLength >= IIRFilter::kMaxOrder + 1, 15 static_assert(kBufferLength >= IIRFilter::kMaxOrder + 1,
16 "Internal IIR buffer length must be greater than maximum IIR " 16 "Internal IIR buffer length must be greater than maximum IIR "
17 "Filter order."); 17 "Filter order.");
18 18
19 IIRFilter::IIRFilter(const AudioDoubleArray* feedforward, 19 IIRFilter::IIRFilter(const AudioDoubleArray* feedforward,
20 const AudioDoubleArray* feedback) 20 const AudioDoubleArray* feedback)
21 : m_bufferIndex(0), m_feedback(feedback), m_feedforward(feedforward) { 21 : m_bufferIndex(0), m_feedback(feedback), m_feedforward(feedforward) {
22 // These are guaranteed to be zero-initialized. 22 // These are guaranteed to be zero-initialized.
23 m_xBuffer.allocate(kBufferLength); 23 m_xBuffer.allocate(kBufferLength);
24 m_yBuffer.allocate(kBufferLength); 24 m_yBuffer.allocate(kBufferLength);
25 } 25 }
26 26
27 IIRFilter::~IIRFilter() {} 27 IIRFilter::~IIRFilter() {}
28 28
29 void IIRFilter::reset() { 29 void IIRFilter::reset() {
30 m_xBuffer.zero(); 30 m_xBuffer.zero();
31 m_yBuffer.zero(); 31 m_yBuffer.zero();
32 } 32 }
33 33
34 static std::complex<double> evaluatePolynomial(const double* coef, 34 static std::complex<double> evaluatePolynomial(const double* coef,
35 std::complex<double> z, 35 std::complex<double> z,
36 int order) { 36 int order) {
37 // Use Horner's method to evaluate the polynomial P(z) = sum(coef[k]*z^k, k, 0 , order); 37 // Use Horner's method to evaluate the polynomial P(z) = sum(coef[k]*z^k, k,
38 // 0, order);
38 std::complex<double> result = 0; 39 std::complex<double> result = 0;
39 40
40 for (int k = order; k >= 0; --k) 41 for (int k = order; k >= 0; --k)
41 result = result * z + std::complex<double>(coef[k]); 42 result = result * z + std::complex<double>(coef[k]);
42 43
43 return result; 44 return result;
44 } 45 }
45 46
46 void IIRFilter::process(const float* sourceP, 47 void IIRFilter::process(const float* sourceP,
47 float* destP, 48 float* destP,
48 size_t framesToProcess) { 49 size_t framesToProcess) {
49 // Compute 50 // Compute
50 // 51 //
51 // y[n] = sum(b[k] * x[n - k], k = 0, M) - sum(a[k] * y[n - k], k = 1, N) 52 // y[n] = sum(b[k] * x[n - k], k = 0, M) - sum(a[k] * y[n - k], k = 1, N)
52 // 53 //
53 // where b[k] are the feedforward coefficients and a[k] are the feedback coeff icients of the 54 // where b[k] are the feedforward coefficients and a[k] are the feedback
54 // filter. 55 // coefficients of the filter.
55 56
56 // This is a Direct Form I implementation of an IIR Filter. Should we conside r doing a 57 // This is a Direct Form I implementation of an IIR Filter. Should we
57 // different implementation such as Transposed Direct Form II? 58 // consider doing a different implementation such as Transposed Direct Form
59 // II?
58 const double* feedback = m_feedback->data(); 60 const double* feedback = m_feedback->data();
59 const double* feedforward = m_feedforward->data(); 61 const double* feedforward = m_feedforward->data();
60 62
61 ASSERT(feedback); 63 ASSERT(feedback);
62 ASSERT(feedforward); 64 ASSERT(feedforward);
63 65
64 // Sanity check to see if the feedback coefficients have been scaled appropria tely. It must 66 // Sanity check to see if the feedback coefficients have been scaled
65 // be EXACTLY 1! 67 // appropriately. It must be EXACTLY 1!
66 ASSERT(feedback[0] == 1); 68 ASSERT(feedback[0] == 1);
67 69
68 int feedbackLength = m_feedback->size(); 70 int feedbackLength = m_feedback->size();
69 int feedforwardLength = m_feedforward->size(); 71 int feedforwardLength = m_feedforward->size();
70 int minLength = std::min(feedbackLength, feedforwardLength); 72 int minLength = std::min(feedbackLength, feedforwardLength);
71 73
72 double* xBuffer = m_xBuffer.data(); 74 double* xBuffer = m_xBuffer.data();
73 double* yBuffer = m_yBuffer.data(); 75 double* yBuffer = m_yBuffer.data();
74 76
75 for (size_t n = 0; n < framesToProcess; ++n) { 77 for (size_t n = 0; n < framesToProcess; ++n) {
76 // To help minimize roundoff, we compute using double's, even though the fil ter coefficients 78 // To help minimize roundoff, we compute using double's, even though the
77 // only have single precision values. 79 // filter coefficients only have single precision values.
78 double yn = feedforward[0] * sourceP[n]; 80 double yn = feedforward[0] * sourceP[n];
79 81
80 // Run both the feedforward and feedback terms together, when possible. 82 // Run both the feedforward and feedback terms together, when possible.
81 for (int k = 1; k < minLength; ++k) { 83 for (int k = 1; k < minLength; ++k) {
82 int n = (m_bufferIndex - k) & (kBufferLength - 1); 84 int n = (m_bufferIndex - k) & (kBufferLength - 1);
83 yn += feedforward[k] * xBuffer[n]; 85 yn += feedforward[k] * xBuffer[n];
84 yn -= feedback[k] * yBuffer[n]; 86 yn -= feedback[k] * yBuffer[n];
85 } 87 }
86 88
87 // Handle any remaining feedforward or feedback terms. 89 // Handle any remaining feedforward or feedback terms.
88 for (int k = minLength; k < feedforwardLength; ++k) 90 for (int k = minLength; k < feedforwardLength; ++k)
89 yn += feedforward[k] * xBuffer[(m_bufferIndex - k) & (kBufferLength - 1)]; 91 yn += feedforward[k] * xBuffer[(m_bufferIndex - k) & (kBufferLength - 1)];
90 92
91 for (int k = minLength; k < feedbackLength; ++k) 93 for (int k = minLength; k < feedbackLength; ++k)
92 yn -= feedback[k] * yBuffer[(m_bufferIndex - k) & (kBufferLength - 1)]; 94 yn -= feedback[k] * yBuffer[(m_bufferIndex - k) & (kBufferLength - 1)];
93 95
94 // Save the current input and output values in the memory buffers for the ne xt output. 96 // Save the current input and output values in the memory buffers for the
97 // next output.
95 m_xBuffer[m_bufferIndex] = sourceP[n]; 98 m_xBuffer[m_bufferIndex] = sourceP[n];
96 m_yBuffer[m_bufferIndex] = yn; 99 m_yBuffer[m_bufferIndex] = yn;
97 100
98 m_bufferIndex = (m_bufferIndex + 1) & (kBufferLength - 1); 101 m_bufferIndex = (m_bufferIndex + 1) & (kBufferLength - 1);
99 102
100 destP[n] = yn; 103 destP[n] = yn;
101 } 104 }
102 } 105 }
103 106
104 void IIRFilter::getFrequencyResponse(int nFrequencies, 107 void IIRFilter::getFrequencyResponse(int nFrequencies,
105 const float* frequency, 108 const float* frequency,
106 float* magResponse, 109 float* magResponse,
107 float* phaseResponse) { 110 float* phaseResponse) {
108 // Evaluate the z-transform of the filter at the given normalized frequencies from 0 to 1. (One 111 // Evaluate the z-transform of the filter at the given normalized frequencies
109 // corresponds to the Nyquist frequency.) 112 // from 0 to 1. (One corresponds to the Nyquist frequency.)
110 // 113 //
111 // The z-tranform of the filter is 114 // The z-tranform of the filter is
112 // 115 //
113 // H(z) = sum(b[k]*z^(-k), k, 0, M) / sum(a[k]*z^(-k), k, 0, N); 116 // H(z) = sum(b[k]*z^(-k), k, 0, M) / sum(a[k]*z^(-k), k, 0, N);
114 // 117 //
115 // The desired frequency response is H(exp(j*omega)), where omega is in [0, 1) . 118 // The desired frequency response is H(exp(j*omega)), where omega is in [0,
119 // 1).
116 // 120 //
117 // Let P(x) = sum(c[k]*x^k, k, 0, P) be a polynomial of order P. Then each of the sums in H(z) 121 // Let P(x) = sum(c[k]*x^k, k, 0, P) be a polynomial of order P. Then each of
118 // is equivalent to evaluating a polynomial at the point 1/z. 122 // the sums in H(z) is equivalent to evaluating a polynomial at the point
123 // 1/z.
119 124
120 for (int k = 0; k < nFrequencies; ++k) { 125 for (int k = 0; k < nFrequencies; ++k) {
121 // zRecip = 1/z = exp(-j*frequency) 126 // zRecip = 1/z = exp(-j*frequency)
122 double omega = -piDouble * frequency[k]; 127 double omega = -piDouble * frequency[k];
123 std::complex<double> zRecip = std::complex<double>(cos(omega), sin(omega)); 128 std::complex<double> zRecip = std::complex<double>(cos(omega), sin(omega));
124 129
125 std::complex<double> numerator = evaluatePolynomial( 130 std::complex<double> numerator = evaluatePolynomial(
126 m_feedforward->data(), zRecip, m_feedforward->size() - 1); 131 m_feedforward->data(), zRecip, m_feedforward->size() - 1);
127 std::complex<double> denominator = 132 std::complex<double> denominator =
128 evaluatePolynomial(m_feedback->data(), zRecip, m_feedback->size() - 1); 133 evaluatePolynomial(m_feedback->data(), zRecip, m_feedback->size() - 1);
129 std::complex<double> response = numerator / denominator; 134 std::complex<double> response = numerator / denominator;
130 magResponse[k] = static_cast<float>(abs(response)); 135 magResponse[k] = static_cast<float>(abs(response));
131 phaseResponse[k] = 136 phaseResponse[k] =
132 static_cast<float>(atan2(imag(response), real(response))); 137 static_cast<float>(atan2(imag(response), real(response)));
133 } 138 }
134 } 139 }
135 140
136 } // namespace blink 141 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/audio/IIRFilter.h ('k') | third_party/WebKit/Source/platform/audio/MultiChannelResampler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698