diff carfac/carfac_test.cc @ 660:499ffd3a50ba

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 ae172177497d
children 7a0031c321da
line wrap: on
line diff
--- a/carfac/carfac_test.cc	Mon Jul 01 19:02:28 2013 +0000
+++ b/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);
 }