Revision: 309
Author:
ro...@google.com
Date: Mon Jul 1 12:02:32 2013
Log: Factor out common test utility functions and clean up carfac_test.
http://code.google.com/p/aimc/source/detail?r=309
Added:
/trunk/carfac/test_util.h
Modified:
/trunk/carfac/carfac_test.cc
=======================================
--- /dev/null
+++ /trunk/carfac/test_util.h Mon Jul 1 12:02:32 2013
@@ -0,0 +1,70 @@
+// Copyright 2013, Google, Inc.
+// Author: Ron Weiss <
ro...@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
=======================================
--- /trunk/carfac/carfac_test.cc Thu Jun 27 15:28:34 2013
+++ /trunk/carfac/carfac_test.cc Mon Jul 1 12:02:32 2013
@@ -26,6 +26,8 @@
#include <string>
#include <vector>
+#include <Eigen/Core>
+
#include "gtest/gtest.h"
#include "agc.h"
@@ -33,74 +35,37 @@
#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:
@@ -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);
}