annotate carfac/carfac_test.cc @ 647:749b5aed61f6

More #include cleanups.
author ronw@google.com
date Tue, 11 Jun 2013 21:32:50 +0000
parents e76951e4da20
children 1c2a5868f23a
rev   line source
alexbrandmeyer@626 1 //
alexbrandmeyer@626 2 // carfac_test.cc
alexbrandmeyer@626 3 // CARFAC Open Source C++ Library
alexbrandmeyer@626 4 //
alexbrandmeyer@626 5 // Created by Alex Brandmeyer on 5/22/13.
alexbrandmeyer@626 6 //
alexbrandmeyer@626 7 // This C++ file is part of an implementation of Lyon's cochlear model:
alexbrandmeyer@626 8 // "Cascade of Asymmetric Resonators with Fast-Acting Compression"
alexbrandmeyer@626 9 // to supplement Lyon's upcoming book "Human and Machine Hearing"
alexbrandmeyer@626 10 //
alexbrandmeyer@626 11 // Licensed under the Apache License, Version 2.0 (the "License");
alexbrandmeyer@626 12 // you may not use this file except in compliance with the License.
alexbrandmeyer@626 13 // You may obtain a copy of the License at
alexbrandmeyer@626 14 //
alexbrandmeyer@626 15 // http://www.apache.org/licenses/LICENSE-2.0
alexbrandmeyer@626 16 //
alexbrandmeyer@626 17 // Unless required by applicable law or agreed to in writing, software
alexbrandmeyer@626 18 // distributed under the License is distributed on an "AS IS" BASIS,
alexbrandmeyer@626 19 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
alexbrandmeyer@626 20 // See the License for the specific language governing permissions and
alexbrandmeyer@626 21 // limitations under the License.
alexbrandmeyer@626 22
ronw@647 23 #include "carfac.h"
ronw@647 24
ronw@646 25 #include <fstream>
alexbrandmeyer@636 26 #include <string>
alexbrandmeyer@640 27 #include <vector>
ronw@642 28
ronw@642 29 #include "gtest/gtest.h"
alexbrandmeyer@643 30
ronw@646 31 #include "agc.h"
alexbrandmeyer@643 32 #include "car.h"
ronw@647 33 #include "carfac_output.h"
alexbrandmeyer@643 34 #include "common.h"
ronw@646 35 #include "ihc.h"
alexbrandmeyer@637 36
alexbrandmeyer@636 37 using std::ifstream;
alexbrandmeyer@636 38 using std::ofstream;
ronw@646 39 using std::string;
ronw@646 40 using std::vector;
alexbrandmeyer@636 41
alexbrandmeyer@637 42 // This is the 'test_data' subdirectory of aimc/carfac that specifies where to
alexbrandmeyer@637 43 // locate the text files produced by 'CARFAC_GenerateTestData.m' for comparing
alexbrandmeyer@637 44 // the ouput of the Matlab version of CARFAC with this C++ version.
alexbrandmeyer@637 45 static const char* kTestSourceDir= "./test_data/";
alexbrandmeyer@643 46 // Here we specify the level to which the output should match (2 decimals).
alexbrandmeyer@643 47 static const float kPrecisionLevel = 1.0e-2;
ronw@630 48
alexbrandmeyer@626 49 // Three helper functions are defined here for loading the test data generated
alexbrandmeyer@626 50 // by the Matlab version of CARFAC.
alexbrandmeyer@643 51 // This loads one-dimensional ArrayXs from single-column text files.
ronw@646 52 void WriteNAPOutput(const CARFACOutput& output, const string filename,
ronw@646 53 int ear) {
alexbrandmeyer@637 54 string fullfile = kTestSourceDir + filename;
alexbrandmeyer@636 55 ofstream ofile(fullfile.c_str());
alexbrandmeyer@643 56 int32_t num_timepoints = output.nap().size();
alexbrandmeyer@637 57 int channels = output.nap()[0][0].size();
alexbrandmeyer@636 58 if (ofile.is_open()) {
alexbrandmeyer@643 59 for (int32_t i = 0; i < num_timepoints; ++i) {
alexbrandmeyer@636 60 for (int j = 0; j < channels; ++j) {
alexbrandmeyer@637 61 ofile << output.nap()[i][ear](j);
ronw@646 62 if (j < channels - 1) {
alexbrandmeyer@636 63 ofile << " ";
alexbrandmeyer@636 64 }
alexbrandmeyer@636 65 }
alexbrandmeyer@636 66 ofile << "\n";
alexbrandmeyer@636 67 }
alexbrandmeyer@636 68 }
alexbrandmeyer@636 69 ofile.close();
alexbrandmeyer@636 70 }
alexbrandmeyer@636 71
alexbrandmeyer@643 72 ArrayX LoadTestData(const string filename, const int number_points) {
alexbrandmeyer@637 73 string fullfile = kTestSourceDir + filename;
alexbrandmeyer@636 74 ifstream file(fullfile.c_str());
alexbrandmeyer@626 75 FPType myarray[number_points];
alexbrandmeyer@643 76 ArrayX output(number_points);
alexbrandmeyer@626 77 if (file.is_open()) {
alexbrandmeyer@626 78 for (int i = 0; i < number_points; ++i) {
alexbrandmeyer@626 79 file >> myarray[i];
alexbrandmeyer@626 80 output(i) = myarray[i];
alexbrandmeyer@626 81 }
alexbrandmeyer@626 82 }
alexbrandmeyer@636 83 file.close();
alexbrandmeyer@626 84 return output;
alexbrandmeyer@626 85 }
alexbrandmeyer@626 86
alexbrandmeyer@643 87 // This loads a vector of ArrayXs from multi-column text files.
alexbrandmeyer@643 88 vector<ArrayX> Load2dTestData(const string filename, const int rows,
alexbrandmeyer@626 89 const int columns) {
alexbrandmeyer@637 90 string fullfile = kTestSourceDir + filename;
alexbrandmeyer@636 91 ifstream file(fullfile.c_str());
alexbrandmeyer@626 92 FPType myarray[rows][columns];
alexbrandmeyer@643 93 vector<ArrayX> output;
alexbrandmeyer@626 94 output.resize(rows);
alexbrandmeyer@626 95 for (auto& timepoint : output) {
alexbrandmeyer@626 96 timepoint.resize(columns);
alexbrandmeyer@626 97 }
alexbrandmeyer@626 98 if (file.is_open()) {
alexbrandmeyer@626 99 for (int i = 0; i < rows; ++i) {
alexbrandmeyer@626 100 for (int j = 0; j < columns; ++j) {
alexbrandmeyer@626 101 file >> myarray[i][j];
alexbrandmeyer@626 102 output[i](j) = myarray[i][j];
alexbrandmeyer@626 103 }
alexbrandmeyer@626 104 }
alexbrandmeyer@626 105 }
alexbrandmeyer@636 106 file.close();
alexbrandmeyer@626 107 return output;
alexbrandmeyer@626 108 }
alexbrandmeyer@626 109
alexbrandmeyer@626 110 // This loads two dimensional vectors of audio data using data generated in
alexbrandmeyer@626 111 // Matlab using the wavread() function.
alexbrandmeyer@636 112 vector<vector<float>> Load2dAudioVector(string filename, int timepoints,
alexbrandmeyer@636 113 int channels) {
alexbrandmeyer@637 114 string fullfile = kTestSourceDir + filename;
alexbrandmeyer@636 115 ifstream file(fullfile.c_str());
alexbrandmeyer@636 116 vector<vector<float>> output;
alexbrandmeyer@626 117 output.resize(channels);
alexbrandmeyer@626 118 for (auto& channel : output) {
alexbrandmeyer@626 119 channel.resize(timepoints);
alexbrandmeyer@626 120 }
alexbrandmeyer@626 121 if (file.is_open()) {
alexbrandmeyer@626 122 for (int i = 0; i < timepoints; ++i) {
alexbrandmeyer@626 123 for (int j = 0; j < channels; ++j) {
alexbrandmeyer@626 124 file >> output[j][i];
alexbrandmeyer@626 125 }
alexbrandmeyer@626 126 }
alexbrandmeyer@626 127 }
alexbrandmeyer@636 128 file.close();
alexbrandmeyer@626 129 return output;
alexbrandmeyer@626 130 }
alexbrandmeyer@626 131
alexbrandmeyer@636 132 TEST(CARFACTest, Binaural_Output_test) {
alexbrandmeyer@643 133 int num_timepoints = 882;
alexbrandmeyer@643 134 int num_channels = 71;
alexbrandmeyer@643 135 int num_ears = 2;
alexbrandmeyer@637 136 string filename = "binaural_test_nap1.txt";
alexbrandmeyer@643 137 vector<ArrayX> nap1 = Load2dTestData(filename, num_timepoints, num_channels);
alexbrandmeyer@636 138 filename = "binaural_test_bm1.txt";
alexbrandmeyer@643 139 vector<ArrayX> bm1 = Load2dTestData(filename, num_timepoints, num_channels);
alexbrandmeyer@636 140 filename = "binaural_test_nap2.txt";
alexbrandmeyer@643 141 vector<ArrayX> nap2 = Load2dTestData(filename, num_timepoints, num_channels);
alexbrandmeyer@636 142 filename = "binaural_test_bm2.txt";
alexbrandmeyer@643 143 vector<ArrayX> bm2 = Load2dTestData(filename, num_timepoints, num_channels);
alexbrandmeyer@636 144 filename = "file_signal_binaural_test.txt";
alexbrandmeyer@643 145 vector<vector<float>> sound_data = Load2dAudioVector(filename, num_timepoints,
alexbrandmeyer@643 146 num_ears);
alexbrandmeyer@626 147 CARParams car_params;
alexbrandmeyer@636 148 IHCParams ihc_params;
alexbrandmeyer@636 149 AGCParams agc_params;
alexbrandmeyer@643 150 CARFAC mycf(num_ears, 22050, car_params, ihc_params, agc_params);
ronw@646 151 CARFACOutput my_output(true, true, false, false);
ronw@641 152 const bool kOpenLoop = false;
ronw@641 153 const int length = sound_data[0].size();
ronw@641 154 mycf.RunSegment(sound_data, 0, length, kOpenLoop, &my_output);
alexbrandmeyer@636 155 filename = "cpp_nap_output_1_binaural_test.txt";
alexbrandmeyer@636 156 WriteNAPOutput(my_output, filename, 0);
alexbrandmeyer@636 157 filename = "cpp_nap_output_2_binaural_test.txt";
alexbrandmeyer@636 158 WriteNAPOutput(my_output, filename, 1);
alexbrandmeyer@636 159 int ear = 0;
alexbrandmeyer@636 160 int n_ch = 71;
alexbrandmeyer@643 161 for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
alexbrandmeyer@636 162 for (int channel = 0; channel < n_ch; ++channel) {
alexbrandmeyer@637 163 FPType cplusplus = my_output.nap()[timepoint][ear](channel);
alexbrandmeyer@636 164 FPType matlab = nap1[timepoint](channel);
alexbrandmeyer@637 165 ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
alexbrandmeyer@637 166 cplusplus = my_output.bm()[timepoint][ear](channel);
alexbrandmeyer@636 167 matlab = bm1[timepoint](channel);
alexbrandmeyer@637 168 ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
alexbrandmeyer@636 169 }
alexbrandmeyer@626 170 }
alexbrandmeyer@636 171 ear = 1;
alexbrandmeyer@643 172 for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
alexbrandmeyer@636 173 for (int channel = 0; channel < n_ch; ++channel) {
alexbrandmeyer@637 174 FPType cplusplus = my_output.nap()[timepoint][ear](channel);
alexbrandmeyer@636 175 FPType matlab = nap2[timepoint](channel);
alexbrandmeyer@637 176 ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
alexbrandmeyer@637 177 cplusplus = my_output.bm()[timepoint][ear](channel);
alexbrandmeyer@636 178 matlab = bm2[timepoint](channel);
alexbrandmeyer@637 179 ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
alexbrandmeyer@626 180 }
alexbrandmeyer@626 181 }
alexbrandmeyer@626 182 }
alexbrandmeyer@626 183
alexbrandmeyer@636 184 TEST(CARFACTest, Long_Output_test) {
alexbrandmeyer@643 185 int num_timepoints = 2000;
alexbrandmeyer@643 186 int num_channels = 83;
alexbrandmeyer@643 187 int num_ears = 2;
alexbrandmeyer@636 188 string filename = "long_test_nap1.txt";
alexbrandmeyer@643 189 vector<ArrayX> nap1 = Load2dTestData(filename, num_timepoints, num_channels);
alexbrandmeyer@636 190 filename = "long_test_bm1.txt";
alexbrandmeyer@643 191 vector<ArrayX> bm1 = Load2dTestData(filename, num_timepoints, num_channels);
alexbrandmeyer@636 192 filename = "long_test_nap2.txt";
alexbrandmeyer@643 193 vector<ArrayX> nap2 = Load2dTestData(filename, num_timepoints, num_channels);
alexbrandmeyer@636 194 filename = "long_test_bm2.txt";
alexbrandmeyer@643 195 vector<ArrayX> bm2 = Load2dTestData(filename, num_timepoints, num_channels);
alexbrandmeyer@636 196 filename = "file_signal_long_test.txt";
alexbrandmeyer@643 197 vector<vector<float>> sound_data = Load2dAudioVector(filename, num_timepoints,
alexbrandmeyer@643 198 num_ears);
alexbrandmeyer@626 199 CARParams car_params;
alexbrandmeyer@626 200 IHCParams ihc_params;
alexbrandmeyer@626 201 AGCParams agc_params;
alexbrandmeyer@643 202 CARFAC mycf(num_ears, 44100, car_params, ihc_params, agc_params);
ronw@646 203 CARFACOutput my_output(true, true, false, false);
ronw@641 204 const bool kOpenLoop = false;
ronw@641 205 const int length = sound_data[0].size();
ronw@641 206 mycf.RunSegment(sound_data, 0, length, kOpenLoop, &my_output);
alexbrandmeyer@636 207 filename = "cpp_nap_output_1_long_test.txt";
alexbrandmeyer@636 208 WriteNAPOutput(my_output, filename, 0);
alexbrandmeyer@636 209 filename = "cpp_nap_output_2_long_test.txt";
alexbrandmeyer@636 210 WriteNAPOutput(my_output, filename, 1);
alexbrandmeyer@636 211 int ear = 0;
alexbrandmeyer@643 212 for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
alexbrandmeyer@643 213 for (int channel = 0; channel < num_channels; ++channel) {
alexbrandmeyer@637 214 FPType cplusplus = my_output.nap()[timepoint][ear](channel);
alexbrandmeyer@636 215 FPType matlab = nap1[timepoint](channel);
alexbrandmeyer@637 216 ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
alexbrandmeyer@637 217 cplusplus = my_output.bm()[timepoint][ear](channel);
alexbrandmeyer@636 218 matlab = bm1[timepoint](channel);
alexbrandmeyer@637 219 ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
alexbrandmeyer@636 220 }
alexbrandmeyer@626 221 }
alexbrandmeyer@636 222 ear = 1;
alexbrandmeyer@643 223 for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
alexbrandmeyer@643 224 for (int channel = 0; channel < num_channels; ++channel) {
alexbrandmeyer@637 225 FPType cplusplus = my_output.nap()[timepoint][ear](channel);
alexbrandmeyer@636 226 FPType matlab = nap2[timepoint](channel);
alexbrandmeyer@637 227 ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
alexbrandmeyer@637 228 cplusplus = my_output.bm()[timepoint][ear](channel);
alexbrandmeyer@636 229 matlab = bm2[timepoint](channel);
alexbrandmeyer@637 230 ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
alexbrandmeyer@626 231 }
alexbrandmeyer@626 232 }
ronw@646 233 }