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

Side by Side Diff: webrtc/modules/audio_processing/three_band_filter_bank.cc

Issue 1230503003: Update a ton of audio code to use size_t more correctly and in general reduce (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Resync Created 5 years, 3 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 /* 1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 24 matching lines...) Expand all
35 35
36 #include "webrtc/modules/audio_processing/three_band_filter_bank.h" 36 #include "webrtc/modules/audio_processing/three_band_filter_bank.h"
37 37
38 #include <cmath> 38 #include <cmath>
39 39
40 #include "webrtc/base/checks.h" 40 #include "webrtc/base/checks.h"
41 41
42 namespace webrtc { 42 namespace webrtc {
43 namespace { 43 namespace {
44 44
45 const int kNumBands = 3; 45 const size_t kNumBands = 3;
46 const int kSparsity = 4; 46 const size_t kSparsity = 4;
47 47
48 // Factors to take into account when choosing |kNumCoeffs|: 48 // Factors to take into account when choosing |kNumCoeffs|:
49 // 1. Higher |kNumCoeffs|, means faster transition, which ensures less 49 // 1. Higher |kNumCoeffs|, means faster transition, which ensures less
50 // aliasing. This is especially important when there is non-linear 50 // aliasing. This is especially important when there is non-linear
51 // processing between the splitting and merging. 51 // processing between the splitting and merging.
52 // 2. The delay that this filter bank introduces is 52 // 2. The delay that this filter bank introduces is
53 // |kNumBands| * |kSparsity| * |kNumCoeffs| / 2, so it increases linearly 53 // |kNumBands| * |kSparsity| * |kNumCoeffs| / 2, so it increases linearly
54 // with |kNumCoeffs|. 54 // with |kNumCoeffs|.
55 // 3. The computation complexity also increases linearly with |kNumCoeffs|. 55 // 3. The computation complexity also increases linearly with |kNumCoeffs|.
56 const int kNumCoeffs = 4; 56 const size_t kNumCoeffs = 4;
57 57
58 // The Matlab code to generate these |kLowpassCoeffs| is: 58 // The Matlab code to generate these |kLowpassCoeffs| is:
59 // 59 //
60 // N = kNumBands * kSparsity * kNumCoeffs - 1; 60 // N = kNumBands * kSparsity * kNumCoeffs - 1;
61 // h = fir1(N, 1 / (2 * kNumBands), kaiser(N + 1, 3.5)); 61 // h = fir1(N, 1 / (2 * kNumBands), kaiser(N + 1, 3.5));
62 // reshape(h, kNumBands * kSparsity, kNumCoeffs); 62 // reshape(h, kNumBands * kSparsity, kNumCoeffs);
63 // 63 //
64 // Because the total bandwidth of the lower and higher band is double the middle 64 // Because the total bandwidth of the lower and higher band is double the middle
65 // one (because of the spectrum parity), the low-pass prototype is half the 65 // one (because of the spectrum parity), the low-pass prototype is half the
66 // bandwidth of 1 / (2 * |kNumBands|) and is then shifted with cosine modulation 66 // bandwidth of 1 / (2 * |kNumBands|) and is then shifted with cosine modulation
(...skipping 11 matching lines...) Expand all
78 {+0.00186353f, +0.01387458f, -0.01136076f, -0.00154717f}, 78 {+0.00186353f, +0.01387458f, -0.01136076f, -0.00154717f},
79 {+0.00607594f, +0.04760441f, -0.02587886f, -0.00346946f}, 79 {+0.00607594f, +0.04760441f, -0.02587886f, -0.00346946f},
80 {+0.00983212f, +0.08543175f, -0.02982767f, -0.00383509f}, 80 {+0.00983212f, +0.08543175f, -0.02982767f, -0.00383509f},
81 {+0.01157993f, +0.12154542f, -0.02536082f, -0.00304815f}, 81 {+0.01157993f, +0.12154542f, -0.02536082f, -0.00304815f},
82 {+0.00994113f, +0.14989004f, -0.01585778f, -0.00173287f}, 82 {+0.00994113f, +0.14989004f, -0.01585778f, -0.00173287f},
83 {+0.00425496f, +0.16547118f, -0.00496888f, -0.00047749f}}; 83 {+0.00425496f, +0.16547118f, -0.00496888f, -0.00047749f}};
84 84
85 // Downsamples |in| into |out|, taking one every |kNumbands| starting from 85 // Downsamples |in| into |out|, taking one every |kNumbands| starting from
86 // |offset|. |split_length| is the |out| length. |in| has to be at least 86 // |offset|. |split_length| is the |out| length. |in| has to be at least
87 // |kNumBands| * |split_length| long. 87 // |kNumBands| * |split_length| long.
88 void Downsample(const float* in, int split_length, int offset, float* out) { 88 void Downsample(const float* in,
89 for (int i = 0; i < split_length; ++i) { 89 size_t split_length,
90 size_t offset,
91 float* out) {
92 for (size_t i = 0; i < split_length; ++i) {
90 out[i] = in[kNumBands * i + offset]; 93 out[i] = in[kNumBands * i + offset];
91 } 94 }
92 } 95 }
93 96
94 // Upsamples |in| into |out|, scaling by |kNumBands| and accumulating it every 97 // Upsamples |in| into |out|, scaling by |kNumBands| and accumulating it every
95 // |kNumBands| starting from |offset|. |split_length| is the |in| length. |out| 98 // |kNumBands| starting from |offset|. |split_length| is the |in| length. |out|
96 // has to be at least |kNumBands| * |split_length| long. 99 // has to be at least |kNumBands| * |split_length| long.
97 void Upsample(const float* in, int split_length, int offset, float* out) { 100 void Upsample(const float* in, size_t split_length, size_t offset, float* out) {
98 for (int i = 0; i < split_length; ++i) { 101 for (size_t i = 0; i < split_length; ++i) {
99 out[kNumBands * i + offset] += kNumBands * in[i]; 102 out[kNumBands * i + offset] += kNumBands * in[i];
100 } 103 }
101 } 104 }
102 105
103 } // namespace 106 } // namespace
104 107
105 // Because the low-pass filter prototype has half bandwidth it is possible to 108 // Because the low-pass filter prototype has half bandwidth it is possible to
106 // use a DCT to shift it in both directions at the same time, to the center 109 // use a DCT to shift it in both directions at the same time, to the center
107 // frequencies [1 / 12, 3 / 12, 5 / 12]. 110 // frequencies [1 / 12, 3 / 12, 5 / 12].
108 ThreeBandFilterBank::ThreeBandFilterBank(int length) 111 ThreeBandFilterBank::ThreeBandFilterBank(size_t length)
109 : in_buffer_(rtc::CheckedDivExact(length, kNumBands)), 112 : in_buffer_(rtc::CheckedDivExact(length, kNumBands)),
110 out_buffer_(in_buffer_.size()) { 113 out_buffer_(in_buffer_.size()) {
111 for (int i = 0; i < kSparsity; ++i) { 114 for (size_t i = 0; i < kSparsity; ++i) {
112 for (int j = 0; j < kNumBands; ++j) { 115 for (size_t j = 0; j < kNumBands; ++j) {
113 analysis_filters_.push_back(new SparseFIRFilter( 116 analysis_filters_.push_back(new SparseFIRFilter(
114 kLowpassCoeffs[i * kNumBands + j], kNumCoeffs, kSparsity, i)); 117 kLowpassCoeffs[i * kNumBands + j], kNumCoeffs, kSparsity, i));
115 synthesis_filters_.push_back(new SparseFIRFilter( 118 synthesis_filters_.push_back(new SparseFIRFilter(
116 kLowpassCoeffs[i * kNumBands + j], kNumCoeffs, kSparsity, i)); 119 kLowpassCoeffs[i * kNumBands + j], kNumCoeffs, kSparsity, i));
117 } 120 }
118 } 121 }
119 dct_modulation_.resize(kNumBands * kSparsity); 122 dct_modulation_.resize(kNumBands * kSparsity);
120 for (size_t i = 0; i < dct_modulation_.size(); ++i) { 123 for (size_t i = 0; i < dct_modulation_.size(); ++i) {
121 dct_modulation_[i].resize(kNumBands); 124 dct_modulation_[i].resize(kNumBands);
122 for (int j = 0; j < kNumBands; ++j) { 125 for (size_t j = 0; j < kNumBands; ++j) {
123 dct_modulation_[i][j] = 126 dct_modulation_[i][j] =
124 2.f * cos(2.f * M_PI * i * (2.f * j + 1.f) / dct_modulation_.size()); 127 2.f * cos(2.f * M_PI * i * (2.f * j + 1.f) / dct_modulation_.size());
125 } 128 }
126 } 129 }
127 } 130 }
128 131
129 // The analysis can be separated in these steps: 132 // The analysis can be separated in these steps:
130 // 1. Serial to parallel downsampling by a factor of |kNumBands|. 133 // 1. Serial to parallel downsampling by a factor of |kNumBands|.
131 // 2. Filtering of |kSparsity| different delayed signals with polyphase 134 // 2. Filtering of |kSparsity| different delayed signals with polyphase
132 // decomposition of the low-pass prototype filter and upsampled by a factor 135 // decomposition of the low-pass prototype filter and upsampled by a factor
133 // of |kSparsity|. 136 // of |kSparsity|.
134 // 3. Modulating with cosines and accumulating to get the desired band. 137 // 3. Modulating with cosines and accumulating to get the desired band.
135 void ThreeBandFilterBank::Analysis(const float* in, 138 void ThreeBandFilterBank::Analysis(const float* in,
136 int length, 139 size_t length,
137 float* const* out) { 140 float* const* out) {
138 CHECK_EQ(static_cast<int>(in_buffer_.size()), 141 CHECK_EQ(in_buffer_.size(), rtc::CheckedDivExact(length, kNumBands));
139 rtc::CheckedDivExact(length, kNumBands)); 142 for (size_t i = 0; i < kNumBands; ++i) {
140 for (int i = 0; i < kNumBands; ++i) {
141 memset(out[i], 0, in_buffer_.size() * sizeof(*out[i])); 143 memset(out[i], 0, in_buffer_.size() * sizeof(*out[i]));
142 } 144 }
143 for (int i = 0; i < kNumBands; ++i) { 145 for (size_t i = 0; i < kNumBands; ++i) {
144 Downsample(in, in_buffer_.size(), kNumBands - i - 1, &in_buffer_[0]); 146 Downsample(in, in_buffer_.size(), kNumBands - i - 1, &in_buffer_[0]);
145 for (int j = 0; j < kSparsity; ++j) { 147 for (size_t j = 0; j < kSparsity; ++j) {
146 const int offset = i + j * kNumBands; 148 const size_t offset = i + j * kNumBands;
147 analysis_filters_[offset]->Filter(&in_buffer_[0], 149 analysis_filters_[offset]->Filter(&in_buffer_[0],
148 in_buffer_.size(), 150 in_buffer_.size(),
149 &out_buffer_[0]); 151 &out_buffer_[0]);
150 DownModulate(&out_buffer_[0], out_buffer_.size(), offset, out); 152 DownModulate(&out_buffer_[0], out_buffer_.size(), offset, out);
151 } 153 }
152 } 154 }
153 } 155 }
154 156
155 // The synthesis can be separated in these steps: 157 // The synthesis can be separated in these steps:
156 // 1. Modulating with cosines. 158 // 1. Modulating with cosines.
157 // 2. Filtering each one with a polyphase decomposition of the low-pass 159 // 2. Filtering each one with a polyphase decomposition of the low-pass
158 // prototype filter upsampled by a factor of |kSparsity| and accumulating 160 // prototype filter upsampled by a factor of |kSparsity| and accumulating
159 // |kSparsity| signals with different delays. 161 // |kSparsity| signals with different delays.
160 // 3. Parallel to serial upsampling by a factor of |kNumBands|. 162 // 3. Parallel to serial upsampling by a factor of |kNumBands|.
161 void ThreeBandFilterBank::Synthesis(const float* const* in, 163 void ThreeBandFilterBank::Synthesis(const float* const* in,
162 int split_length, 164 size_t split_length,
163 float* out) { 165 float* out) {
164 CHECK_EQ(static_cast<int>(in_buffer_.size()), split_length); 166 CHECK_EQ(in_buffer_.size(), split_length);
165 memset(out, 0, kNumBands * in_buffer_.size() * sizeof(*out)); 167 memset(out, 0, kNumBands * in_buffer_.size() * sizeof(*out));
166 for (int i = 0; i < kNumBands; ++i) { 168 for (size_t i = 0; i < kNumBands; ++i) {
167 for (int j = 0; j < kSparsity; ++j) { 169 for (size_t j = 0; j < kSparsity; ++j) {
168 const int offset = i + j * kNumBands; 170 const size_t offset = i + j * kNumBands;
169 UpModulate(in, in_buffer_.size(), offset, &in_buffer_[0]); 171 UpModulate(in, in_buffer_.size(), offset, &in_buffer_[0]);
170 synthesis_filters_[offset]->Filter(&in_buffer_[0], 172 synthesis_filters_[offset]->Filter(&in_buffer_[0],
171 in_buffer_.size(), 173 in_buffer_.size(),
172 &out_buffer_[0]); 174 &out_buffer_[0]);
173 Upsample(&out_buffer_[0], out_buffer_.size(), i, out); 175 Upsample(&out_buffer_[0], out_buffer_.size(), i, out);
174 } 176 }
175 } 177 }
176 } 178 }
177 179
178 180
179 // Modulates |in| by |dct_modulation_| and accumulates it in each of the 181 // Modulates |in| by |dct_modulation_| and accumulates it in each of the
180 // |kNumBands| bands of |out|. |offset| is the index in the period of the 182 // |kNumBands| bands of |out|. |offset| is the index in the period of the
181 // cosines used for modulation. |split_length| is the length of |in| and each 183 // cosines used for modulation. |split_length| is the length of |in| and each
182 // band of |out|. 184 // band of |out|.
183 void ThreeBandFilterBank::DownModulate(const float* in, 185 void ThreeBandFilterBank::DownModulate(const float* in,
184 int split_length, 186 size_t split_length,
185 int offset, 187 size_t offset,
186 float* const* out) { 188 float* const* out) {
187 for (int i = 0; i < kNumBands; ++i) { 189 for (size_t i = 0; i < kNumBands; ++i) {
188 for (int j = 0; j < split_length; ++j) { 190 for (size_t j = 0; j < split_length; ++j) {
189 out[i][j] += dct_modulation_[offset][i] * in[j]; 191 out[i][j] += dct_modulation_[offset][i] * in[j];
190 } 192 }
191 } 193 }
192 } 194 }
193 195
194 // Modulates each of the |kNumBands| bands of |in| by |dct_modulation_| and 196 // Modulates each of the |kNumBands| bands of |in| by |dct_modulation_| and
195 // accumulates them in |out|. |out| is cleared before starting to accumulate. 197 // accumulates them in |out|. |out| is cleared before starting to accumulate.
196 // |offset| is the index in the period of the cosines used for modulation. 198 // |offset| is the index in the period of the cosines used for modulation.
197 // |split_length| is the length of each band of |in| and |out|. 199 // |split_length| is the length of each band of |in| and |out|.
198 void ThreeBandFilterBank::UpModulate(const float* const* in, 200 void ThreeBandFilterBank::UpModulate(const float* const* in,
199 int split_length, 201 size_t split_length,
200 int offset, 202 size_t offset,
201 float* out) { 203 float* out) {
202 memset(out, 0, split_length * sizeof(*out)); 204 memset(out, 0, split_length * sizeof(*out));
203 for (int i = 0; i < kNumBands; ++i) { 205 for (size_t i = 0; i < kNumBands; ++i) {
204 for (int j = 0; j < split_length; ++j) { 206 for (size_t j = 0; j < split_length; ++j) {
205 out[j] += dct_modulation_[offset][i] * in[i][j]; 207 out[j] += dct_modulation_[offset][i] * in[i][j];
206 } 208 }
207 } 209 }
208 } 210 }
209 211
210 } // namespace webrtc 212 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698