peah | 8d2ade6 | 2016-03-22 11:05:12 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 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 |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | #include <vector> |
| 11 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame^] | 12 | #include "api/array_view.h" |
| 13 | #include "modules/audio_processing/audio_buffer.h" |
| 14 | #include "modules/audio_processing/echo_control_mobile_impl.h" |
| 15 | #include "modules/audio_processing/test/audio_buffer_tools.h" |
| 16 | #include "modules/audio_processing/test/bitexactness_tools.h" |
| 17 | #include "test/gtest.h" |
peah | 8d2ade6 | 2016-03-22 11:05:12 -0700 | [diff] [blame] | 18 | |
| 19 | namespace webrtc { |
| 20 | namespace { |
| 21 | |
| 22 | // TODO(peah): Increase the number of frames to proces when the issue of |
| 23 | // non repeatable test results have been found. |
| 24 | const int kNumFramesToProcess = 200; |
| 25 | |
| 26 | void SetupComponent(int sample_rate_hz, |
| 27 | EchoControlMobile::RoutingMode routing_mode, |
| 28 | bool comfort_noise_enabled, |
| 29 | EchoControlMobileImpl* echo_control_mobile) { |
| 30 | echo_control_mobile->Initialize( |
| 31 | sample_rate_hz > 16000 ? 16000 : sample_rate_hz, 1, 1); |
| 32 | EchoControlMobile* ec = static_cast<EchoControlMobile*>(echo_control_mobile); |
| 33 | ec->Enable(true); |
| 34 | ec->set_routing_mode(routing_mode); |
| 35 | ec->enable_comfort_noise(comfort_noise_enabled); |
| 36 | } |
| 37 | |
| 38 | void ProcessOneFrame(int sample_rate_hz, |
| 39 | int stream_delay_ms, |
| 40 | AudioBuffer* render_audio_buffer, |
| 41 | AudioBuffer* capture_audio_buffer, |
| 42 | EchoControlMobileImpl* echo_control_mobile) { |
| 43 | if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) { |
| 44 | render_audio_buffer->SplitIntoFrequencyBands(); |
| 45 | capture_audio_buffer->SplitIntoFrequencyBands(); |
| 46 | } |
| 47 | |
peah | a062460 | 2016-10-25 04:45:24 -0700 | [diff] [blame] | 48 | std::vector<int16_t> render_audio; |
| 49 | EchoControlMobileImpl::PackRenderAudioBuffer( |
| 50 | render_audio_buffer, 1, render_audio_buffer->num_channels(), |
| 51 | &render_audio); |
| 52 | echo_control_mobile->ProcessRenderAudio(render_audio); |
| 53 | |
peah | 8d2ade6 | 2016-03-22 11:05:12 -0700 | [diff] [blame] | 54 | echo_control_mobile->ProcessCaptureAudio(capture_audio_buffer, |
| 55 | stream_delay_ms); |
| 56 | |
| 57 | if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) { |
| 58 | capture_audio_buffer->MergeFrequencyBands(); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | void RunBitexactnessTest(int sample_rate_hz, |
| 63 | size_t num_channels, |
| 64 | int stream_delay_ms, |
| 65 | EchoControlMobile::RoutingMode routing_mode, |
| 66 | bool comfort_noise_enabled, |
| 67 | const rtc::ArrayView<const float>& output_reference) { |
| 68 | rtc::CriticalSection crit_render; |
| 69 | rtc::CriticalSection crit_capture; |
| 70 | EchoControlMobileImpl echo_control_mobile(&crit_render, &crit_capture); |
| 71 | SetupComponent(sample_rate_hz, routing_mode, comfort_noise_enabled, |
| 72 | &echo_control_mobile); |
| 73 | |
| 74 | const int samples_per_channel = rtc::CheckedDivExact(sample_rate_hz, 100); |
| 75 | const StreamConfig render_config(sample_rate_hz, num_channels, false); |
| 76 | AudioBuffer render_buffer( |
| 77 | render_config.num_frames(), render_config.num_channels(), |
| 78 | render_config.num_frames(), 1, render_config.num_frames()); |
| 79 | test::InputAudioFile render_file( |
| 80 | test::GetApmRenderTestVectorFileName(sample_rate_hz)); |
| 81 | std::vector<float> render_input(samples_per_channel * num_channels); |
| 82 | |
| 83 | const StreamConfig capture_config(sample_rate_hz, num_channels, false); |
| 84 | AudioBuffer capture_buffer( |
| 85 | capture_config.num_frames(), capture_config.num_channels(), |
| 86 | capture_config.num_frames(), 1, capture_config.num_frames()); |
| 87 | test::InputAudioFile capture_file( |
| 88 | test::GetApmCaptureTestVectorFileName(sample_rate_hz)); |
| 89 | std::vector<float> capture_input(samples_per_channel * num_channels); |
| 90 | |
| 91 | for (int frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) { |
| 92 | ReadFloatSamplesFromStereoFile(samples_per_channel, num_channels, |
| 93 | &render_file, render_input); |
| 94 | ReadFloatSamplesFromStereoFile(samples_per_channel, num_channels, |
| 95 | &capture_file, capture_input); |
| 96 | |
| 97 | test::CopyVectorToAudioBuffer(render_config, render_input, &render_buffer); |
| 98 | test::CopyVectorToAudioBuffer(capture_config, capture_input, |
| 99 | &capture_buffer); |
| 100 | |
| 101 | ProcessOneFrame(sample_rate_hz, stream_delay_ms, &render_buffer, |
| 102 | &capture_buffer, &echo_control_mobile); |
| 103 | } |
| 104 | |
| 105 | // Extract and verify the test results. |
| 106 | std::vector<float> capture_output; |
| 107 | test::ExtractVectorFromAudioBuffer(capture_config, &capture_buffer, |
| 108 | &capture_output); |
| 109 | |
| 110 | // Compare the output with the reference. Only the first values of the output |
| 111 | // from last frame processed are compared in order not having to specify all |
| 112 | // preceeding frames as testvectors. As the algorithm being tested has a |
| 113 | // memory, testing only the last frame implicitly also tests the preceeding |
| 114 | // frames. |
peah | 7ea928e | 2016-03-30 08:13:57 -0700 | [diff] [blame] | 115 | const float kElementErrorBound = 1.0f / 32768.0f; |
| 116 | EXPECT_TRUE(test::VerifyDeinterleavedArray( |
peah | 8d2ade6 | 2016-03-22 11:05:12 -0700 | [diff] [blame] | 117 | capture_config.num_frames(), capture_config.num_channels(), |
peah | 7ea928e | 2016-03-30 08:13:57 -0700 | [diff] [blame] | 118 | output_reference, capture_output, kElementErrorBound)); |
peah | 8d2ade6 | 2016-03-22 11:05:12 -0700 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | } // namespace |
| 122 | |
| 123 | // TODO(peah): Renable once the integer overflow issue in aecm_core.c:932:69 |
| 124 | // has been solved. |
| 125 | TEST(EchoControlMobileBitExactnessTest, |
| 126 | DISABLED_Mono8kHz_LoudSpeakerPhone_CngOn_StreamDelay0) { |
| 127 | const float kOutputReference[] = {0.005280f, 0.002380f, -0.000427f}; |
| 128 | |
| 129 | RunBitexactnessTest(8000, 1, 0, |
| 130 | EchoControlMobile::RoutingMode::kLoudSpeakerphone, true, |
| 131 | kOutputReference); |
| 132 | } |
| 133 | |
| 134 | TEST(EchoControlMobileBitExactnessTest, |
| 135 | DISABLED_Mono16kHz_LoudSpeakerPhone_CngOn_StreamDelay0) { |
| 136 | const float kOutputReference[] = {0.003601f, 0.002991f, 0.001923f}; |
| 137 | RunBitexactnessTest(16000, 1, 0, |
| 138 | EchoControlMobile::RoutingMode::kLoudSpeakerphone, true, |
| 139 | kOutputReference); |
| 140 | } |
| 141 | |
| 142 | TEST(EchoControlMobileBitExactnessTest, |
| 143 | DISABLED_Mono32kHz_LoudSpeakerPhone_CngOn_StreamDelay0) { |
| 144 | const float kOutputReference[] = {0.002258f, 0.002899f, 0.003906f}; |
| 145 | |
| 146 | RunBitexactnessTest(32000, 1, 0, |
| 147 | EchoControlMobile::RoutingMode::kLoudSpeakerphone, true, |
| 148 | kOutputReference); |
| 149 | } |
| 150 | |
| 151 | TEST(EchoControlMobileBitExactnessTest, |
| 152 | DISABLED_Mono48kHz_LoudSpeakerPhone_CngOn_StreamDelay0) { |
| 153 | const float kOutputReference[] = {-0.000046f, 0.000041f, 0.000249f}; |
| 154 | |
| 155 | RunBitexactnessTest(48000, 1, 0, |
| 156 | EchoControlMobile::RoutingMode::kLoudSpeakerphone, true, |
| 157 | kOutputReference); |
| 158 | } |
| 159 | |
| 160 | TEST(EchoControlMobileBitExactnessTest, |
| 161 | DISABLED_Mono16kHz_LoudSpeakerPhone_CngOff_StreamDelay0) { |
| 162 | const float kOutputReference[] = {0.000000f, 0.000000f, 0.000000f}; |
| 163 | |
| 164 | RunBitexactnessTest(16000, 1, 0, |
| 165 | EchoControlMobile::RoutingMode::kLoudSpeakerphone, false, |
| 166 | kOutputReference); |
| 167 | } |
| 168 | |
| 169 | // TODO(peah): Renable once the integer overflow issue in aecm_core.c:932:69 |
| 170 | // has been solved. |
| 171 | TEST(EchoControlMobileBitExactnessTest, |
| 172 | DISABLED_Mono16kHz_LoudSpeakerPhone_CngOn_StreamDelay5) { |
| 173 | const float kOutputReference[] = {0.003693f, 0.002930f, 0.001801f}; |
| 174 | |
| 175 | RunBitexactnessTest(16000, 1, 5, |
| 176 | EchoControlMobile::RoutingMode::kLoudSpeakerphone, true, |
| 177 | kOutputReference); |
| 178 | } |
| 179 | |
| 180 | TEST(EchoControlMobileBitExactnessTest, |
| 181 | Mono16kHz_LoudSpeakerPhone_CngOn_StreamDelay10) { |
peah | 8974973 | 2016-10-22 04:00:29 -0700 | [diff] [blame] | 182 | const float kOutputReference[] = {-0.002380f, -0.002533f, -0.002563f}; |
peah | 8d2ade6 | 2016-03-22 11:05:12 -0700 | [diff] [blame] | 183 | |
| 184 | RunBitexactnessTest(16000, 1, 10, |
| 185 | EchoControlMobile::RoutingMode::kLoudSpeakerphone, true, |
| 186 | kOutputReference); |
| 187 | } |
| 188 | |
| 189 | TEST(EchoControlMobileBitExactnessTest, |
| 190 | DISABLED_Mono16kHz_QuietEarpieceOrHeadset_CngOn_StreamDelay0) { |
| 191 | const float kOutputReference[] = {0.000397f, 0.000000f, -0.000305f}; |
| 192 | |
| 193 | RunBitexactnessTest(16000, 1, 0, |
| 194 | EchoControlMobile::RoutingMode::kQuietEarpieceOrHeadset, |
| 195 | true, kOutputReference); |
| 196 | } |
| 197 | |
| 198 | TEST(EchoControlMobileBitExactnessTest, |
| 199 | DISABLED_Mono16kHz_Earpiece_CngOn_StreamDelay0) { |
| 200 | const float kOutputReference[] = {0.002167f, 0.001617f, 0.001038f}; |
| 201 | |
| 202 | RunBitexactnessTest(16000, 1, 0, EchoControlMobile::RoutingMode::kEarpiece, |
| 203 | true, kOutputReference); |
| 204 | } |
| 205 | |
| 206 | TEST(EchoControlMobileBitExactnessTest, |
| 207 | DISABLED_Mono16kHz_LoudEarpiece_CngOn_StreamDelay0) { |
| 208 | const float kOutputReference[] = {0.003540f, 0.002899f, 0.001862f}; |
| 209 | |
| 210 | RunBitexactnessTest(16000, 1, 0, |
| 211 | EchoControlMobile::RoutingMode::kLoudEarpiece, true, |
| 212 | kOutputReference); |
| 213 | } |
| 214 | |
| 215 | TEST(EchoControlMobileBitExactnessTest, |
| 216 | DISABLED_Mono16kHz_SpeakerPhone_CngOn_StreamDelay0) { |
| 217 | const float kOutputReference[] = {0.003632f, 0.003052f, 0.001984f}; |
| 218 | |
| 219 | RunBitexactnessTest(16000, 1, 0, |
| 220 | EchoControlMobile::RoutingMode::kSpeakerphone, true, |
| 221 | kOutputReference); |
| 222 | } |
| 223 | |
| 224 | } // namespace webrtc |