Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2017 The WebRTC Project Authors. All rights reserved. | 2 * Copyright (c) 2017 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 // This is a placeholder for the work oprypin@ is doing on a low-bandwidth | 11 #include <algorithm> |
| 12 // audio test executable. | 12 |
| 13 | 13 #include "webrtc/audio/test/low_bandwidth_audio_test.h" |
| 14 int main() { | 14 #include "webrtc/common_audio/wav_file.h" |
| 15 #include "webrtc/test/gtest.h" | |
| 16 #include "webrtc/test/run_test.h" | |
| 17 #include "webrtc/system_wrappers/include/sleep.h" | |
| 18 #include "webrtc/test/testsupport/fileutils.h" | |
| 19 | |
| 20 namespace { | |
| 21 // Wait half a second between stopping sending and stopping receiving audio. | |
| 22 constexpr int kExtraRecordTimeMs = 500; | |
| 23 | |
| 24 // Large bitrate by default. | |
| 25 const webrtc::CodecInst kDefaultCodec{120, "OPUS", 48000, 960, 2, 64000}; | |
| 26 | |
| 27 // The best that can be done with PESQ. | |
| 28 constexpr int kAudioFileBitRate = 16000; | |
| 29 } | |
| 30 | |
| 31 namespace webrtc { | |
| 32 namespace test { | |
| 33 | |
| 34 // Writes to a WAV file, cutting off silence at the beginning and the end. | |
|
kwiberg-webrtc
2017/03/17 11:19:32
For silence in the beginning, you the amplitude on
oprypin_webrtc
2017/03/17 11:45:10
It is intentional but it's just based on the stran
| |
| 35 class BoundedWavFileWriter : public test::FakeAudioDevice::Renderer { | |
| 36 public: | |
| 37 BoundedWavFileWriter(std::string filename, int sampling_frequency_in_hz) | |
| 38 : sampling_frequency_in_hz_(sampling_frequency_in_hz), | |
| 39 wav_writer_(filename, sampling_frequency_in_hz, 1), | |
| 40 silent_audio_(test::FakeAudioDevice::SamplesPerFrame( | |
| 41 sampling_frequency_in_hz), 0), | |
| 42 started_writing_(false), | |
| 43 trailing_zeros_(0) {} | |
| 44 | |
| 45 int SamplingFrequency() const override { | |
| 46 return sampling_frequency_in_hz_; | |
| 47 } | |
| 48 | |
| 49 bool Render(rtc::ArrayView<const int16_t> data) override { | |
| 50 const int16_t kAmplitudeThreshold = 5; | |
| 51 | |
| 52 const int16_t* begin = data.begin(); | |
| 53 const int16_t* end = data.end(); | |
| 54 if (!started_writing_) { | |
| 55 // Cut off silence at the beginning. | |
| 56 while (begin < end) { | |
| 57 if (*begin > kAmplitudeThreshold || *begin < -kAmplitudeThreshold) { | |
|
kwiberg-webrtc
2017/03/17 11:19:32
std::abs(*begin) > kAmplitudeThreshold
?
oprypin_webrtc
2017/03/17 11:45:10
Done.
| |
| 58 started_writing_ = true; | |
| 59 break; | |
| 60 } | |
| 61 ++begin; | |
| 62 } | |
| 63 } | |
| 64 if (started_writing_) { | |
| 65 // Cut off silence at the end. | |
| 66 while (begin < end) { | |
| 67 if (*(end - 1) != 0) { | |
| 68 break; | |
| 69 } | |
| 70 --end; | |
| 71 ++trailing_zeros_; | |
| 72 } | |
| 73 if (begin < end) { | |
| 74 // If it turns out that the silence was not final, need to write all the | |
| 75 // skipped zeros and continue writing audio. | |
| 76 while (trailing_zeros_ > 0) { | |
| 77 const size_t zeros_to_write = std::min(trailing_zeros_, | |
| 78 silent_audio_.size()); | |
| 79 wav_writer_.WriteSamples(silent_audio_.data(), zeros_to_write); | |
| 80 trailing_zeros_ -= zeros_to_write; | |
| 81 } | |
| 82 wav_writer_.WriteSamples(begin, end - begin); | |
| 83 } | |
| 84 } | |
| 85 return true; | |
| 86 } | |
| 87 | |
| 88 private: | |
| 89 int sampling_frequency_in_hz_; | |
| 90 WavWriter wav_writer_; | |
| 91 std::vector<int16_t> silent_audio_; | |
| 92 bool started_writing_; | |
| 93 size_t trailing_zeros_; | |
| 94 }; | |
| 95 | |
| 96 | |
| 97 AudioQualityTest::AudioQualityTest() | |
| 98 : EndToEndTest(CallTest::kDefaultTimeoutMs) {} | |
| 99 | |
| 100 size_t AudioQualityTest::GetNumVideoStreams() const { | |
| 15 return 0; | 101 return 0; |
| 16 } | 102 } |
| 103 size_t AudioQualityTest::GetNumAudioStreams() const { | |
| 104 return 1; | |
| 105 } | |
| 106 size_t AudioQualityTest::GetNumFlexfecStreams() const { | |
| 107 return 0; | |
| 108 } | |
| 109 | |
| 110 std::string AudioQualityTest::AudioInputFile() { | |
| 111 return test::ResourcePath("voice_engine/audio_tiny16", "wav"); | |
| 112 } | |
| 113 | |
| 114 std::string AudioQualityTest::AudioOutputFile() { | |
| 115 const ::testing::TestInfo* const test_info = | |
| 116 ::testing::UnitTest::GetInstance()->current_test_info(); | |
| 117 return webrtc::test::OutputPath() + | |
| 118 "LowBandwidth_" + test_info->name() + ".wav"; | |
| 119 } | |
| 120 | |
| 121 std::unique_ptr<test::FakeAudioDevice::Capturer> | |
| 122 AudioQualityTest::CreateCapturer() { | |
| 123 return test::FakeAudioDevice::CreateWavFileReader(AudioInputFile()); | |
| 124 } | |
| 125 | |
| 126 std::unique_ptr<test::FakeAudioDevice::Renderer> | |
| 127 AudioQualityTest::CreateRenderer() { | |
| 128 return std::unique_ptr<test::FakeAudioDevice::Renderer>( | |
| 129 new BoundedWavFileWriter(AudioOutputFile(), kAudioFileBitRate)); | |
| 130 } | |
| 131 | |
| 132 void AudioQualityTest::OnFakeAudioDevicesCreated( | |
| 133 test::FakeAudioDevice* send_audio_device, | |
| 134 test::FakeAudioDevice* recv_audio_device) { | |
| 135 send_audio_device_ = send_audio_device; | |
| 136 } | |
| 137 | |
| 138 FakeNetworkPipe::Config AudioQualityTest::GetNetworkPipeConfig() { | |
| 139 return FakeNetworkPipe::Config(); | |
| 140 } | |
| 141 | |
| 142 test::PacketTransport* AudioQualityTest::CreateSendTransport( | |
| 143 Call* sender_call) { | |
| 144 return new test::PacketTransport( | |
| 145 sender_call, this, test::PacketTransport::kSender, | |
| 146 GetNetworkPipeConfig()); | |
| 147 } | |
| 148 | |
| 149 test::PacketTransport* AudioQualityTest::CreateReceiveTransport() { | |
| 150 return new test::PacketTransport(nullptr, this, | |
| 151 test::PacketTransport::kReceiver, GetNetworkPipeConfig()); | |
| 152 } | |
| 153 | |
| 154 void AudioQualityTest::ModifyAudioConfigs( | |
| 155 AudioSendStream::Config* send_config, | |
| 156 std::vector<AudioReceiveStream::Config>* receive_configs) { | |
| 157 send_config->send_codec_spec.codec_inst = kDefaultCodec; | |
| 158 } | |
| 159 | |
| 160 void AudioQualityTest::PerformTest() { | |
| 161 // Wait until the input audio file is done... | |
| 162 send_audio_device_->WaitForRecordingEnd(); | |
| 163 // and some extra time to account for network delay. | |
| 164 SleepMs(GetNetworkPipeConfig().queue_delay_ms + kExtraRecordTimeMs); | |
| 165 } | |
| 166 | |
| 167 void AudioQualityTest::OnTestFinished() { | |
| 168 const ::testing::TestInfo* const test_info = | |
| 169 ::testing::UnitTest::GetInstance()->current_test_info(); | |
| 170 | |
| 171 // Output information about the input and output audio files so that further | |
| 172 // processing can be done by an external process. | |
| 173 printf("TEST %s %s:%s\n", test_info->name(), | |
| 174 AudioInputFile().c_str(), AudioOutputFile().c_str()); | |
| 175 } | |
| 176 | |
| 177 | |
| 178 using LowBandwidthAudioTest = test::CallTest; | |
|
kwiberg-webrtc
2017/03/17 11:19:33
You don't need the test:: prefix, since you're in
oprypin_webrtc
2017/03/17 11:45:10
Done.
| |
| 179 | |
| 180 TEST_F(LowBandwidthAudioTest, GoodNetworkHighBitrate) { | |
| 181 AudioQualityTest test; | |
| 182 RunBaseTest(&test); | |
| 183 } | |
| 184 | |
| 185 | |
| 186 class Mobile2GNetworkTest : public AudioQualityTest { | |
| 187 void ModifyAudioConfigs(AudioSendStream::Config* send_config, | |
| 188 std::vector<AudioReceiveStream::Config>* receive_configs) override { | |
| 189 send_config->send_codec_spec.codec_inst = CodecInst{ | |
| 190 120, // pltype | |
| 191 "OPUS", // plname | |
| 192 48000, // plfreq | |
| 193 2880, // pacsize | |
| 194 1, // channels | |
| 195 6000 // rate bits/sec | |
| 196 }; | |
| 197 } | |
| 198 | |
| 199 FakeNetworkPipe::Config GetNetworkPipeConfig() override { | |
| 200 FakeNetworkPipe::Config pipe_config; | |
| 201 pipe_config.link_capacity_kbps = 12; | |
| 202 pipe_config.queue_length_packets = 1500; | |
| 203 pipe_config.queue_delay_ms = 400; | |
| 204 return pipe_config; | |
| 205 } | |
| 206 }; | |
| 207 | |
| 208 TEST_F(LowBandwidthAudioTest, Mobile2GNetwork) { | |
| 209 Mobile2GNetworkTest test; | |
| 210 RunBaseTest(&test); | |
| 211 } | |
| 212 | |
| 213 } // namespace test | |
| 214 } // namespace webrtc | |
| OLD | NEW |