1 /* 2 * Copyright (c) 2012 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 11 #include <math.h> 12 13 #include "testing/gtest/include/gtest/gtest.h" 14 #include "webrtc/common_audio/resampler/include/push_resampler.h" 15 #include "webrtc/modules/interface/module_common_types.h" 16 #include "webrtc/voice_engine/utility.h" 17 #include "webrtc/voice_engine/voice_engine_defines.h" 18 19 namespace webrtc { 20 namespace voe { 21 namespace { 22 23 enum FunctionToTest { 24 TestRemixAndResample, 25 TestDownConvertToCodecFormat 26 }; 27 28 class UtilityTest : public ::testing::Test { 29 protected: 30 UtilityTest() { 31 src_frame_.sample_rate_hz_ = 16000; 32 src_frame_.samples_per_channel_ = src_frame_.sample_rate_hz_ / 100; 33 src_frame_.num_channels_ = 1; 34 dst_frame_.CopyFrom(src_frame_); 35 golden_frame_.CopyFrom(src_frame_); 36 } 37 38 void RunResampleTest(int src_channels, int src_sample_rate_hz, 39 int dst_channels, int dst_sample_rate_hz, 40 FunctionToTest function); 41 42 PushResampler<int16_t> resampler_; 43 AudioFrame src_frame_; 44 AudioFrame dst_frame_; 45 AudioFrame golden_frame_; 46 }; 47 48 // Sets the signal value to increase by |data| with every sample. Floats are 49 // used so non-integer values result in rounding error, but not an accumulating 50 // error. 51 void SetMonoFrame(AudioFrame* frame, float data, int sample_rate_hz) { 52 memset(frame->data_, 0, sizeof(frame->data_)); 53 frame->num_channels_ = 1; 54 frame->sample_rate_hz_ = sample_rate_hz; 55 frame->samples_per_channel_ = sample_rate_hz / 100; 56 for (int i = 0; i < frame->samples_per_channel_; i++) { 57 frame->data_[i] = data * i; 58 } 59 } 60 61 // Keep the existing sample rate. 62 void SetMonoFrame(AudioFrame* frame, float data) { 63 SetMonoFrame(frame, data, frame->sample_rate_hz_); 64 } 65 66 // Sets the signal value to increase by |left| and |right| with every sample in 67 // each channel respectively. 68 void SetStereoFrame(AudioFrame* frame, float left, float right, 69 int sample_rate_hz) { 70 memset(frame->data_, 0, sizeof(frame->data_)); 71 frame->num_channels_ = 2; 72 frame->sample_rate_hz_ = sample_rate_hz; 73 frame->samples_per_channel_ = sample_rate_hz / 100; 74 for (int i = 0; i < frame->samples_per_channel_; i++) { 75 frame->data_[i * 2] = left * i; 76 frame->data_[i * 2 + 1] = right * i; 77 } 78 } 79 80 // Keep the existing sample rate. 81 void SetStereoFrame(AudioFrame* frame, float left, float right) { 82 SetStereoFrame(frame, left, right, frame->sample_rate_hz_); 83 } 84 85 void VerifyParams(const AudioFrame& ref_frame, const AudioFrame& test_frame) { 86 EXPECT_EQ(ref_frame.num_channels_, test_frame.num_channels_); 87 EXPECT_EQ(ref_frame.samples_per_channel_, test_frame.samples_per_channel_); 88 EXPECT_EQ(ref_frame.sample_rate_hz_, test_frame.sample_rate_hz_); 89 } 90 91 // Computes the best SNR based on the error between |ref_frame| and 92 // |test_frame|. It allows for up to a |max_delay| in samples between the 93 // signals to compensate for the resampling delay. 94 float ComputeSNR(const AudioFrame& ref_frame, const AudioFrame& test_frame, 95 int max_delay) { 96 VerifyParams(ref_frame, test_frame); 97 float best_snr = 0; 98 int best_delay = 0; 99 for (int delay = 0; delay <= max_delay; delay++) { 100 float mse = 0; 101 float variance = 0; 102 for (int i = 0; i < ref_frame.samples_per_channel_ * 103 ref_frame.num_channels_ - delay; i++) { 104 int error = ref_frame.data_[i] - test_frame.data_[i + delay]; 105 mse += error * error; 106 variance += ref_frame.data_[i] * ref_frame.data_[i]; 107 } 108 float snr = 100; // We assign 100 dB to the zero-error case. 109 if (mse > 0) 110 snr = 10 * log10(variance / mse); 111 if (snr > best_snr) { 112 best_snr = snr; 113 best_delay = delay; 114 } 115 } 116 printf("SNR=%.1f dB at delay=%d\n", best_snr, best_delay); 117 return best_snr; 118 } 119 120 void VerifyFramesAreEqual(const AudioFrame& ref_frame, 121 const AudioFrame& test_frame) { 122 VerifyParams(ref_frame, test_frame); 123 for (int i = 0; i < ref_frame.samples_per_channel_ * ref_frame.num_channels_; 124 i++) { 125 EXPECT_EQ(ref_frame.data_[i], test_frame.data_[i]); 126 } 127 } 128 129 void UtilityTest::RunResampleTest(int src_channels, 130 int src_sample_rate_hz, 131 int dst_channels, 132 int dst_sample_rate_hz, 133 FunctionToTest function) { 134 PushResampler<int16_t> resampler; // Create a new one with every test. 135 const int16_t kSrcLeft = 30; // Shouldn't overflow for any used sample rate. 136 const int16_t kSrcRight = 15; 137 const float resampling_factor = (1.0 * src_sample_rate_hz) / 138 dst_sample_rate_hz; 139 const float dst_left = resampling_factor * kSrcLeft; 140 const float dst_right = resampling_factor * kSrcRight; 141 const float dst_mono = (dst_left + dst_right) / 2; 142 if (src_channels == 1) 143 SetMonoFrame(&src_frame_, kSrcLeft, src_sample_rate_hz); 144 else 145 SetStereoFrame(&src_frame_, kSrcLeft, kSrcRight, src_sample_rate_hz); 146 147 if (dst_channels == 1) { 148 SetMonoFrame(&dst_frame_, 0, dst_sample_rate_hz); 149 if (src_channels == 1) 150 SetMonoFrame(&golden_frame_, dst_left, dst_sample_rate_hz); 151 else 152 SetMonoFrame(&golden_frame_, dst_mono, dst_sample_rate_hz); 153 } else { 154 SetStereoFrame(&dst_frame_, 0, 0, dst_sample_rate_hz); 155 if (src_channels == 1) 156 SetStereoFrame(&golden_frame_, dst_left, dst_left, dst_sample_rate_hz); 157 else 158 SetStereoFrame(&golden_frame_, dst_left, dst_right, dst_sample_rate_hz); 159 } 160 161 // The sinc resampler has a known delay, which we compute here. Multiplying by 162 // two gives us a crude maximum for any resampling, as the old resampler 163 // typically (but not always) has lower delay. 164 static const int kInputKernelDelaySamples = 16; 165 const int max_delay = static_cast<double>(dst_sample_rate_hz) 166 / src_sample_rate_hz * kInputKernelDelaySamples * dst_channels * 2; 167 printf("(%d, %d Hz) -> (%d, %d Hz) ", // SNR reported on the same line later. 168 src_channels, src_sample_rate_hz, dst_channels, dst_sample_rate_hz); 169 if (function == TestRemixAndResample) { 170 RemixAndResample(src_frame_, &resampler, &dst_frame_); 171 } else { 172 int16_t mono_buffer[kMaxMonoDataSizeSamples]; 173 DownConvertToCodecFormat(src_frame_.data_, 174 src_frame_.samples_per_channel_, 175 src_frame_.num_channels_, 176 src_frame_.sample_rate_hz_, 177 dst_frame_.num_channels_, 178 dst_frame_.sample_rate_hz_, 179 mono_buffer, 180 &resampler, 181 &dst_frame_); 182 } 183 184 if (src_sample_rate_hz == 96000 && dst_sample_rate_hz == 8000) { 185 // The sinc resampler gives poor SNR at this extreme conversion, but we 186 // expect to see this rarely in practice. 187 EXPECT_GT(ComputeSNR(golden_frame_, dst_frame_, max_delay), 14.0f); 188 } else { 189 EXPECT_GT(ComputeSNR(golden_frame_, dst_frame_, max_delay), 46.0f); 190 } 191 } 192 193 TEST_F(UtilityTest, RemixAndResampleCopyFrameSucceeds) { 194 // Stereo -> stereo. 195 SetStereoFrame(&src_frame_, 10, 10); 196 SetStereoFrame(&dst_frame_, 0, 0); 197 RemixAndResample(src_frame_, &resampler_, &dst_frame_); 198 VerifyFramesAreEqual(src_frame_, dst_frame_); 199 200 // Mono -> mono. 201 SetMonoFrame(&src_frame_, 20); 202 SetMonoFrame(&dst_frame_, 0); 203 RemixAndResample(src_frame_, &resampler_, &dst_frame_); 204 VerifyFramesAreEqual(src_frame_, dst_frame_); 205 } 206 207 TEST_F(UtilityTest, RemixAndResampleMixingOnlySucceeds) { 208 // Stereo -> mono. 209 SetStereoFrame(&dst_frame_, 0, 0); 210 SetMonoFrame(&src_frame_, 10); 211 SetStereoFrame(&golden_frame_, 10, 10); 212 RemixAndResample(src_frame_, &resampler_, &dst_frame_); 213 VerifyFramesAreEqual(dst_frame_, golden_frame_); 214 215 // Mono -> stereo. 216 SetMonoFrame(&dst_frame_, 0); 217 SetStereoFrame(&src_frame_, 10, 20); 218 SetMonoFrame(&golden_frame_, 15); 219 RemixAndResample(src_frame_, &resampler_, &dst_frame_); 220 VerifyFramesAreEqual(golden_frame_, dst_frame_); 221 } 222 223 TEST_F(UtilityTest, RemixAndResampleSucceeds) { 224 const int kSampleRates[] = {8000, 16000, 32000, 44100, 48000, 96000}; 225 const int kSampleRatesSize = sizeof(kSampleRates) / sizeof(*kSampleRates); 226 const int kChannels[] = {1, 2}; 227 const int kChannelsSize = sizeof(kChannels) / sizeof(*kChannels); 228 for (int src_rate = 0; src_rate < kSampleRatesSize; src_rate++) { 229 for (int dst_rate = 0; dst_rate < kSampleRatesSize; dst_rate++) { 230 for (int src_channel = 0; src_channel < kChannelsSize; src_channel++) { 231 for (int dst_channel = 0; dst_channel < kChannelsSize; dst_channel++) { 232 RunResampleTest(kChannels[src_channel], kSampleRates[src_rate], 233 kChannels[dst_channel], kSampleRates[dst_rate], 234 TestRemixAndResample); 235 } 236 } 237 } 238 } 239 } 240 241 TEST_F(UtilityTest, ConvertToCodecFormatSucceeds) { 242 const int kSampleRates[] = {8000, 16000, 32000, 44100, 48000, 96000}; 243 const int kSampleRatesSize = sizeof(kSampleRates) / sizeof(*kSampleRates); 244 const int kChannels[] = {1, 2}; 245 const int kChannelsSize = sizeof(kChannels) / sizeof(*kChannels); 246 for (int src_rate = 0; src_rate < kSampleRatesSize; src_rate++) { 247 for (int dst_rate = 0; dst_rate < kSampleRatesSize; dst_rate++) { 248 for (int src_channel = 0; src_channel < kChannelsSize; src_channel++) { 249 for (int dst_channel = 0; dst_channel < kChannelsSize; dst_channel++) { 250 if (dst_rate <= src_rate && dst_channel <= src_channel) { 251 RunResampleTest(kChannels[src_channel], kSampleRates[src_rate], 252 kChannels[src_channel], kSampleRates[dst_rate], 253 TestDownConvertToCodecFormat); 254 } 255 } 256 } 257 } 258 } 259 } 260 261 } // namespace 262 } // namespace voe 263 } // namespace webrtc 264