blob: 3deb0416b359ef942b20c5d2604e29d63426b4f3 [file] [log] [blame]
/*
* Copyright (c) 2013 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 "dl/sp/src/test/test_util.h"
#include "dl/sp/src/test/compare.h"
/*
* Test results from running either forward or inverse FFT tests
*/
struct TestResult {
/* Number of tests that failed */
int failed_count_;
/* Number of tests run */
int test_count_;
/* Number of tests that were expected to fail */
int expected_failure_count_;
/* Number of tests that were expected to fail but didn't */
int unexpected_pass_count_;
/* Number of tests that unexpectedly failed */
int unexpected_failure_count_;
/* The minimum SNR found for all of the tests */
float min_snr_;
};
/*
* Run one FFT test
*/
void TestOneFFT(int fft_log_size,
int signal_type,
float signal_value,
const struct TestInfo* info,
const char* message) {
struct SnrResult snr;
if (info->do_forward_tests_) {
RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr);
printf("Forward %s\n", message);
printf("SNR: real part %10.3f dB\n", snr.real_snr_);
printf(" imag part %10.3f dB\n", snr.imag_snr_);
printf(" complex part %10.3f dB\n", snr.complex_snr_);
}
if (info->do_inverse_tests_) {
RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr);
printf("Inverse %s\n", message);
if (info->real_only_) {
printf("SNR: real %10.3f dB\n", snr.real_snr_);
} else {
printf("SNR: real part %10.3f dB\n", snr.real_snr_);
printf(" imag part %10.3f dB\n", snr.imag_snr_);
printf(" complex part %10.3f dB\n", snr.complex_snr_);
}
}
}
/*
* Run a set of tests, printing out the result of each test.
*/
void RunTests(struct TestResult* result,
float (*test_function)(int, int, float, struct SnrResult*),
const char* id,
int is_inverse_test,
const struct TestInfo* info,
float snr_threshold) {
int fft_order;
int signal_type;
float snr;
int tests = 0;
int failures = 0;
int expected_failures = 0;
int unexpected_failures = 0;
int unexpected_passes = 0;
float min_snr = 1e10;
struct SnrResult snrResults;
for (fft_order = info->min_fft_order_; fft_order <= info->max_fft_order_;
++fft_order) {
for (signal_type = 0; signal_type < MaxSignalType(info->real_only_);
++signal_type) {
int known_failure = 0;
int test_failed = 0;
++tests;
snr = test_function(fft_order, signal_type, 1024.0, &snrResults);
if (snr < min_snr)
min_snr = snr;
known_failure = IsKnownFailure(fft_order, is_inverse_test,
signal_type, info->known_failures_);
if (snr < snr_threshold) {
++failures;
test_failed = 1;
if (known_failure) {
++expected_failures;
printf(" *FAILED: %s ", id);
} else {
++unexpected_failures;
printf("**FAILED: %s ", id);
}
} else {
test_failed = 0;
printf(" PASSED: %s ", id);
}
printf("order %2d signal %d: SNR = %9.3f",
fft_order, signal_type, snr);
if (known_failure) {
if (test_failed) {
printf(" (expected failure)");
} else {
++unexpected_passes;
printf(" (**Expected to fail, but passed)");
}
}
printf("\n");
}
}
printf("%sSummary: %d %s tests failed out of %d tests. "
"(Success rate %.2f%%.)\n",
failures ? "**" : "",
failures,
id,
tests,
(100.0 * (tests - failures)) / tests);
if (expected_failures || unexpected_passes || unexpected_failures) {
printf(" (%d expected failures)\n", expected_failures);
printf(" (%d unexpected failures)\n", unexpected_failures);
printf(" (%d unexpected passes)\n", unexpected_passes);
}
printf(" (Minimum SNR = %.3f dB)\n", min_snr);
result->failed_count_ = failures;
result->test_count_ = tests;
result->expected_failure_count_ = expected_failures;
result->unexpected_pass_count_ = unexpected_passes;
result->unexpected_failure_count_ = unexpected_failures;
result->min_snr_ = min_snr;
}
/*
* For all FFT orders and signal types, run the forward FFT.
* runOneForwardTest must be defined to compute the forward FFT and
* return the SNR beween the actual and expected FFT.
*
* Also finds the minium SNR from all of the tests and returns the
* minimum SNR value.
*/
void RunForwardTests(struct TestResult* result, const struct TestInfo* info,
float snr_threshold) {
RunTests(result, RunOneForwardTest, "FwdFFT", 0, info, snr_threshold);
}
void initializeTestResult(struct TestResult *result) {
result->failed_count_ = 0;
result->test_count_ = 0;
result->expected_failure_count_ = 0;
result->min_snr_ = 1000;
}
/*
* For all FFT orders and signal types, run the inverse FFT.
* runOneInverseTest must be defined to compute the forward FFT and
* return the SNR beween the actual and expected FFT.
*
* Also finds the minium SNR from all of the tests and returns the
* minimum SNR value.
*/
void RunInverseTests(struct TestResult* result, const struct TestInfo* info,
float snr_threshold) {
RunTests(result, RunOneInverseTest, "InvFFT", 1, info, snr_threshold);
}
/*
* Run all forward and inverse FFT tests, printing a summary of the
* results.
*/
int RunAllTests(const struct TestInfo* info) {
int failed;
int total;
float min_forward_snr;
float min_inverse_snr;
struct TestResult forward_results;
struct TestResult inverse_results;
initializeTestResult(&forward_results);
initializeTestResult(&inverse_results);
if (info->do_forward_tests_)
RunForwardTests(&forward_results, info, info->forward_threshold_);
if (info->do_inverse_tests_)
RunInverseTests(&inverse_results, info, info->inverse_threshold_);
failed = forward_results.failed_count_ + inverse_results.failed_count_;
total = forward_results.test_count_ + inverse_results.test_count_;
min_forward_snr = forward_results.min_snr_;
min_inverse_snr = inverse_results.min_snr_;
if (total) {
printf("%sTotal: %d tests failed out of %d tests. "
"(Success rate = %.2f%%.)\n",
failed ? "**" : "",
failed,
total,
(100.0 * (total - failed)) / total);
if (forward_results.expected_failure_count_
+ inverse_results.expected_failure_count_) {
printf(" (%d expected failures)\n",
forward_results.expected_failure_count_
+ inverse_results.expected_failure_count_);
printf(" (%d unexpected failures)\n",
forward_results.unexpected_failure_count_
+ inverse_results.unexpected_failure_count_);
printf(" (%d unexpected passes)\n",
forward_results.unexpected_pass_count_
+ inverse_results.unexpected_pass_count_);
}
printf(" Min forward SNR = %.3f dB, min inverse SNR = %.3f dB\n",
min_forward_snr,
min_inverse_snr);
} else {
printf("No tests run\n");
}
return failed;
}