OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 <math.h> | 11 #include <math.h> |
12 | 12 |
13 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 #include "webrtc/base/format_macros.h" |
14 #include "webrtc/common_audio/resampler/include/push_resampler.h" | 15 #include "webrtc/common_audio/resampler/include/push_resampler.h" |
15 #include "webrtc/modules/interface/module_common_types.h" | 16 #include "webrtc/modules/interface/module_common_types.h" |
16 #include "webrtc/voice_engine/utility.h" | 17 #include "webrtc/voice_engine/utility.h" |
17 #include "webrtc/voice_engine/voice_engine_defines.h" | 18 #include "webrtc/voice_engine/voice_engine_defines.h" |
18 | 19 |
19 namespace webrtc { | 20 namespace webrtc { |
20 namespace voe { | 21 namespace voe { |
21 namespace { | 22 namespace { |
22 | 23 |
23 enum FunctionToTest { | 24 enum FunctionToTest { |
(...skipping 22 matching lines...) Expand all Loading... |
46 }; | 47 }; |
47 | 48 |
48 // Sets the signal value to increase by |data| with every sample. Floats are | 49 // 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 // used so non-integer values result in rounding error, but not an accumulating |
50 // error. | 51 // error. |
51 void SetMonoFrame(AudioFrame* frame, float data, int sample_rate_hz) { | 52 void SetMonoFrame(AudioFrame* frame, float data, int sample_rate_hz) { |
52 memset(frame->data_, 0, sizeof(frame->data_)); | 53 memset(frame->data_, 0, sizeof(frame->data_)); |
53 frame->num_channels_ = 1; | 54 frame->num_channels_ = 1; |
54 frame->sample_rate_hz_ = sample_rate_hz; | 55 frame->sample_rate_hz_ = sample_rate_hz; |
55 frame->samples_per_channel_ = sample_rate_hz / 100; | 56 frame->samples_per_channel_ = sample_rate_hz / 100; |
56 for (int i = 0; i < frame->samples_per_channel_; i++) { | 57 for (size_t i = 0; i < frame->samples_per_channel_; i++) { |
57 frame->data_[i] = static_cast<int16_t>(data * i); | 58 frame->data_[i] = static_cast<int16_t>(data * i); |
58 } | 59 } |
59 } | 60 } |
60 | 61 |
61 // Keep the existing sample rate. | 62 // Keep the existing sample rate. |
62 void SetMonoFrame(AudioFrame* frame, float data) { | 63 void SetMonoFrame(AudioFrame* frame, float data) { |
63 SetMonoFrame(frame, data, frame->sample_rate_hz_); | 64 SetMonoFrame(frame, data, frame->sample_rate_hz_); |
64 } | 65 } |
65 | 66 |
66 // Sets the signal value to increase by |left| and |right| with every sample in | 67 // Sets the signal value to increase by |left| and |right| with every sample in |
67 // each channel respectively. | 68 // each channel respectively. |
68 void SetStereoFrame(AudioFrame* frame, float left, float right, | 69 void SetStereoFrame(AudioFrame* frame, float left, float right, |
69 int sample_rate_hz) { | 70 int sample_rate_hz) { |
70 memset(frame->data_, 0, sizeof(frame->data_)); | 71 memset(frame->data_, 0, sizeof(frame->data_)); |
71 frame->num_channels_ = 2; | 72 frame->num_channels_ = 2; |
72 frame->sample_rate_hz_ = sample_rate_hz; | 73 frame->sample_rate_hz_ = sample_rate_hz; |
73 frame->samples_per_channel_ = sample_rate_hz / 100; | 74 frame->samples_per_channel_ = sample_rate_hz / 100; |
74 for (int i = 0; i < frame->samples_per_channel_; i++) { | 75 for (size_t i = 0; i < frame->samples_per_channel_; i++) { |
75 frame->data_[i * 2] = static_cast<int16_t>(left * i); | 76 frame->data_[i * 2] = static_cast<int16_t>(left * i); |
76 frame->data_[i * 2 + 1] = static_cast<int16_t>(right * i); | 77 frame->data_[i * 2 + 1] = static_cast<int16_t>(right * i); |
77 } | 78 } |
78 } | 79 } |
79 | 80 |
80 // Keep the existing sample rate. | 81 // Keep the existing sample rate. |
81 void SetStereoFrame(AudioFrame* frame, float left, float right) { | 82 void SetStereoFrame(AudioFrame* frame, float left, float right) { |
82 SetStereoFrame(frame, left, right, frame->sample_rate_hz_); | 83 SetStereoFrame(frame, left, right, frame->sample_rate_hz_); |
83 } | 84 } |
84 | 85 |
85 void VerifyParams(const AudioFrame& ref_frame, const AudioFrame& test_frame) { | 86 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.num_channels_, test_frame.num_channels_); |
87 EXPECT_EQ(ref_frame.samples_per_channel_, test_frame.samples_per_channel_); | 88 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 EXPECT_EQ(ref_frame.sample_rate_hz_, test_frame.sample_rate_hz_); |
89 } | 90 } |
90 | 91 |
91 // Computes the best SNR based on the error between |ref_frame| and | 92 // 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 // |test_frame|. It allows for up to a |max_delay| in samples between the |
93 // signals to compensate for the resampling delay. | 94 // signals to compensate for the resampling delay. |
94 float ComputeSNR(const AudioFrame& ref_frame, const AudioFrame& test_frame, | 95 float ComputeSNR(const AudioFrame& ref_frame, const AudioFrame& test_frame, |
95 int max_delay) { | 96 size_t max_delay) { |
96 VerifyParams(ref_frame, test_frame); | 97 VerifyParams(ref_frame, test_frame); |
97 float best_snr = 0; | 98 float best_snr = 0; |
98 int best_delay = 0; | 99 size_t best_delay = 0; |
99 for (int delay = 0; delay <= max_delay; delay++) { | 100 for (size_t delay = 0; delay <= max_delay; delay++) { |
100 float mse = 0; | 101 float mse = 0; |
101 float variance = 0; | 102 float variance = 0; |
102 for (int i = 0; i < ref_frame.samples_per_channel_ * | 103 for (size_t i = 0; i < ref_frame.samples_per_channel_ * |
103 ref_frame.num_channels_ - delay; i++) { | 104 ref_frame.num_channels_ - delay; i++) { |
104 int error = ref_frame.data_[i] - test_frame.data_[i + delay]; | 105 int error = ref_frame.data_[i] - test_frame.data_[i + delay]; |
105 mse += error * error; | 106 mse += error * error; |
106 variance += ref_frame.data_[i] * ref_frame.data_[i]; | 107 variance += ref_frame.data_[i] * ref_frame.data_[i]; |
107 } | 108 } |
108 float snr = 100; // We assign 100 dB to the zero-error case. | 109 float snr = 100; // We assign 100 dB to the zero-error case. |
109 if (mse > 0) | 110 if (mse > 0) |
110 snr = 10 * log10(variance / mse); | 111 snr = 10 * log10(variance / mse); |
111 if (snr > best_snr) { | 112 if (snr > best_snr) { |
112 best_snr = snr; | 113 best_snr = snr; |
113 best_delay = delay; | 114 best_delay = delay; |
114 } | 115 } |
115 } | 116 } |
116 printf("SNR=%.1f dB at delay=%d\n", best_snr, best_delay); | 117 printf("SNR=%.1f dB at delay=%" PRIuS "\n", best_snr, best_delay); |
117 return best_snr; | 118 return best_snr; |
118 } | 119 } |
119 | 120 |
120 void VerifyFramesAreEqual(const AudioFrame& ref_frame, | 121 void VerifyFramesAreEqual(const AudioFrame& ref_frame, |
121 const AudioFrame& test_frame) { | 122 const AudioFrame& test_frame) { |
122 VerifyParams(ref_frame, test_frame); | 123 VerifyParams(ref_frame, test_frame); |
123 for (int i = 0; i < ref_frame.samples_per_channel_ * ref_frame.num_channels_; | 124 for (size_t i = 0; |
124 i++) { | 125 i < ref_frame.samples_per_channel_ * ref_frame.num_channels_; i++) { |
125 EXPECT_EQ(ref_frame.data_[i], test_frame.data_[i]); | 126 EXPECT_EQ(ref_frame.data_[i], test_frame.data_[i]); |
126 } | 127 } |
127 } | 128 } |
128 | 129 |
129 void UtilityTest::RunResampleTest(int src_channels, | 130 void UtilityTest::RunResampleTest(int src_channels, |
130 int src_sample_rate_hz, | 131 int src_sample_rate_hz, |
131 int dst_channels, | 132 int dst_channels, |
132 int dst_sample_rate_hz, | 133 int dst_sample_rate_hz, |
133 FunctionToTest function) { | 134 FunctionToTest function) { |
134 PushResampler<int16_t> resampler; // Create a new one with every test. | 135 PushResampler<int16_t> resampler; // Create a new one with every test. |
(...skipping 19 matching lines...) Expand all Loading... |
154 SetStereoFrame(&dst_frame_, 0, 0, dst_sample_rate_hz); | 155 SetStereoFrame(&dst_frame_, 0, 0, dst_sample_rate_hz); |
155 if (src_channels == 1) | 156 if (src_channels == 1) |
156 SetStereoFrame(&golden_frame_, dst_left, dst_left, dst_sample_rate_hz); | 157 SetStereoFrame(&golden_frame_, dst_left, dst_left, dst_sample_rate_hz); |
157 else | 158 else |
158 SetStereoFrame(&golden_frame_, dst_left, dst_right, dst_sample_rate_hz); | 159 SetStereoFrame(&golden_frame_, dst_left, dst_right, dst_sample_rate_hz); |
159 } | 160 } |
160 | 161 |
161 // The sinc resampler has a known delay, which we compute here. Multiplying by | 162 // 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 // two gives us a crude maximum for any resampling, as the old resampler |
163 // typically (but not always) has lower delay. | 164 // typically (but not always) has lower delay. |
164 static const int kInputKernelDelaySamples = 16; | 165 static const size_t kInputKernelDelaySamples = 16; |
165 const int max_delay = static_cast<double>(dst_sample_rate_hz) | 166 const size_t max_delay = static_cast<size_t>( |
166 / src_sample_rate_hz * kInputKernelDelaySamples * dst_channels * 2; | 167 static_cast<double>(dst_sample_rate_hz) / src_sample_rate_hz * |
| 168 kInputKernelDelaySamples * dst_channels * 2); |
167 printf("(%d, %d Hz) -> (%d, %d Hz) ", // SNR reported on the same line later. | 169 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); | 170 src_channels, src_sample_rate_hz, dst_channels, dst_sample_rate_hz); |
169 if (function == TestRemixAndResample) { | 171 if (function == TestRemixAndResample) { |
170 RemixAndResample(src_frame_, &resampler, &dst_frame_); | 172 RemixAndResample(src_frame_, &resampler, &dst_frame_); |
171 } else { | 173 } else { |
172 int16_t mono_buffer[kMaxMonoDataSizeSamples]; | 174 int16_t mono_buffer[kMaxMonoDataSizeSamples]; |
173 DownConvertToCodecFormat(src_frame_.data_, | 175 DownConvertToCodecFormat(src_frame_.data_, |
174 src_frame_.samples_per_channel_, | 176 src_frame_.samples_per_channel_, |
175 src_frame_.num_channels_, | 177 src_frame_.num_channels_, |
176 src_frame_.sample_rate_hz_, | 178 src_frame_.sample_rate_hz_, |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 } | 256 } |
255 } | 257 } |
256 } | 258 } |
257 } | 259 } |
258 } | 260 } |
259 } | 261 } |
260 | 262 |
261 } // namespace | 263 } // namespace |
262 } // namespace voe | 264 } // namespace voe |
263 } // namespace webrtc | 265 } // namespace webrtc |
OLD | NEW |