| 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 |