| Index: third_party/openmax_dl/dl/sp/src/test/test_util.c
|
| diff --git a/third_party/openmax_dl/dl/sp/src/test/test_util.c b/third_party/openmax_dl/dl/sp/src/test/test_util.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..88d697b78135d792c069423846dd826c20eead1e
|
| --- /dev/null
|
| +++ b/third_party/openmax_dl/dl/sp/src/test/test_util.c
|
| @@ -0,0 +1,408 @@
|
| +/*
|
| + * 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 <stdio.h>
|
| +#include <stdlib.h>
|
| +#include <string.h>
|
| +#include <unistd.h>
|
| +
|
| +#include "dl/sp/api/armSP.h"
|
| +#include "dl/sp/src/test/compare.h"
|
| +
|
| +/*
|
| + * Test resuls 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_;
|
| +
|
| + /* The minimum SNR found for all of the tests */
|
| + float min_snr_;
|
| +};
|
| +
|
| +/*
|
| + * Return the program name, fur usage messages and debugging
|
| + */
|
| +char* ProgramName(char* argv0) {
|
| + char* slash = strrchr(argv0, '/');
|
| +
|
| + return slash ? slash + 1 : argv0;
|
| +}
|
| +
|
| +/*
|
| + * Print usage message for the command line options.
|
| + */
|
| +void usage(char* prog, int real_only, int max_fft_order, const char *summary) {
|
| + fprintf(stderr, "\n%s: [-hTFI] [-n logsize] [-s scale] [-g signal-type] "
|
| + "[-S signal value]\n\t\t[-v verbose] [-m minFFT] [-M maxFFT]\n",
|
| + ProgramName(prog));
|
| + fprintf(stderr, summary);
|
| + fprintf(stderr, " -h\t\tThis help\n");
|
| + fprintf(stderr, " -T\t\tIndividual test mode, otherwise run all tests\n");
|
| + fprintf(stderr, " -F\t\tDo not run forward FFT tests\n");
|
| + fprintf(stderr, " -I\t\tDo not run inverse FFT tests\n");
|
| + fprintf(stderr, " -m min\tMinium FFT order to test (default 2)\n");
|
| + fprintf(stderr, " -M min\tMaximum FFT order to test (default %d)\n",
|
| + max_fft_order);
|
| + fprintf(stderr, " -n logsize\tLog2 of FFT size\n");
|
| + fprintf(stderr, " -s scale\tScale factor for forward FFT (default = 0)\n");
|
| + fprintf(stderr, " -S signal\tBase value for the test signal "
|
| + "(default = 1024)\n");
|
| + fprintf(stderr, " -v level\tVerbose output level (default = 1)\n");
|
| + fprintf(stderr, " -g type\tInput signal type:\n");
|
| + fprintf(stderr, "\t\t 0 - Constant signal S + i*S. (Default value.)\n");
|
| + fprintf(stderr, "\t\t 1 - Real ramp starting at S/N, N = FFT size\n");
|
| + fprintf(stderr, "\t\t 2 - Sine wave of amplitude S\n");
|
| + if (!real_only)
|
| + fprintf(stderr, "\t\t 3 - Complex signal whose transform is a sine "
|
| + "wave.\n");
|
| + exit(0);
|
| +}
|
| +
|
| +/*
|
| + * Set default values for all command line options.
|
| + */
|
| +void SetDefaultOptions(struct Options* options, int real_only,
|
| + int max_fft_order) {
|
| + options->real_only_ = real_only;
|
| +
|
| + options->verbose_ = 1;
|
| +
|
| + /*
|
| + * Test mode options, defaulting to non-test mode
|
| + */
|
| + options->test_mode_ = 1;
|
| + options->do_forward_tests_ = 1;
|
| + options->do_inverse_tests_ = 1;
|
| + options->min_fft_order_ = 2;
|
| + options->max_fft_order_ = max_fft_order;
|
| +
|
| + /*
|
| + * Individual test options
|
| + */
|
| + options->fft_log_size_ = 4;
|
| + options->scale_factor_ = 0;
|
| + options->signal_type_ = 0;
|
| + options->signal_value_ = 1024;
|
| + options->signal_value_given_ = 0;
|
| +}
|
| +
|
| +/*
|
| + * Print values of command line options, for debugging.
|
| + */
|
| +void DumpOptions(FILE* f, const struct Options* options) {
|
| + fprintf(f, "real_only = %d\n", options->real_only_);
|
| + fprintf(f, "verbose = %d\n", options->verbose_);
|
| + fprintf(f, "test_mode = %d\n", options->test_mode_);
|
| + fprintf(f, "do_forward_tests = %d\n", options->do_forward_tests_);
|
| + fprintf(f, "do_inverse_tests = %d\n", options->do_inverse_tests_);
|
| + fprintf(f, "min_fft_order = %d\n", options->min_fft_order_);
|
| + fprintf(f, "max_fft_order = %d\n", options->max_fft_order_);
|
| + fprintf(f, "fft_log_size = %d\n", options->fft_log_size_);
|
| + fprintf(f, "scale_factor = %d\n", options->scale_factor_);
|
| + fprintf(f, "signal_type = %d\n", options->signal_type_);
|
| + fprintf(f, "signal_value = %g\n", options->signal_value_);
|
| + fprintf(f, "signal_value_given = %d\n", options->signal_value_given_);
|
| +}
|
| +
|
| +/*
|
| + * Process command line options, returning the values in |options|.
|
| + */
|
| +void ProcessCommandLine(struct Options *options, int argc, char* argv[],
|
| + const char* summary) {
|
| + int opt;
|
| + int max_fft_order = options->max_fft_order_;
|
| +
|
| + options->signal_value_given_ = 0;
|
| +
|
| + while ((opt = getopt(argc, argv, "hTFIn:s:S:g:v:m:M:")) != -1) {
|
| + switch (opt) {
|
| + case 'h':
|
| + usage(argv[0], options->real_only_, max_fft_order, summary);
|
| + break;
|
| + case 'T':
|
| + options->test_mode_ = 0;
|
| + break;
|
| + case 'F':
|
| + options->do_forward_tests_ = 0;
|
| + break;
|
| + case 'I':
|
| + options->do_inverse_tests_ = 0;
|
| + break;
|
| + case 'm':
|
| + options->min_fft_order_ = atoi(optarg);
|
| + break;
|
| + case 'M':
|
| + options->max_fft_order_ = atoi(optarg);
|
| + break;
|
| + case 'n':
|
| + options->fft_log_size_ = atoi(optarg);
|
| + break;
|
| + case 'S':
|
| + options->signal_value_ = atof(optarg);
|
| + options->signal_value_given_ = 1;
|
| + break;
|
| + case 's':
|
| + options->scale_factor_ = atoi(optarg);
|
| + break;
|
| + case 'g':
|
| + options->signal_type_ = atoi(optarg);
|
| + break;
|
| + case 'v':
|
| + options->verbose_ = atoi(optarg);
|
| + break;
|
| + default:
|
| + usage(argv[0], options->real_only_, max_fft_order, summary);
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| +/*
|
| + * Return true if the given test is known to fail. The array of known
|
| + * failures is in |knownFailures|. The FFT order is |fft_order|,
|
| + * |is_inverse_fft| is true, if the test fails for the inverse FFT
|
| + * (otherwise for forward FFT), and |signal_type| specifies the test
|
| + * signal used.
|
| + */
|
| +int IsKnownFailure(int fft_order, int is_inverse_fft, int signal_type,
|
| + struct KnownTestFailures* known_failures) {
|
| + if (known_failures) {
|
| + /*
|
| + * Look through array of known failures and see if an FFT
|
| + * (forward or inverse) of the given order and signal type
|
| + * matches. Return true if so.
|
| + */
|
| + while (known_failures->fft_order_ > 0) {
|
| + if ((fft_order == known_failures->fft_order_)
|
| + && (is_inverse_fft == known_failures->is_inverse_fft_test_)
|
| + && (signal_type == known_failures->signal_type_)) {
|
| + return 1;
|
| + }
|
| + ++known_failures;
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +/*
|
| + * 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;
|
| + 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 {
|
| + 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 {
|
| + 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)
|
| + printf(" (%d expected failures)\n", expected_failures);
|
| + printf(" (Minimum SNR = %.3f dB)\n", min_snr);
|
| +
|
| + result->failed_count_ = failures;
|
| + result->test_count_ = tests;
|
| + result->expected_failure_count_ = expected_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);
|
| +}
|
| +
|
| +/*
|
| + * 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.
|
| + */
|
| +void 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;
|
| +
|
| + 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(" Min forward SNR = %.3f dB, min inverse SNR = %.3f dB\n",
|
| + min_forward_snr,
|
| + min_inverse_snr);
|
| + } else {
|
| + printf("No tests run\n");
|
| + }
|
| +}
|
| +
|
| +/*
|
| + * Print the contents of an array to stdout, one element per line.
|
| + * |array_name| is the name of the array to be used in the header
|
| + * line.
|
| + *
|
| + * Arrays with elements of type OMX_S16, OMX_S32, OMX_SC32, OMX_F32,
|
| + * and OMX_FC32 are supported.
|
| + */
|
| +void DumpArrayReal16(const char* array_name, int count,
|
| + const OMX_S16* array) {
|
| + int n;
|
| +
|
| + printf("%4s\t%5s[n]\n", "n", array_name);
|
| + for (n = 0; n < count; ++n) {
|
| + printf("%4d\t%8d\n", n, array[n]);
|
| + }
|
| +}
|
| +
|
| +void DumpArrayReal32(const char* array_name, int count, const OMX_S32* array) {
|
| + int n;
|
| +
|
| + printf("%4s\t%5s[n]\n", "n", array_name);
|
| + for (n = 0; n < count; ++n) {
|
| + printf("%4d\t%8d\n", n, array[n]);
|
| + }
|
| +}
|
| +
|
| +void DumpArrayComplex32(const char* array_name, int count,
|
| + const OMX_SC32* array) {
|
| + int n;
|
| +
|
| + printf("%4s\t%10s.re[n]\t%10s.im[n]\n", "n", array_name);
|
| + for (n = 0; n < count; ++n) {
|
| + printf("%4d\t%16d\t%16d\n", n, array[n].Re, array[n].Im);
|
| + }
|
| +}
|
| +
|
| +void DumpArrayComplex16(const char* array_name, int count,
|
| + const OMX_SC16* array) {
|
| + int n;
|
| +
|
| + printf("%4s\t%10s.re[n]\t%10s.im[n]\n", "n", array_name);
|
| + for (n = 0; n < count; ++n) {
|
| + printf("%4d\t%16d\t%16d\n", n, array[n].Re, array[n].Im);
|
| + }
|
| +}
|
| +
|
| +void DumpArrayFloat(const char* array_name, int count, const OMX_F32* array) {
|
| + int n;
|
| +
|
| + printf("%4s\t%13s[n]\n", "n", array_name);
|
| + for (n = 0; n < count; ++n) {
|
| + printf("%4d\t%16g\n", n, array[n]);
|
| + }
|
| +}
|
| +
|
| +void DumpArrayComplexFloat(const char* array_name, int count,
|
| + const OMX_FC32* array) {
|
| + int n;
|
| +
|
| + printf("%4s\t%10s.re[n]\t%10s.im[n]\n", "n", array_name, array_name);
|
| + for (n = 0; n < count; ++n) {
|
| + printf("%4d\t%16g\t%16g\n", n, array[n].Re, array[n].Im);
|
| + }
|
| +}
|
|
|