Mercurial > hg > aimc
changeset 702:7acfa23cde23
Factor out common test utility functions and clean up carfac_test.
author | ronw@google.com |
---|---|
date | Mon, 01 Jul 2013 19:02:32 +0000 |
parents | bf89b122a683 |
children | 2bd09040ecf0 |
files | trunk/carfac/carfac_test.cc trunk/carfac/test_util.h |
diffstat | 2 files changed, 126 insertions(+), 104 deletions(-) [+] |
line wrap: on
line diff
--- a/trunk/carfac/carfac_test.cc Mon Jul 01 19:02:28 2013 +0000 +++ b/trunk/carfac/carfac_test.cc Mon Jul 01 19:02:32 2013 +0000 @@ -26,6 +26,8 @@ #include <string> #include <vector> +#include <Eigen/Core> + #include "gtest/gtest.h" #include "agc.h" @@ -33,75 +35,38 @@ #include "carfac_output.h" #include "common.h" #include "ihc.h" +#include "test_util.h" using std::deque; -using std::ifstream; using std::ofstream; using std::string; using std::vector; -// Location of the text files produced by 'CARFAC_GenerateTestData.m' for -// comparing the ouput of the Matlab implementation with the one used here. -static const char* kTestDataDir = "./test_data/"; +// Reads a two dimensional vector of audio data from a text file +// containing the output of the Matlab wavread() function. +vector<vector<float>> LoadAudio(const string& filename, int timepoints, + int num_channels) { + return LoadMatrix<vector<float>, false>(filename, timepoints, num_channels); +} // Writes the CARFAC NAP output to a text file. void WriteNAPOutput(const CARFACOutput& output, const string& filename, int ear) { string fullfile = kTestDataDir + filename; ofstream ofile(fullfile.c_str()); - ofile.precision(9); + const int kPrecision = 9; + ofile.precision(kPrecision); int32_t num_timepoints = output.nap().size(); int channels = output.nap()[0][0].size(); + Eigen::IOFormat ioformat(kPrecision, Eigen::DontAlignCols); if (ofile.is_open()) { for (int32_t i = 0; i < num_timepoints; ++i) { - for (int j = 0; j < channels; ++j) { - ofile << output.nap()[i][ear](j); - if (j < channels - 1) { - ofile << " "; - } - } - ofile << "\n"; + ofile << output.nap()[i][ear].transpose().format(ioformat) << std::endl; } } ofile.close(); } -// Reads a size rows vector of size columns Container objects from a -// multi-column text file generated by the Matlab version of CARFAC. -template <typename Container = ArrayX, bool ColMajor = true> -vector<Container> Load2dTestData(const string& filename, int rows, - int columns) { - string fullfile = kTestDataDir + filename; - ifstream file(fullfile.c_str()); - vector<Container> output; - if (ColMajor) { - output.assign(rows, Container(columns)); - } else { - output.assign(columns, Container(rows)); - } - if (file.is_open()) { - for (int i = 0; i < rows; ++i) { - for (int j = 0; j < columns; ++j) { - if (ColMajor) { - file >> output[i][j]; - } else { - file >> output[j][i]; - } - } - } - } - file.close(); - return output; -} - -// Reads a two dimensional vector of audio data from a text file -// containing the output of the Matlab wavread() function. -vector<vector<float>> Load2dAudioVector(string filename, int timepoints, - int num_channels) { - return Load2dTestData<vector<float>, false>(filename, timepoints, - num_channels); -} - class CARFACTest : public testing::Test { protected: deque<vector<ArrayX>> LoadTestData(const string& basename, @@ -111,7 +76,7 @@ deque<vector<ArrayX>> test_data(num_samples, vector<ArrayX>(num_ears)); for (int ear = 0; ear < num_ears; ++ear) { string filename = basename + std::to_string(ear + 1) + ".txt"; - vector<ArrayX> data = Load2dTestData(filename, num_samples, num_channels); + vector<ArrayX> data = LoadMatrix(filename, num_samples, num_channels); for (int i = 0; i < num_samples; ++i) { test_data[i][ear] = data[i]; } @@ -122,75 +87,62 @@ void AssertCARFACOutputNear(const deque<vector<ArrayX>>& expected, const deque<vector<ArrayX>>& actual, int num_samples, - int num_ears, - int num_channels) const { + int num_ears) const { for (int timepoint = 0; timepoint < num_samples; ++timepoint) { for (int ear = 0; ear < num_ears; ++ear) { - for (int channel = 0; channel < num_channels; ++channel) { - const float kPrecisionLevel = 1.0e-7; - ASSERT_NEAR(expected[timepoint][ear](channel), - actual[timepoint][ear](channel), - kPrecisionLevel); + const float kPrecisionLevel = 1.0e-7; + ASSERT_TRUE(ArraysNear(expected[timepoint][ear], + actual[timepoint][ear], + kPrecisionLevel)); } } - } } - CARParams car_params_; - IHCParams ihc_params_; - AGCParams agc_params_; + void RunCARFACAndCompareWithMatlab(const string& test_name, + int num_samples, + int num_ears, + int num_channels, + FPType sample_rate) const { + vector<vector<float>> sound_data = + LoadAudio(test_name + "-audio.txt", num_samples, num_ears); + + CARParams car_params; + IHCParams ihc_params; + AGCParams agc_params; + CARFAC carfac(num_ears, sample_rate, car_params, ihc_params, agc_params); + CARFACOutput output(true, true, false, false); + const bool kOpenLoop = false; + const int length = sound_data[0].size(); + carfac.RunSegment(sound_data, 0, length, kOpenLoop, &output); + + // TODO(ronw): Don't unconditionally overwrite files that are + // checked in to the repository on every test run. + WriteNAPOutput(output, test_name + "-cpp-nap1.txt", 0); + WriteNAPOutput(output, test_name + "-cpp-nap2.txt", 1); + + deque<vector<ArrayX>> expected_nap = LoadTestData( + test_name + "-matlab-nap", num_samples, num_ears, num_channels); + AssertCARFACOutputNear(expected_nap, output.nap(), num_samples, num_ears); + deque<vector<ArrayX>> expected_bm = LoadTestData( + test_name + "-matlab-bm", num_samples, num_ears, num_channels); + AssertCARFACOutputNear(expected_bm, output.bm(), num_samples, num_ears); + } }; -TEST_F(CARFACTest, BinauralData) { +TEST_F(CARFACTest, MatchesMatlabOnBinauralData) { const int kNumSamples = 882; const int kNumEars = 2; const int kNumChannels = 71; - vector<vector<float>> sound_data = - Load2dAudioVector("binaural_test-audio.txt", kNumSamples, kNumEars); - CARFAC carfac(kNumEars, 22050, car_params_, ihc_params_, agc_params_); - CARFACOutput output(true, true, false, false); - const bool kOpenLoop = false; - const int length = sound_data[0].size(); - carfac.RunSegment(sound_data, 0, length, kOpenLoop, &output); - - // TODO(ronw): Don't unconditionally overwrite files that are - // checked in to the repository on every test run. - WriteNAPOutput(output, "binaural_test-cpp-nap1.txt", 0); - WriteNAPOutput(output, "binaural_test-cpp-nap2.txt", 1); - - deque<vector<ArrayX>> expected_nap = LoadTestData( - "binaural_test-matlab-nap", kNumSamples, kNumEars, kNumChannels); - AssertCARFACOutputNear(expected_nap, output.nap(), - kNumSamples, kNumEars, kNumChannels); - deque<vector<ArrayX>> expected_bm = LoadTestData( - "binaural_test-matlab-bm", kNumSamples, kNumEars, kNumChannels); - AssertCARFACOutputNear(expected_bm, output.bm(), - kNumSamples, kNumEars, kNumChannels); + const FPType kSampleRate = 22050.0; + RunCARFACAndCompareWithMatlab( + "binaural_test", kNumSamples, kNumEars, kNumChannels, kSampleRate); } -TEST_F(CARFACTest, LongBinauralData) { +TEST_F(CARFACTest, MatchesMatlabOnLongBinauralData) { const int kNumSamples = 2000; const int kNumEars = 2; const int kNumChannels = 83; - vector<vector<float>> sound_data = - Load2dAudioVector("long_test-audio.txt", kNumSamples, kNumEars); - CARFAC carfac(kNumEars, 44100, car_params_, ihc_params_, agc_params_); - CARFACOutput output(true, true, false, false); - const bool kOpenLoop = false; - const int length = sound_data[0].size(); - carfac.RunSegment(sound_data, 0, length, kOpenLoop, &output); - - // TODO(ronw): Don't unconditionally overwrite files that are - // checked in to the repository on every test run. - WriteNAPOutput(output, "long_test-cpp-nap1.txt", 0); - WriteNAPOutput(output, "long_test-cpp-nap2.txt", 1); - - deque<vector<ArrayX>> expected_nap = LoadTestData( - "long_test-matlab-nap", kNumSamples, kNumEars, kNumChannels); - AssertCARFACOutputNear(expected_nap, output.nap(), - kNumSamples, kNumEars, kNumChannels); - deque<vector<ArrayX>> expected_bm = LoadTestData( - "long_test-matlab-bm", kNumSamples, kNumEars, kNumChannels); - AssertCARFACOutputNear(expected_bm, output.bm(), - kNumSamples, kNumEars, kNumChannels); + const FPType kSampleRate = 44100.0; + RunCARFACAndCompareWithMatlab( + "long_test", kNumSamples, kNumEars, kNumChannels, kSampleRate); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/carfac/test_util.h Mon Jul 01 19:02:32 2013 +0000 @@ -0,0 +1,70 @@ +// Copyright 2013, Google, Inc. +// Author: Ron Weiss <ronw@google.com> +// +// This C++ file is part of an implementation of Lyon's cochlear model: +// "Cascade of Asymmetric Resonators with Fast-Acting Compression" +// to supplement Lyon's upcoming book "Human and Machine Hearing" +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Shared test utilities. + +#ifndef CARFAC_TEST_UTIL_H +#define CARFAC_TEST_UTIL_H + +#include <fstream> +#include <string> +#include <vector> + +#include <Eigen/Core> + +#include "common.h" + +// Location of the text files produced by 'CARFAC_GenerateTestData.m' for +// comparing the ouput of the Matlab implementation with the C++ one. +static const char* kTestDataDir = "./test_data/"; + +// Reads a matrix (size rows vector of size columns Container objects) +// from a text file written using the Matlab dlmwrite function. +template <typename Container = ArrayX, bool ColMajor = true> +std::vector<Container> LoadMatrix(const std::string& filename, int rows, + int columns) { + std::string fullfile = kTestDataDir + filename; + std::ifstream file(fullfile.c_str()); + std::vector<Container> output; + if (ColMajor) { + output.assign(rows, Container(columns)); + } else { + output.assign(columns, Container(rows)); + } + if (file.is_open()) { + for (int i = 0; i < rows; ++i) { + for (int j = 0; j < columns; ++j) { + if (ColMajor) { + file >> output[i][j]; + } else { + file >> output[j][i]; + } + } + } + } + file.close(); + return output; +} + +bool ArraysNear(const ArrayX& expected, const ArrayX& actual, + double precision) { + return (expected - actual).cwiseAbs().maxCoeff() <= precision; +} + +#endif // CARFAC_TEST_UTIL_H