OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 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 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 << " dBFS" | 172 << " dBFS" |
173 << "}"; | 173 << "}"; |
174 | 174 |
175 Reset(); | 175 Reset(); |
176 } | 176 } |
177 } | 177 } |
178 | 178 |
179 LevelController::LevelController() | 179 LevelController::LevelController() |
180 : data_dumper_(new ApmDataDumper(instance_count_)), | 180 : data_dumper_(new ApmDataDumper(instance_count_)), |
181 gain_applier_(data_dumper_.get()), | 181 gain_applier_(data_dumper_.get()), |
182 signal_classifier_(data_dumper_.get()) { | 182 signal_classifier_(data_dumper_.get()), |
| 183 peak_level_estimator_(kTargetLcPeakLeveldBFS) { |
183 Initialize(AudioProcessing::kSampleRate48kHz); | 184 Initialize(AudioProcessing::kSampleRate48kHz); |
184 ++instance_count_; | 185 ++instance_count_; |
185 } | 186 } |
186 | 187 |
187 LevelController::~LevelController() {} | 188 LevelController::~LevelController() {} |
188 | 189 |
189 void LevelController::Initialize(int sample_rate_hz) { | 190 void LevelController::Initialize(int sample_rate_hz) { |
190 RTC_DCHECK(sample_rate_hz == AudioProcessing::kSampleRate8kHz || | 191 RTC_DCHECK(sample_rate_hz == AudioProcessing::kSampleRate8kHz || |
191 sample_rate_hz == AudioProcessing::kSampleRate16kHz || | 192 sample_rate_hz == AudioProcessing::kSampleRate16kHz || |
192 sample_rate_hz == AudioProcessing::kSampleRate32kHz || | 193 sample_rate_hz == AudioProcessing::kSampleRate32kHz || |
193 sample_rate_hz == AudioProcessing::kSampleRate48kHz); | 194 sample_rate_hz == AudioProcessing::kSampleRate48kHz); |
194 data_dumper_->InitiateNewSetOfRecordings(); | 195 data_dumper_->InitiateNewSetOfRecordings(); |
195 gain_selector_.Initialize(sample_rate_hz); | 196 gain_selector_.Initialize(sample_rate_hz); |
196 gain_applier_.Initialize(sample_rate_hz); | 197 gain_applier_.Initialize(sample_rate_hz); |
197 signal_classifier_.Initialize(sample_rate_hz); | 198 signal_classifier_.Initialize(sample_rate_hz); |
198 noise_level_estimator_.Initialize(sample_rate_hz); | 199 noise_level_estimator_.Initialize(sample_rate_hz); |
199 peak_level_estimator_.Initialize(); | 200 peak_level_estimator_.Initialize(config_.initial_peak_level_dbfs); |
200 saturating_gain_estimator_.Initialize(); | 201 saturating_gain_estimator_.Initialize(); |
201 metrics_.Initialize(sample_rate_hz); | 202 metrics_.Initialize(sample_rate_hz); |
202 | 203 |
203 last_gain_ = 1.0f; | 204 last_gain_ = 1.0f; |
204 sample_rate_hz_ = rtc::Optional<int>(sample_rate_hz); | 205 sample_rate_hz_ = rtc::Optional<int>(sample_rate_hz); |
205 dc_forgetting_factor_ = 0.01f * sample_rate_hz / 48000.f; | 206 dc_forgetting_factor_ = 0.01f * sample_rate_hz / 48000.f; |
206 std::fill(dc_level_, dc_level_ + arraysize(dc_level_), 0.f); | 207 std::fill(dc_level_, dc_level_ + arraysize(dc_level_), 0.f); |
207 } | 208 } |
208 | 209 |
209 void LevelController::Process(AudioBuffer* audio) { | 210 void LevelController::Process(AudioBuffer* audio) { |
(...skipping 21 matching lines...) Expand all Loading... |
231 noise_level_estimator_.Analyze(signal_type, FrameEnergy(*audio)); | 232 noise_level_estimator_.Analyze(signal_type, FrameEnergy(*audio)); |
232 | 233 |
233 // Estimate the overall signal peak level. | 234 // Estimate the overall signal peak level. |
234 const float frame_peak_level = PeakLevel(*audio); | 235 const float frame_peak_level = PeakLevel(*audio); |
235 const float long_term_peak_level = | 236 const float long_term_peak_level = |
236 peak_level_estimator_.Analyze(signal_type, frame_peak_level); | 237 peak_level_estimator_.Analyze(signal_type, frame_peak_level); |
237 | 238 |
238 float saturating_gain = saturating_gain_estimator_.GetGain(); | 239 float saturating_gain = saturating_gain_estimator_.GetGain(); |
239 | 240 |
240 // Compute the new gain to apply. | 241 // Compute the new gain to apply. |
241 last_gain_ = gain_selector_.GetNewGain(long_term_peak_level, noise_energy, | 242 last_gain_ = |
242 saturating_gain, signal_type); | 243 gain_selector_.GetNewGain(long_term_peak_level, noise_energy, |
| 244 saturating_gain, gain_jumpstart_, signal_type); |
| 245 |
| 246 // Unflag the jumpstart of the gain as it should only happen once. |
| 247 gain_jumpstart_ = false; |
243 | 248 |
244 // Apply the gain to the signal. | 249 // Apply the gain to the signal. |
245 int num_saturations = gain_applier_.Process(last_gain_, audio); | 250 int num_saturations = gain_applier_.Process(last_gain_, audio); |
246 | 251 |
247 // Estimate the gain that saturates the overall signal. | 252 // Estimate the gain that saturates the overall signal. |
248 saturating_gain_estimator_.Update(last_gain_, num_saturations); | 253 saturating_gain_estimator_.Update(last_gain_, num_saturations); |
249 | 254 |
250 // Update the metrics. | 255 // Update the metrics. |
251 metrics_.Update(long_term_peak_level, noise_energy, last_gain_, | 256 metrics_.Update(long_term_peak_level, noise_energy, last_gain_, |
252 frame_peak_level); | 257 frame_peak_level); |
253 | 258 |
254 data_dumper_->DumpRaw("lc_selected_gain", 1, &last_gain_); | 259 data_dumper_->DumpRaw("lc_selected_gain", 1, &last_gain_); |
255 data_dumper_->DumpRaw("lc_noise_energy", 1, &noise_energy); | 260 data_dumper_->DumpRaw("lc_noise_energy", 1, &noise_energy); |
256 data_dumper_->DumpRaw("lc_peak_level", 1, &long_term_peak_level); | 261 data_dumper_->DumpRaw("lc_peak_level", 1, &long_term_peak_level); |
257 data_dumper_->DumpRaw("lc_saturating_gain", 1, &saturating_gain); | 262 data_dumper_->DumpRaw("lc_saturating_gain", 1, &saturating_gain); |
258 | 263 |
259 data_dumper_->DumpWav("lc_output", audio->num_frames(), | 264 data_dumper_->DumpWav("lc_output", audio->num_frames(), |
260 audio->channels_f()[0], *sample_rate_hz_, 1); | 265 audio->channels_f()[0], *sample_rate_hz_, 1); |
261 } | 266 } |
262 | 267 |
| 268 void LevelController::ApplyConfig( |
| 269 const AudioProcessing::Config::LevelController& config) { |
| 270 RTC_DCHECK(Validate(config)); |
| 271 config_ = config; |
| 272 peak_level_estimator_.Initialize(config_.initial_peak_level_dbfs); |
| 273 gain_jumpstart_ = true; |
| 274 } |
| 275 |
263 std::string LevelController::ToString( | 276 std::string LevelController::ToString( |
264 const AudioProcessing::Config::LevelController& config) { | 277 const AudioProcessing::Config::LevelController& config) { |
265 std::stringstream ss; | 278 std::stringstream ss; |
266 ss << "{" | 279 ss << "{" |
267 << "enabled: " << (config.enabled ? "true" : "false") << "}"; | 280 << "enabled: " << (config.enabled ? "true" : "false") << ", " |
| 281 << "initial_peak_level_dbfs: " << config.initial_peak_level_dbfs << "}"; |
268 return ss.str(); | 282 return ss.str(); |
269 } | 283 } |
270 | 284 |
271 bool LevelController::Validate( | 285 bool LevelController::Validate( |
272 const AudioProcessing::Config::LevelController& config) { | 286 const AudioProcessing::Config::LevelController& config) { |
273 return true; | 287 return (config.initial_peak_level_dbfs < |
| 288 std::numeric_limits<float>::epsilon() && |
| 289 config.initial_peak_level_dbfs > |
| 290 -(100.f + std::numeric_limits<float>::epsilon())); |
274 } | 291 } |
275 | 292 |
276 } // namespace webrtc | 293 } // namespace webrtc |
OLD | NEW |