Index: webrtc/modules/audio_processing/high_pass_filter_bitexactness_unittest.cc |
diff --git a/webrtc/modules/audio_processing/high_pass_filter_bitexactness_unittest.cc b/webrtc/modules/audio_processing/high_pass_filter_bitexactness_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a212c5cdf539271f060fc2b94604f11e879becaa |
--- /dev/null |
+++ b/webrtc/modules/audio_processing/high_pass_filter_bitexactness_unittest.cc |
@@ -0,0 +1,206 @@ |
+/* |
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+#include <vector> |
+ |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "webrtc/base/scoped_ptr.h" |
+#include "webrtc/modules/audio_processing/audio_buffer.h" |
+#include "webrtc/modules/audio_processing/audio_processing_impl.h" |
+#include "webrtc/modules/audio_processing/high_pass_filter_impl.h" |
+#include "webrtc/modules/audio_processing/test/vector_based_audio_frame.h" |
+#include "webrtc/test/random.h" |
+ |
+namespace webrtc { |
+namespace { |
+ |
+const int kFrameLengthMs = 10; |
+const int kNumFramesConvergedTest = 5; |
+const int kReferenceLength = 10; |
+const float kComparisonTolerance = 1.0f / 32768.0f; |
+ |
+// Testvectors. |
+const float kReference8000InitMono[1][kReferenceLength] = { |
the sun
2015/12/10 12:03:53
Move these down locally, into the test cases.
peah-webrtc
2015/12/22 06:28:09
Done.
|
+ {0.927244f, 0.111148f, 0.824671f, 0.741569f, 0.661855f, 0.357463f, |
+ 0.534501f, 0.464797f, 0.398785f, -0.304901f}}; |
+const float kReference8000ConvergedMono[1][kReferenceLength] = { |
+ {0.087222f, 0.184210f, 0.166265f, 0.148991f, -0.251312f, -0.696716f, |
+ -0.248871f, 0.241462f, 0.221870f, -0.103943f}}; |
+const float kReference8000InitStereo[2][kReferenceLength] = { |
+ {0.927244f, 0.111148f, 0.824671f, 0.741569f, 0.661855f, 0.357463f, |
+ 0.534501f, 0.464797f, 0.398785f, -0.304901f}, |
+ {0.139164f, 0.914151f, 0.827479f, -0.142487f, 0.747337f, 0.094913f, |
+ 0.409925f, 0.255745f, 0.451918f, 0.062838f}}; |
+const float kReference8000ConvergedStereo[2][kReferenceLength] = { |
+ {0.353587f, 0.291604f, 0.306009f, -0.636810f, 0.343516f, -0.499390f, |
+ -0.343231f, 0.406812f, 0.055544f, 0.378124f}, |
+ {0.307932f, 0.282388f, 0.257607f, 0.063173f, 0.226539f, 0.203742f, |
+ -0.369110f, -0.585968f, 0.020997f, 0.265389f}}; |
+const float kReference16000InitMono[1][kReferenceLength] = { |
+ {0.979492f, 0.164037f, 0.924772f, 0.879910f, 0.835566f, 0.550707f, |
+ 0.759758f, 0.717124f, 0.675130f, -0.043640f}}; |
+const float kReference16000ConvergedMono[1][kReferenceLength] = { |
+ {0.287484f, 0.236702f, 0.264290f, -0.717865f, 0.284677f, -0.590240f, |
+ -0.451477f, 0.321879f, -0.030701f, 0.311777f}}; |
+const float kReference16000InitStereo[2][kReferenceLength] = { |
+ {0.979492f, 0.164037f, 0.924772f, 0.879910f, 0.835566f, 0.550707f, |
+ 0.759758f, 0.717124f, 0.675130f, -0.043640f}, |
+ {0.496658f, 0.956450f, 0.911252f, 0.866482f, 0.822260f, 0.414136f, |
+ 0.612018f, 0.460341f, 0.686392f, 0.645100f}}; |
+const float kReference16000ConvergedStereo[2][kReferenceLength] = { |
+ {0.248573f, 0.004273f, 0.232765f, -0.395172f, -0.732819f, -0.083557f, |
+ 0.270577f, 0.257454f, 0.244453f, 0.231635f}, |
+ {0.364727f, 0.350108f, 0.269601f, 0.324076f, 0.309641f, -0.149445f, |
+ 0.301798f, 0.287576f, -0.006104f, 0.272530f}}; |
+ |
+enum class ChannelsType { kMono, kStereo }; |
the sun
2015/12/10 12:03:53
I think this is quite unnecessary. The HPF takes a
peah-webrtc
2015/12/22 06:28:10
Done.
|
+ |
+// Test configuration. |
+struct TestConfig { |
+ TestConfig(int sample_rate, |
+ float tolerance, |
+ ChannelsType channels_type, |
+ const float ref_init[][kReferenceLength], |
+ const float ref_converged[][kReferenceLength]) |
+ : sample_rate(sample_rate), |
+ frame_length(sample_rate * kFrameLengthMs / 1000), |
+ tolerance(tolerance) { |
+ num_channels = (channels_type == ChannelsType::kMono ? 1 : 2); |
hlundin-webrtc
2015/12/10 12:12:16
Move num_channels to initializer list too.
peah-webrtc
2015/12/22 06:28:09
Done.
|
+ for (int ch = 0; ch < num_channels; ++ch) { |
+ memcpy(&reference_init[ch * kReferenceLength], &ref_init[ch][0], |
+ kReferenceLength * sizeof(reference_init[0])); |
+ memcpy(&reference_converged[ch * kReferenceLength], &ref_converged[ch][0], |
+ kReferenceLength * sizeof(reference_init[0])); |
+ } |
+ } |
+ |
+ int sample_rate; |
+ size_t frame_length; |
+ float tolerance; |
+ int num_channels; |
+ float reference_init[2 * kReferenceLength]; |
+ float reference_converged[2 * kReferenceLength]; |
+}; |
+ |
+// Main test class. |
+class HighPassFilterBitExactnessTest { |
+ public: |
+ HighPassFilterBitExactnessTest(TestConfig test_config) |
hlundin-webrtc
2015/12/10 12:12:16
explicit
peah-webrtc
2015/12/22 06:28:09
Done.
|
+ : test_config_(test_config), |
+ rand_gen_(42U), |
+ stream_config_(test_config_.sample_rate, |
+ test_config_.num_channels, |
+ false), |
+ audio_buffer_(new AudioBuffer(stream_config_.num_frames(), |
+ stream_config_.num_channels(), |
+ stream_config_.num_frames(), |
+ stream_config_.num_channels(), |
+ stream_config_.num_frames())), |
+ inputoutput_(test_config_.frame_length, test_config_.num_channels) { |
+ high_pass_filter_.reset(new HighPassFilterImpl(&crit_)); |
+ high_pass_filter_->Initialize(test_config_.num_channels, |
+ test_config_.sample_rate); |
+ high_pass_filter_->Enable(true); |
+ } |
+ |
+ void Run() { |
+ // Verify the initial frame. |
+ VerifyFrame(1, test_config_.reference_init, "init"); |
+ |
+ // Verify the results for a frame several frames into the processing. |
+ VerifyFrame(kNumFramesConvergedTest - 1, test_config_.reference_converged, |
+ "converged"); |
+ } |
+ |
+ private: |
+ // Processes a specified amoutn of frames, verifies the results and reports |
hlundin-webrtc
2015/12/10 12:12:17
amount
peah-webrtc
2015/12/22 06:28:09
Done.
|
+ // any errors. |
+ void VerifyFrame(int num_frames_to_process, |
+ const float* reference, |
+ std::string report_header) { |
hlundin-webrtc
2015/12/10 12:12:17
const std::string&
peah-webrtc
2015/12/22 06:28:10
Done.
|
+ for (int frame_no = 0; frame_no < num_frames_to_process; ++frame_no) { |
+ EXPECT_EQ(ProcessOneFrame(), AudioProcessing::kNoError); |
hlundin-webrtc
2015/12/10 12:12:16
Swap the parameters: AudioProcessing::kNoError, Pr
peah-webrtc
2015/12/22 06:28:09
Done.
|
+ } |
+ |
+ VectorBasedAudioFrame reference_frame(kReferenceLength, |
+ test_config_.num_channels, reference); |
+ bool result = |
hlundin-webrtc
2015/12/10 12:12:17
const bool
peah-webrtc
2015/12/22 06:28:09
Done.
|
+ inputoutput_.CompareTo(&reference_frame, test_config_.tolerance); |
+ |
+ if (!result) { |
+ printf( |
+ "Results difference: %s values test, sample rate: %d, number of " |
+ "channels: %d \n", |
+ report_header.c_str(), test_config_.sample_rate, |
+ test_config_.num_channels); |
+ PrintReferenceAndOutput(reference); |
+ } |
+ EXPECT_TRUE(result); |
+ } |
+ |
+ // Print out the values for the actual output and for a reference test vector. |
+ void PrintReferenceAndOutput(const float* reference) { |
the sun
2015/12/10 12:03:53
You should be able to use EXPECT_PRED_FORMAT2() fr
peah-webrtc
2015/12/22 06:28:10
Nice suggestion!
Done.
|
+ VectorBasedAudioFrame reference_frame(kReferenceLength, |
+ test_config_.num_channels, reference); |
+ printf("Expected: \n"); |
+ reference_frame.PrintValues(); |
+ printf("\n\nActual: \n"); |
+ inputoutput_.PrintValues(kReferenceLength); |
+ printf("\n"); |
+ } |
+ |
+ // Process one frame of data. |
+ int ProcessOneFrame() { |
+ inputoutput_.Randomize(&rand_gen_); |
the sun
2015/12/10 12:03:53
It's a bad idea to let the test output rely on the
peah-webrtc
2015/12/22 06:28:10
Good point!
Done.
|
+ inputoutput_.CopyToAudioBuffer(stream_config_, audio_buffer_.get()); |
+ high_pass_filter_->ProcessCaptureAudio(audio_buffer_.get()); |
+ inputoutput_.CopyFromAudioBuffer(stream_config_, audio_buffer_.get()); |
+ return AudioProcessing::kNoError; |
+ } |
+ |
+ const TestConfig test_config_; |
+ mutable test::Random rand_gen_; |
+ const StreamConfig stream_config_; |
+ rtc::scoped_ptr<AudioBuffer> audio_buffer_; |
the sun
2015/12/10 12:03:53
Don't need a scoped_ptr here, and not for high_pas
peah-webrtc
2015/12/22 06:28:09
Done.
|
+ VectorBasedAudioFrame inputoutput_; |
hlundin-webrtc
2015/12/10 12:12:16
input_output_
peah-webrtc
2015/12/22 06:28:09
Done.
|
+ mutable rtc::CriticalSection crit_; |
+ rtc::scoped_ptr<HighPassFilterImpl> high_pass_filter_; |
+}; |
+ |
+} // namespace |
+ |
+TEST(HighPassFilterBitExactnessTest, Mono8kHz) { |
+ HighPassFilterBitExactnessTest test( |
+ TestConfig(8000, kComparisonTolerance, ChannelsType::kMono, |
+ kReference8000InitMono, kReference8000ConvergedMono)); |
+ test.Run(); |
+} |
+ |
+TEST(HighPassFilterBitExactnessTest, Stereo8kHz) { |
+ HighPassFilterBitExactnessTest test( |
+ TestConfig(8000, kComparisonTolerance, ChannelsType::kStereo, |
+ kReference8000InitStereo, kReference8000ConvergedStereo)); |
+ test.Run(); |
+} |
+ |
+TEST(HighPassFilterBitExactnessTest, Mono16kHz) { |
+ HighPassFilterBitExactnessTest test( |
+ TestConfig(16000, kComparisonTolerance, ChannelsType::kMono, |
+ kReference16000InitMono, kReference16000ConvergedMono)); |
+ test.Run(); |
+} |
+ |
+TEST(HighPassFilterBitExactnessTest, Stereo16kHz) { |
+ HighPassFilterBitExactnessTest test( |
+ TestConfig(16000, kComparisonTolerance, ChannelsType::kStereo, |
+ kReference16000InitStereo, kReference16000ConvergedStereo)); |
+ test.Run(); |
+} |
+ |
+} // namespace webrtc |