| 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 |
| 11 #include "webrtc/modules/audio_processing/test/audio_processing_simulator.h" | 11 #include "webrtc/modules/audio_processing/test/audio_processing_simulator.h" |
| 12 | 12 |
| 13 #include <algorithm> | 13 #include <algorithm> |
| 14 #include <iostream> | 14 #include <iostream> |
| 15 #include <sstream> | 15 #include <sstream> |
| 16 #include <string> | 16 #include <string> |
| 17 #include <vector> | 17 #include <vector> |
| 18 | 18 |
| 19 #include "webrtc/base/checks.h" |
| 19 #include "webrtc/base/stringutils.h" | 20 #include "webrtc/base/stringutils.h" |
| 20 #include "webrtc/common_audio/include/audio_util.h" | 21 #include "webrtc/common_audio/include/audio_util.h" |
| 21 #include "webrtc/modules/audio_processing/include/audio_processing.h" | 22 #include "webrtc/modules/audio_processing/include/audio_processing.h" |
| 22 | 23 |
| 23 namespace webrtc { | 24 namespace webrtc { |
| 24 namespace test { | 25 namespace test { |
| 25 namespace { | 26 namespace { |
| 26 | 27 |
| 27 void CopyFromAudioFrame(const AudioFrame& src, ChannelBuffer<float>* dest) { | 28 void CopyFromAudioFrame(const AudioFrame& src, ChannelBuffer<float>* dest) { |
| 28 RTC_CHECK_EQ(src.num_channels_, dest->num_channels()); | 29 RTC_CHECK_EQ(src.num_channels_, dest->num_channels()); |
| 29 RTC_CHECK_EQ(src.samples_per_channel_, dest->num_frames()); | 30 RTC_CHECK_EQ(src.samples_per_channel_, dest->num_frames()); |
| 30 // Copy the data from the input buffer. | 31 // Copy the data from the input buffer. |
| 31 std::vector<float> tmp(src.samples_per_channel_ * src.num_channels_); | 32 std::vector<float> tmp(src.samples_per_channel_ * src.num_channels_); |
| 32 S16ToFloat(src.data_, tmp.size(), tmp.data()); | 33 S16ToFloat(src.data_, tmp.size(), tmp.data()); |
| 33 Deinterleave(tmp.data(), src.samples_per_channel_, src.num_channels_, | 34 Deinterleave(tmp.data(), src.samples_per_channel_, src.num_channels_, |
| 34 dest->channels()); | 35 dest->channels()); |
| 35 } | 36 } |
| 36 | 37 |
| 37 std::string GetIndexedOutputWavFilename(const std::string& wav_name, | 38 std::string GetIndexedOutputWavFilename(const std::string& wav_name, |
| 38 int counter) { | 39 int counter) { |
| 39 std::stringstream ss; | 40 std::stringstream ss; |
| 40 ss << wav_name.substr(0, wav_name.size() - 4) << "_" << counter | 41 ss << wav_name.substr(0, wav_name.size() - 4) << "_" << counter |
| 41 << wav_name.substr(wav_name.size() - 4); | 42 << wav_name.substr(wav_name.size() - 4); |
| 42 return ss.str(); | 43 return ss.str(); |
| 43 } | 44 } |
| 44 | 45 |
| 46 void WriteEchoLikelihoodGraphFileHeader(std::ofstream* output_file) { |
| 47 (*output_file) << "import numpy as np" << std::endl |
| 48 << "import matplotlib.pyplot as plt" << std::endl |
| 49 << "y = np.array(["; |
| 50 } |
| 51 |
| 52 void WriteEchoLikelihoodGraphFileFooter(std::ofstream* output_file) { |
| 53 (*output_file) << "])" << std::endl |
| 54 << "x = np.arange(len(y))*.01" << std::endl |
| 55 << "plt.plot(x, y)" << std::endl |
| 56 << "plt.ylabel('Echo likelihood')" << std::endl |
| 57 << "plt.xlabel('Time (s)')" << std::endl |
| 58 << "plt.ylim([0,1])" << std::endl |
| 59 << "plt.show()" << std::endl; |
| 60 } |
| 61 |
| 45 } // namespace | 62 } // namespace |
| 46 | 63 |
| 47 SimulationSettings::SimulationSettings() = default; | 64 SimulationSettings::SimulationSettings() = default; |
| 48 SimulationSettings::SimulationSettings(const SimulationSettings&) = default; | 65 SimulationSettings::SimulationSettings(const SimulationSettings&) = default; |
| 49 SimulationSettings::~SimulationSettings() = default; | 66 SimulationSettings::~SimulationSettings() = default; |
| 50 | 67 |
| 51 void CopyToAudioFrame(const ChannelBuffer<float>& src, AudioFrame* dest) { | 68 void CopyToAudioFrame(const ChannelBuffer<float>& src, AudioFrame* dest) { |
| 52 RTC_CHECK_EQ(src.num_channels(), dest->num_channels_); | 69 RTC_CHECK_EQ(src.num_channels(), dest->num_channels_); |
| 53 RTC_CHECK_EQ(src.num_frames(), dest->samples_per_channel_); | 70 RTC_CHECK_EQ(src.num_frames(), dest->samples_per_channel_); |
| 54 for (size_t ch = 0; ch < dest->num_channels_; ++ch) { | 71 for (size_t ch = 0; ch < dest->num_channels_; ++ch) { |
| 55 for (size_t sample = 0; sample < dest->samples_per_channel_; ++sample) { | 72 for (size_t sample = 0; sample < dest->samples_per_channel_; ++sample) { |
| 56 dest->data_[sample * dest->num_channels_ + ch] = | 73 dest->data_[sample * dest->num_channels_ + ch] = |
| 57 src.channels()[ch][sample] * 32767; | 74 src.channels()[ch][sample] * 32767; |
| 58 } | 75 } |
| 59 } | 76 } |
| 60 } | 77 } |
| 61 | 78 |
| 62 AudioProcessingSimulator::AudioProcessingSimulator( | 79 AudioProcessingSimulator::AudioProcessingSimulator( |
| 63 const SimulationSettings& settings) | 80 const SimulationSettings& settings) |
| 64 : settings_(settings) {} | 81 : settings_(settings) { |
| 82 if (settings_.red_graph_output_filename && |
| 83 settings_.red_graph_output_filename->size() > 0) { |
| 84 residual_echo_likelihood_graph_writer_.open( |
| 85 *settings_.red_graph_output_filename); |
| 86 RTC_CHECK(residual_echo_likelihood_graph_writer_.is_open()); |
| 87 WriteEchoLikelihoodGraphFileHeader(&residual_echo_likelihood_graph_writer_); |
| 88 } |
| 89 } |
| 65 | 90 |
| 66 AudioProcessingSimulator::~AudioProcessingSimulator() = default; | 91 AudioProcessingSimulator::~AudioProcessingSimulator() { |
| 92 if (residual_echo_likelihood_graph_writer_.is_open()) { |
| 93 WriteEchoLikelihoodGraphFileFooter(&residual_echo_likelihood_graph_writer_); |
| 94 residual_echo_likelihood_graph_writer_.close(); |
| 95 } |
| 96 } |
| 67 | 97 |
| 68 AudioProcessingSimulator::ScopedTimer::~ScopedTimer() { | 98 AudioProcessingSimulator::ScopedTimer::~ScopedTimer() { |
| 69 int64_t interval = rtc::TimeNanos() - start_time_; | 99 int64_t interval = rtc::TimeNanos() - start_time_; |
| 70 proc_time_->sum += interval; | 100 proc_time_->sum += interval; |
| 71 proc_time_->max = std::max(proc_time_->max, interval); | 101 proc_time_->max = std::max(proc_time_->max, interval); |
| 72 proc_time_->min = std::min(proc_time_->min, interval); | 102 proc_time_->min = std::min(proc_time_->min, interval); |
| 73 } | 103 } |
| 74 | 104 |
| 75 void AudioProcessingSimulator::ProcessStream(bool fixed_interface) { | 105 void AudioProcessingSimulator::ProcessStream(bool fixed_interface) { |
| 76 if (fixed_interface) { | 106 if (fixed_interface) { |
| 77 { | 107 { |
| 78 const auto st = ScopedTimer(mutable_proc_time()); | 108 const auto st = ScopedTimer(mutable_proc_time()); |
| 79 RTC_CHECK_EQ(AudioProcessing::kNoError, ap_->ProcessStream(&fwd_frame_)); | 109 RTC_CHECK_EQ(AudioProcessing::kNoError, ap_->ProcessStream(&fwd_frame_)); |
| 80 } | 110 } |
| 81 CopyFromAudioFrame(fwd_frame_, out_buf_.get()); | 111 CopyFromAudioFrame(fwd_frame_, out_buf_.get()); |
| 82 } else { | 112 } else { |
| 83 const auto st = ScopedTimer(mutable_proc_time()); | 113 const auto st = ScopedTimer(mutable_proc_time()); |
| 84 RTC_CHECK_EQ(AudioProcessing::kNoError, | 114 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 85 ap_->ProcessStream(in_buf_->channels(), in_config_, | 115 ap_->ProcessStream(in_buf_->channels(), in_config_, |
| 86 out_config_, out_buf_->channels())); | 116 out_config_, out_buf_->channels())); |
| 87 } | 117 } |
| 88 | 118 |
| 89 if (buffer_writer_) { | 119 if (buffer_writer_) { |
| 90 buffer_writer_->Write(*out_buf_); | 120 buffer_writer_->Write(*out_buf_); |
| 91 } | 121 } |
| 92 | 122 |
| 123 if (residual_echo_likelihood_graph_writer_.is_open()) { |
| 124 auto stats = ap_->GetStatistics(); |
| 125 residual_echo_likelihood_graph_writer_ << stats.residual_echo_likelihood |
| 126 << ", "; |
| 127 } |
| 128 |
| 93 ++num_process_stream_calls_; | 129 ++num_process_stream_calls_; |
| 94 } | 130 } |
| 95 | 131 |
| 96 void AudioProcessingSimulator::ProcessReverseStream(bool fixed_interface) { | 132 void AudioProcessingSimulator::ProcessReverseStream(bool fixed_interface) { |
| 97 if (fixed_interface) { | 133 if (fixed_interface) { |
| 98 const auto st = ScopedTimer(mutable_proc_time()); | 134 const auto st = ScopedTimer(mutable_proc_time()); |
| 99 RTC_CHECK_EQ(AudioProcessing::kNoError, | 135 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 100 ap_->ProcessReverseStream(&rev_frame_)); | 136 ap_->ProcessReverseStream(&rev_frame_)); |
| 101 CopyFromAudioFrame(rev_frame_, reverse_out_buf_.get()); | 137 CopyFromAudioFrame(rev_frame_, reverse_out_buf_.get()); |
| 102 | 138 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 apm_config.level_controller.enabled = *settings_.use_lc; | 274 apm_config.level_controller.enabled = *settings_.use_lc; |
| 239 } | 275 } |
| 240 if (settings_.use_refined_adaptive_filter) { | 276 if (settings_.use_refined_adaptive_filter) { |
| 241 config.Set<RefinedAdaptiveFilter>( | 277 config.Set<RefinedAdaptiveFilter>( |
| 242 new RefinedAdaptiveFilter(*settings_.use_refined_adaptive_filter)); | 278 new RefinedAdaptiveFilter(*settings_.use_refined_adaptive_filter)); |
| 243 } | 279 } |
| 244 config.Set<ExtendedFilter>(new ExtendedFilter( | 280 config.Set<ExtendedFilter>(new ExtendedFilter( |
| 245 !settings_.use_extended_filter || *settings_.use_extended_filter)); | 281 !settings_.use_extended_filter || *settings_.use_extended_filter)); |
| 246 config.Set<DelayAgnostic>(new DelayAgnostic(!settings_.use_delay_agnostic || | 282 config.Set<DelayAgnostic>(new DelayAgnostic(!settings_.use_delay_agnostic || |
| 247 *settings_.use_delay_agnostic)); | 283 *settings_.use_delay_agnostic)); |
| 284 if (settings_.use_red) { |
| 285 apm_config.residual_echo_detector.enabled = *settings_.use_red; |
| 286 } |
| 248 | 287 |
| 249 ap_.reset(AudioProcessing::Create(config)); | 288 ap_.reset(AudioProcessing::Create(config)); |
| 250 RTC_CHECK(ap_); | 289 RTC_CHECK(ap_); |
| 251 | 290 |
| 252 ap_->ApplyConfig(apm_config); | 291 ap_->ApplyConfig(apm_config); |
| 253 | 292 |
| 254 if (settings_.use_aec) { | 293 if (settings_.use_aec) { |
| 255 RTC_CHECK_EQ(AudioProcessing::kNoError, | 294 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 256 ap_->echo_cancellation()->Enable(*settings_.use_aec)); | 295 ap_->echo_cancellation()->Enable(*settings_.use_aec)); |
| 257 } | 296 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 size_t kMaxFilenameSize = AudioProcessing::kMaxFilenameSize; | 382 size_t kMaxFilenameSize = AudioProcessing::kMaxFilenameSize; |
| 344 RTC_CHECK_LE(settings_.aec_dump_output_filename->size(), kMaxFilenameSize); | 383 RTC_CHECK_LE(settings_.aec_dump_output_filename->size(), kMaxFilenameSize); |
| 345 RTC_CHECK_EQ(AudioProcessing::kNoError, | 384 RTC_CHECK_EQ(AudioProcessing::kNoError, |
| 346 ap_->StartDebugRecording( | 385 ap_->StartDebugRecording( |
| 347 settings_.aec_dump_output_filename->c_str(), -1)); | 386 settings_.aec_dump_output_filename->c_str(), -1)); |
| 348 } | 387 } |
| 349 } | 388 } |
| 350 | 389 |
| 351 } // namespace test | 390 } // namespace test |
| 352 } // namespace webrtc | 391 } // namespace webrtc |
| OLD | NEW |