2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
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"
25 TestDownConvertToCodecFormat
28 class UtilityTest : public ::testing::Test {
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_);
38 void RunResampleTest(int src_channels, int src_sample_rate_hz,
39 int dst_channels, int dst_sample_rate_hz,
40 FunctionToTest function);
42 PushResampler<int16_t> resampler_;
43 AudioFrame src_frame_;
44 AudioFrame dst_frame_;
45 AudioFrame golden_frame_;
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
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;
61 // Keep the existing sample rate.
62 void SetMonoFrame(AudioFrame* frame, float data) {
63 SetMonoFrame(frame, data, frame->sample_rate_hz_);
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,
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;
80 // Keep the existing sample rate.
81 void SetStereoFrame(AudioFrame* frame, float left, float right) {
82 SetStereoFrame(frame, left, right, frame->sample_rate_hz_);
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_);
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,
96 VerifyParams(ref_frame, test_frame);
99 for (int delay = 0; delay <= max_delay; delay++) {
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];
108 float snr = 100; // We assign 100 dB to the zero-error case.
110 snr = 10 * log10(variance / mse);
111 if (snr > best_snr) {
116 printf("SNR=%.1f dB at delay=%d\n", best_snr, best_delay);
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_;
125 EXPECT_EQ(ref_frame.data_[i], test_frame.data_[i]);
129 void UtilityTest::RunResampleTest(int src_channels,
130 int src_sample_rate_hz,
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) /
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);
145 SetStereoFrame(&src_frame_, kSrcLeft, kSrcRight, src_sample_rate_hz);
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);
152 SetMonoFrame(&golden_frame_, dst_mono, dst_sample_rate_hz);
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);
158 SetStereoFrame(&golden_frame_, dst_left, dst_right, dst_sample_rate_hz);
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_);
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_,
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);
189 EXPECT_GT(ComputeSNR(golden_frame_, dst_frame_, max_delay), 46.0f);
193 TEST_F(UtilityTest, RemixAndResampleCopyFrameSucceeds) {
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_);
201 SetMonoFrame(&src_frame_, 20);
202 SetMonoFrame(&dst_frame_, 0);
203 RemixAndResample(src_frame_, &resampler_, &dst_frame_);
204 VerifyFramesAreEqual(src_frame_, dst_frame_);
207 TEST_F(UtilityTest, RemixAndResampleMixingOnlySucceeds) {
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_);
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_);
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);
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);
263 } // namespace webrtc