changeset 685:d0612798f6de

Additional changes to C++ CARFAC on the basis of ronw's comments on r289. Moved CARFAC::Design to CARFAC::CARFAC and CARFAC::Reset(), moved carfac_common.h to common.h, CARFACDetect to carfac_util.h/cc, FloatArray and Float2dArray to ArrayX and ArrayXX, improved variable naming, made a start on improved commenting documentation.
author alexbrandmeyer
date Tue, 04 Jun 2013 18:30:22 +0000
parents 49af9a8d5a53
children c3012b2943b2
files trunk/carfac/SConstruct trunk/carfac/agc.h trunk/carfac/agc_coeffs.h trunk/carfac/agc_params.h trunk/carfac/agc_state.h trunk/carfac/car.h trunk/carfac/car_coeffs.h trunk/carfac/car_params.h trunk/carfac/car_state.h trunk/carfac/carfac.cc trunk/carfac/carfac.h trunk/carfac/carfac_common.cc trunk/carfac/carfac_common.h trunk/carfac/carfac_output.cc trunk/carfac/carfac_output.h trunk/carfac/carfac_test.cc trunk/carfac/carfac_util.cc trunk/carfac/carfac_util.h trunk/carfac/common.h trunk/carfac/ear.cc trunk/carfac/ear.h trunk/carfac/ihc.h trunk/carfac/ihc_coeffs.h trunk/carfac/ihc_params.h trunk/carfac/ihc_state.h trunk/carfac/sai.cc trunk/carfac/sai.h trunk/carfac/sai_test.cc
diffstat 28 files changed, 729 insertions(+), 876 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/carfac/SConstruct	Fri May 31 21:46:48 2013 +0000
+++ b/trunk/carfac/SConstruct	Tue Jun 04 18:30:22 2013 +0000
@@ -51,20 +51,15 @@
   env.MergeFlags(['-std=c++11'])
 
 carfac_sources = [
-    'agc_coeffs.h',
-    'agc_params.h',
-    'agc_state.h',
-    'car_coeffs.h',
+    'agc.h',
+    'car.h',
+    'ihc.h',
     'carfac.cc',
-    'carfac_common.cc',
+    'common.h',
+    'carfac_util.h',
     'carfac_output.cc',
-    'car_params.h',
-    'car_state.h',
     'ear.cc',
-    'ihc_coeffs.h',
-    'ihc_params.h',
-    'ihc_state.h',
-    'sai.cc',
+    'sai.cc'
     ]
 env.Library(target = 'carfac', source = carfac_sources)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/carfac/agc.h	Tue Jun 04 18:30:22 2013 +0000
@@ -0,0 +1,80 @@
+//
+//  agc.h
+//  CARFAC Open Source C++ Library
+//
+//  Created by Alex Brandmeyer on 5/30/13.
+//
+// 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.
+
+#ifndef CARFAC_AGC_H
+#define CARFAC_AGC_H
+
+#include <vector>
+#include "common.h"
+
+struct AGCParams {
+  AGCParams() {
+    num_stages = 4;
+    agc_stage_gain = 2.0;
+    time_constants.resize(num_stages);
+    agc1_scales.resize(num_stages);
+    agc2_scales.resize(num_stages);
+    agc1_scales[0] = 1.0;
+    agc2_scales[0] = 1.65;
+    time_constants[0] = 0.002;
+    for (int i = 1; i < num_stages; ++i) {
+      agc1_scales[i] = agc1_scales[i - 1] * sqrt(2.0);
+      agc2_scales[i] = agc2_scales[i - 1] * sqrt(2.0);
+      time_constants[i] = time_constants[i - 1] * 4.0;
+    }
+    decimation = {8, 2, 2, 2};
+    agc_mix_coeff = 0.5;
+  }
+  int num_stages;
+  FPType agc_stage_gain;
+  FPType agc_mix_coeff;
+  std::vector<FPType> time_constants;
+  std::vector<int> decimation;
+  std::vector<FPType> agc1_scales;
+  std::vector<FPType> agc2_scales;
+};
+
+struct AGCCoeffs {
+  int num_agc_stages;
+  FPType agc_stage_gain;
+  FPType agc_epsilon;
+  int decimation;
+  FPType agc_pole_z1;
+  FPType agc_pole_z2;
+  int agc_spatial_iterations;
+  FPType agc_spatial_fir_left;
+  FPType agc_spatial_fir_mid;
+  FPType agc_spatial_fir_right;
+  int agc_spatial_n_taps;
+  FPType agc_mix_coeffs;
+  FPType agc_gain;
+  FPType detect_scale;
+  FPType decim;
+};
+
+struct AGCState {
+  ArrayX agc_memory;
+  ArrayX input_accum;
+  int decim_phase;
+};
+
+#endif  // CARFAC_AGC_H
\ No newline at end of file
--- a/trunk/carfac/agc_coeffs.h	Fri May 31 21:46:48 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-//
-//  agc_coeffs.h
-//  CARFAC Open Source C++ Library
-//
-//  Created by Alex Brandmeyer on 5/10/13.
-//
-// 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.
-
-#ifndef CARFAC_AGC_COEFFS_H
-#define CARFAC_AGC_COEFFS_H
-
-#include "carfac_common.h"
-
-struct AGCCoeffs {
-  int n_agc_stages;
-  FPType agc_stage_gain;
-  FPType agc_epsilon;
-  int decimation;
-  FPType agc_pole_z1;
-  FPType agc_pole_z2;
-  int agc_spatial_iterations;
-  FPType agc_spatial_fir_left;
-  FPType agc_spatial_fir_mid;
-  FPType agc_spatial_fir_right;
-  int agc_spatial_n_taps;
-  FPType agc_mix_coeffs;
-  FPType agc_gain;
-  FPType detect_scale;
-  FPType decim;
-};
-
-#endif  // CARFAC_AGC_COEFFS_H
\ No newline at end of file
--- a/trunk/carfac/agc_params.h	Fri May 31 21:46:48 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-//
-//  agc_params.h
-//  CARFAC Open Source C++ Library
-//
-//  Created by Alex Brandmeyer on 5/10/13.
-//
-// 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.
-
-#ifndef CARFAC_AGC_PARAMS_H
-#define CARFAC_AGC_PARAMS_H
-
-#include <vector>
-#include "carfac_common.h"
-
-struct AGCParams {
-  AGCParams() {
-    n_stages = 4;
-    agc_stage_gain = 2.0;
-    time_constants.resize(n_stages);
-    agc1_scales.resize(n_stages);
-    agc2_scales.resize(n_stages);
-    agc1_scales[0] = 1.0;
-    agc2_scales[0] = 1.65;
-    time_constants[0] = 0.002;
-    for (int i = 1; i < n_stages; ++i) {
-      agc1_scales[i] = agc1_scales[i - 1] * sqrt(2.0);
-      agc2_scales[i] = agc2_scales[i - 1] * sqrt(2.0);
-      time_constants[i] = time_constants[i - 1] * 4.0;
-    }
-    decimation = {8, 2, 2, 2};
-    agc_mix_coeff = 0.5;
-  }
-  int n_stages;
-  FPType agc_stage_gain;
-  FPType agc_mix_coeff;
-  std::vector<FPType> time_constants;
-  std::vector<int> decimation;
-  std::vector<FPType> agc1_scales;
-  std::vector<FPType> agc2_scales;
-};
-
-#endif  // CARFAC_AGC_PARAMS_H
\ No newline at end of file
--- a/trunk/carfac/agc_state.h	Fri May 31 21:46:48 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-//
-//  agc_state.h
-//  CARFAC Open Source C++ Library
-//
-//  Created by Alex Brandmeyer on 5/10/13.
-//
-// 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.
-
-#ifndef CARFAC_AGC_STATE_H
-#define CARFAC_AGC_STATE_H
-
-#include "carfac_common.h"
-
-struct AGCState {
-  int n_ch;
-  FloatArray agc_memory;
-  FloatArray input_accum;
-  int decim_phase;
-};
-
-#endif  // CARFAC_AGC_STATE_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/carfac/car.h	Tue Jun 04 18:30:22 2013 +0000
@@ -0,0 +1,86 @@
+//
+//  car.h
+//  CARFAC Open Source C++ Library
+//
+//  Created by Alex Brandmeyer on 5/10/13.
+//
+// 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.
+
+#ifndef CARFAC_CAR_H
+#define CARFAC_CAR_H
+
+#include "common.h"
+
+// A CARParams structure stores the necessary information needed by a CARFAC
+// object to design the set of coefficients implementing 'The Cascade of
+// Asymmetric Resonators' described in the chapter of the same name in Lyon's
+// book "Human and Machine Hearing". 
+struct CARParams {
+  // The constructor initializes using default parameter values.
+  CARParams() {
+    velocity_scale = 0.1;
+    v_offset = 0.04;
+    min_zeta = 0.1;
+    max_zeta = 0.35;
+    first_pole_theta = 0.85 * kPi;
+    zero_ratio = sqrt(2.0);
+    high_f_damping_compression = 0.5;
+    erb_per_step = 0.5;
+    min_pole_hz = 30;
+    erb_break_freq = 165.3;  // This is the Greenwood map's break frequency.
+    // This represents Glassberg and Moore's high-cf ratio.
+    erb_q = 1000/(24.7*4.37);
+  };
+  FPType velocity_scale; // This is used for the velocity nonlinearity.
+  FPType v_offset;  // The offset gives us quadratic part.
+  FPType min_zeta;  // This is the minimum damping factor in mid-freq channels.
+  FPType max_zeta;  // This is the maximum damping factor in mid-freq channels.
+  FPType first_pole_theta;
+  FPType zero_ratio;  // This is how far zero is above the pole.
+  FPType high_f_damping_compression;  // A range from 0 to 1 to compress theta.
+  FPType erb_per_step;
+  FPType min_pole_hz;
+  FPType erb_break_freq;
+  FPType erb_q;
+};
+
+// The CAR coefficients are designed by the CARFAC::DesignCARCoeffs method,
+// which is called during initial construction and resetting of a CARFAC object.
+struct CARCoeffs {
+  FPType velocity_scale;
+  FPType v_offset;
+  ArrayX r1_coeffs;
+  ArrayX a0_coeffs;
+  ArrayX c0_coeffs;
+  ArrayX h_coeffs;
+  ArrayX g0_coeffs;
+  ArrayX zr_coeffs;
+};
+
+
+struct CARState {
+  ArrayX z1_memory;
+  ArrayX z2_memory;
+  ArrayX za_memory;
+  ArrayX zb_memory;
+  ArrayX dzb_memory;
+  ArrayX zy_memory;
+  ArrayX g_memory;
+  ArrayX dg_memory;
+};
+
+#endif  // CARFAC_CAR_H
\ No newline at end of file
--- a/trunk/carfac/car_coeffs.h	Fri May 31 21:46:48 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-//
-//  car_coeffs.h
-//  CARFAC Open Source C++ Library
-//
-//  Created by Alex Brandmeyer on 5/10/13.
-//
-// 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.
-
-#ifndef CARFAC_CAR_COEFFS_H
-#define CARFAC_CAR_COEFFS_H
-
-#include "carfac_common.h"
-
-struct CARCoeffs {
-  int n_ch;
-  FPType velocity_scale;
-  FPType v_offset;
-  FloatArray r1_coeffs;
-  FloatArray a0_coeffs;
-  FloatArray c0_coeffs;
-  FloatArray h_coeffs;
-  FloatArray g0_coeffs;
-  FloatArray zr_coeffs;
-};
-
-#endif  // CARFAC_CAR_COEFFS_H
\ No newline at end of file
--- a/trunk/carfac/car_params.h	Fri May 31 21:46:48 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-//
-//  car_params.h
-//  CARFAC Open Source C++ Library
-//
-//  Created by Alex Brandmeyer on 5/10/13.
-//
-// 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.
-
-#ifndef CARFAC_CAR_PARAMS_H
-#define CARFAC_CAR_PARAMS_H
-
-#include "carfac_common.h"
-
-struct CARParams {
-  // The constructor initializes using default parameter values.
-  CARParams() {
-    velocity_scale = 0.1;
-    v_offset = 0.04;
-    min_zeta = 0.1;
-    max_zeta = 0.35;
-    first_pole_theta = 0.85 * kPi;
-    zero_ratio = sqrt(2.0);
-    high_f_damping_compression = 0.5;
-    erb_per_step = 0.5;
-    min_pole_hz = 30;
-    erb_break_freq = 165.3;  // This is the Greenwood map's break frequency.
-    // This represents Glassberg and Moore's high-cf ratio.
-    erb_q = 1000/(24.7*4.37);
-  };
-  FPType velocity_scale; // This is used for the velocity nonlinearity.
-  FPType v_offset;  // The offset gives us quadratic part.
-  FPType min_zeta;  // This is the minimum damping factor in mid-freq channels.
-  FPType max_zeta;  // This is the maximum damping factor in mid-freq channels.
-  FPType first_pole_theta;
-  FPType zero_ratio;  // This is how far zero is above the pole.
-  FPType high_f_damping_compression;  // A range from 0 to 1 to compress theta.
-  FPType erb_per_step;
-  FPType min_pole_hz;
-  FPType erb_break_freq;
-  FPType erb_q;
-};
-
-#endif  // CARFAC_CAR_PARAMS_H
\ No newline at end of file
--- a/trunk/carfac/car_state.h	Fri May 31 21:46:48 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-//
-//  car_state.h
-//  CARFAC Open Source C++ Library
-//
-//  Created by Alex Brandmeyer on 5/10/13.
-//
-// 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.
-
-#ifndef CARFAC_CAR_STATE_H
-#define CARFAC_CAR_STATE_H
-
-#include "carfac_common.h"
-
-struct CARState {
-  FloatArray z1_memory;
-  FloatArray z2_memory;
-  FloatArray za_memory;
-  FloatArray zb_memory;
-  FloatArray dzb_memory;
-  FloatArray zy_memory;
-  FloatArray g_memory;
-  FloatArray dg_memory;
-};
-
-#endif  // CARFAC_CAR_STATE_H
\ No newline at end of file
--- a/trunk/carfac/carfac.cc	Fri May 31 21:46:48 2013 +0000
+++ b/trunk/carfac/carfac.cc	Tue Jun 04 18:30:22 2013 +0000
@@ -21,41 +21,49 @@
 // limitations under the License.
 
 #include <assert.h>
+
 #include "carfac.h"
+
 using std::vector;
 
-void CARFAC::Design(const int n_ears, const FPType fs,
+CARFAC::CARFAC(const int num_ears, const FPType sample_rate,
                     const CARParams& car_params, const IHCParams& ihc_params,
                     const AGCParams& agc_params) {
-  n_ears_ = n_ears;
-  fs_ = fs;
-  ears_.resize(n_ears_);
-  n_ch_ = 0;
-  FPType pole_hz = car_params.first_pole_theta * fs / (2 * kPi);
-  while (pole_hz > car_params.min_pole_hz) {
-    ++n_ch_;
-    pole_hz = pole_hz - car_params.erb_per_step *
-    ERBHz(pole_hz, car_params.erb_break_freq, car_params.erb_q);
+  num_ears_ = num_ears;
+  sample_rate_ = sample_rate;
+  ears_.resize(num_ears_);
+  car_params_ = car_params;
+  ihc_params_ = ihc_params;
+  agc_params_ = agc_params;
+  Reset();
+}
+
+void CARFAC::Reset() {
+  num_channels_ = 0;
+  FPType pole_hz = car_params_.first_pole_theta * sample_rate_ / (2 * kPi);
+  while (pole_hz > car_params_.min_pole_hz) {
+    ++num_channels_;
+    pole_hz = pole_hz - car_params_.erb_per_step *
+    ERBHz(pole_hz, car_params_.erb_break_freq, car_params_.erb_q);
   }
-  pole_freqs_.resize(n_ch_);
-  pole_hz = car_params.first_pole_theta * fs / (2 * kPi);
-  for (int ch = 0; ch < n_ch_; ++ch) {
-    pole_freqs_(ch) = pole_hz;
-    pole_hz = pole_hz - car_params.erb_per_step *
-    ERBHz(pole_hz, car_params.erb_break_freq, car_params.erb_q);
+  pole_freqs_.resize(num_channels_);
+  pole_hz = car_params_.first_pole_theta * sample_rate_ / (2 * kPi);
+  for (int channel = 0; channel < num_channels_; ++channel) {
+    pole_freqs_(channel) = pole_hz;
+    pole_hz = pole_hz - car_params_.erb_per_step *
+    ERBHz(pole_hz, car_params_.erb_break_freq, car_params_.erb_q);
   }
   max_channels_per_octave_ = log(2) / log(pole_freqs_(0) / pole_freqs_(1));
   CARCoeffs car_coeffs;
   IHCCoeffs ihc_coeffs;
   std::vector<AGCCoeffs> agc_coeffs;
-  DesignCARCoeffs(car_params, fs, pole_freqs_, &car_coeffs);
-  DesignIHCCoeffs(ihc_params, fs, &ihc_coeffs);
+  DesignCARCoeffs(car_params_, sample_rate_, pole_freqs_, &car_coeffs);
+  DesignIHCCoeffs(ihc_params_, sample_rate_, &ihc_coeffs);
   // This code initializes the coefficients for each of the AGC stages.
-  DesignAGCCoeffs(agc_params, fs, &agc_coeffs);
+  DesignAGCCoeffs(agc_params_, sample_rate_, &agc_coeffs);
   // Once we have the coefficient structure we can design the ears.
   for (auto& ear : ears_) {
-    ear.InitEar(n_ch_, fs_, car_coeffs, ihc_coeffs,
-                agc_coeffs);
+    ear.Init(num_channels_, car_coeffs, ihc_coeffs, agc_coeffs);
   }
 }
 
@@ -65,21 +73,22 @@
   // A nested loop structure is used to iterate through the individual samples
   // for each ear (audio channel).
   bool updated;  // This variable is used by the AGC stage.
-  for (int32_t i = 0; i < length; ++i) {
-    for (int j = 0; j < n_ears_; ++j) {
+  for (int32_t timepoint = 0; timepoint < length; ++timepoint) {
+    for (int audio_channel = 0; audio_channel < num_ears_; ++audio_channel) {
       // First we create a reference to the current Ear object.
-      Ear& ear = ears_[j];
+      Ear& ear = ears_[audio_channel];
       // This stores the audio sample currently being processed.
-      FPType input = sound_data[j][start+i];
+      FPType input = sound_data[audio_channel][start + timepoint];
+      
       // Now we apply the three stages of the model in sequence to the current
       // audio sample.
       ear.CARStep(input);
       ear.IHCStep(ear.car_out());
       updated = ear.AGCStep(ear.ihc_out());
     }
-    seg_output->StoreOutput(ears_);
+    seg_output->AppendOutput(ears_);
     if (updated) {
-      if (n_ears_ > 1) {
+      if (num_ears_ > 1) {
         CrossCouple();
       }
       if (! open_loop) {
@@ -90,19 +99,19 @@
 }
 
 void CARFAC::CrossCouple() {
-  for (int stage = 0; stage < ears_[0].agc_nstages(); ++stage) {
+  for (int stage = 0; stage < ears_[0].agc_num_stages(); ++stage) {
     if (ears_[0].agc_decim_phase(stage) > 0) {
       break;
     } else {
       FPType mix_coeff = ears_[0].agc_mix_coeff(stage);
       if (mix_coeff > 0) {
-        FloatArray stage_state;
-        FloatArray this_stage_values = FloatArray::Zero(n_ch_);
+        ArrayX stage_state;
+        ArrayX this_stage_values = ArrayX::Zero(num_channels_);
         for (auto& ear : ears_) {
           stage_state = ear.agc_memory(stage);
           this_stage_values += stage_state;
         }
-        this_stage_values /= n_ears_;
+        this_stage_values /= num_ears_;
         for (auto& ear : ears_) {
           stage_state = ear.agc_memory(stage);
           ear.set_agc_memory(stage, stage_state + mix_coeff *
@@ -115,7 +124,7 @@
 
 void CARFAC::CloseAGCLoop() {
   for (auto& ear: ears_) {
-    FloatArray undamping = 1 - ear.agc_memory(0);
+    ArrayX undamping = 1 - ear.agc_memory(0);
     // This updates the target stage gain for the new damping.
     ear.set_dzb_memory((ear.zr_coeffs() * undamping - ear.zb_memory()) /
                        ear.agc_decimation(0));
@@ -124,51 +133,52 @@
   }
 }
 
-void CARFAC::DesignCARCoeffs(const CARParams& car_params, const FPType fs,
-                             const FloatArray& pole_freqs,
+void CARFAC::DesignCARCoeffs(const CARParams& car_params,
+                             const FPType sample_rate,
+                             const ArrayX& pole_freqs,
                              CARCoeffs* car_coeffs) {
-  n_ch_ = pole_freqs.size();
+  num_channels_ = pole_freqs.size();
   car_coeffs->velocity_scale = car_params.velocity_scale;
   car_coeffs->v_offset = car_params.v_offset;
-  car_coeffs->r1_coeffs.resize(n_ch_);
-  car_coeffs->a0_coeffs.resize(n_ch_);
-  car_coeffs->c0_coeffs.resize(n_ch_);
-  car_coeffs->h_coeffs.resize(n_ch_);
-  car_coeffs->g0_coeffs.resize(n_ch_);
+  car_coeffs->r1_coeffs.resize(num_channels_);
+  car_coeffs->a0_coeffs.resize(num_channels_);
+  car_coeffs->c0_coeffs.resize(num_channels_);
+  car_coeffs->h_coeffs.resize(num_channels_);
+  car_coeffs->g0_coeffs.resize(num_channels_);
   FPType f = car_params.zero_ratio * car_params.zero_ratio - 1.0;
-  FloatArray theta = pole_freqs * ((2.0 * kPi) / fs);
+  ArrayX theta = pole_freqs * ((2.0 * kPi) / sample_rate);
   car_coeffs->c0_coeffs = theta.sin();
   car_coeffs->a0_coeffs = theta.cos();
   FPType ff = car_params.high_f_damping_compression;
-  FloatArray x = theta / kPi;
+  ArrayX x = theta / kPi;
   car_coeffs->zr_coeffs = kPi * (x - (ff * (x*x*x)));
   FPType max_zeta = car_params.max_zeta;
   FPType min_zeta = car_params.min_zeta;
   car_coeffs->r1_coeffs = (1.0 - (car_coeffs->zr_coeffs * max_zeta));
-  FloatArray erb_freqs(n_ch_);
-  for (int ch=0; ch < n_ch_; ++ch) {
-    erb_freqs(ch) = ERBHz(pole_freqs(ch), car_params.erb_break_freq,
+  ArrayX erb_freqs(num_channels_);
+  for (int channel = 0; channel < num_channels_; ++channel) {
+    erb_freqs(channel) = ERBHz(pole_freqs(channel), car_params.erb_break_freq,
                           car_params.erb_q);
   }
-  FloatArray min_zetas = min_zeta + (0.25 * ((erb_freqs / pole_freqs) -
+  ArrayX min_zetas = min_zeta + (0.25 * ((erb_freqs / pole_freqs) -
                                              min_zeta));
   car_coeffs->zr_coeffs *= max_zeta - min_zetas;
   car_coeffs->h_coeffs = car_coeffs->c0_coeffs * f;
-  FloatArray relative_undamping = FloatArray::Ones(n_ch_);
-  FloatArray r = car_coeffs->r1_coeffs + (car_coeffs->zr_coeffs *
+  ArrayX relative_undamping = ArrayX::Ones(num_channels_);
+  ArrayX r = car_coeffs->r1_coeffs + (car_coeffs->zr_coeffs *
                                            relative_undamping);
   car_coeffs->g0_coeffs = (1.0 - (2.0 * r * car_coeffs->a0_coeffs) + (r*r)) /
     (1 - (2 * r * car_coeffs->a0_coeffs) +
     (car_coeffs->h_coeffs * r * car_coeffs->c0_coeffs) + (r*r));
 }
 
-void CARFAC::DesignIHCCoeffs(const IHCParams& ihc_params, const FPType fs,
-                             IHCCoeffs* ihc_coeffs) {
+void CARFAC::DesignIHCCoeffs(const IHCParams& ihc_params,
+                             const FPType sample_rate, IHCCoeffs* ihc_coeffs) {
   if (ihc_params.just_half_wave_rectify) {
     ihc_coeffs->just_half_wave_rectify = ihc_params.just_half_wave_rectify;
   } else {
     // This section calculates conductance values using two pre-defined scalars.
-    FloatArray x(1);
+    ArrayX x(1);
     FPType conduct_at_10, conduct_at_0;
     x(0) = 10.0;
     x = CARFACDetect(x);
@@ -185,9 +195,9 @@
       FPType current = 1 / (ri + r0);
       ihc_coeffs->cap1_voltage = 1 - (current * ri);
       ihc_coeffs->just_half_wave_rectify = false;
-      ihc_coeffs->lpf_coeff = 1 - exp( -1 / (ihc_params.tau_lpf * fs));
-      ihc_coeffs->out1_rate = ro / (ihc_params.tau1_out * fs);
-      ihc_coeffs->in1_rate = 1 / (ihc_params.tau1_in * fs);
+      ihc_coeffs->lpf_coeff = 1 - exp( -1 / (ihc_params.tau_lpf * sample_rate));
+      ihc_coeffs->out1_rate = ro / (ihc_params.tau1_out * sample_rate);
+      ihc_coeffs->in1_rate = 1 / (ihc_params.tau1_in * sample_rate);
       ihc_coeffs->one_capacitor = ihc_params.one_capacitor;
       ihc_coeffs->output_gain = 1 / (saturation_output - current);
       ihc_coeffs->rest_output = current / (saturation_output - current);
@@ -204,11 +214,11 @@
       ihc_coeffs->cap1_voltage = 1 - (current * r1);
       ihc_coeffs->cap2_voltage = ihc_coeffs->cap1_voltage - (current * r2);
       ihc_coeffs->just_half_wave_rectify = false;
-      ihc_coeffs->lpf_coeff = 1 - exp(-1 / (ihc_params.tau_lpf * fs));
-      ihc_coeffs->out1_rate = 1 / (ihc_params.tau1_out * fs);
-      ihc_coeffs->in1_rate = 1 / (ihc_params.tau1_in * fs);
-      ihc_coeffs->out2_rate = ro / (ihc_params.tau2_out * fs);
-      ihc_coeffs->in2_rate = 1 / (ihc_params.tau2_in * fs);
+      ihc_coeffs->lpf_coeff = 1 - exp(-1 / (ihc_params.tau_lpf * sample_rate));
+      ihc_coeffs->out1_rate = 1 / (ihc_params.tau1_out * sample_rate);
+      ihc_coeffs->in1_rate = 1 / (ihc_params.tau1_in * sample_rate);
+      ihc_coeffs->out2_rate = ro / (ihc_params.tau2_out * sample_rate);
+      ihc_coeffs->in2_rate = 1 / (ihc_params.tau2_in * sample_rate);
       ihc_coeffs->one_capacitor = ihc_params.one_capacitor;
       ihc_coeffs->output_gain = 1 / (saturation_output - current);
       ihc_coeffs->rest_output = current / (saturation_output - current);
@@ -216,17 +226,18 @@
       ihc_coeffs->rest_cap2 = ihc_coeffs->cap2_voltage;
     }
   }
-  ihc_coeffs->ac_coeff = 2 * kPi * ihc_params.ac_corner_hz / fs;
+  ihc_coeffs->ac_coeff = 2 * kPi * ihc_params.ac_corner_hz / sample_rate;
 }
 
-void CARFAC::DesignAGCCoeffs(const AGCParams& agc_params, const FPType fs,
+void CARFAC::DesignAGCCoeffs(const AGCParams& agc_params,
+                             const FPType sample_rate,
                              vector<AGCCoeffs>* agc_coeffs) {
-  agc_coeffs->resize(agc_params.n_stages);
+  agc_coeffs->resize(agc_params.num_stages);
   FPType previous_stage_gain = 0.0;
   FPType decim = 1.0;
-  for (int stage = 0; stage < agc_params.n_stages; ++stage) {
+  for (int stage = 0; stage < agc_params.num_stages; ++stage) {
     AGCCoeffs& agc_coeff = agc_coeffs->at(stage);
-    agc_coeff.n_agc_stages = agc_params.n_stages;
+    agc_coeff.num_agc_stages = agc_params.num_stages;
     agc_coeff.agc_stage_gain = agc_params.agc_stage_gain;
     vector<FPType> agc1_scales = agc_params.agc1_scales;
     vector<FPType> agc2_scales = agc_params.agc2_scales;
@@ -238,8 +249,9 @@
     FPType tau = time_constants[stage];
     agc_coeff.decim = decim;
     agc_coeff.decim *= agc_coeff.decimation;
-    agc_coeff.agc_epsilon = 1 - exp((-1 * agc_coeff.decim) / (tau * fs));
-    FPType n_times = tau * (fs / agc_coeff.decim);
+    agc_coeff.agc_epsilon = 1 - exp((-1 * agc_coeff.decim) /
+                                    (tau * sample_rate));
+    FPType n_times = tau * (sample_rate / agc_coeff.decim);
     FPType delay = (agc2_scales[stage] - agc1_scales[stage]) / n_times;
     FPType spread_sq = (pow(agc1_scales[stage], 2) +
                         pow(agc2_scales[stage], 2)) / n_times;
@@ -317,10 +329,15 @@
     agc_coeff.agc_spatial_fir_right = fir_right;
     total_dc_gain += pow(agc_coeff.agc_stage_gain, stage);
     agc_coeff.agc_mix_coeffs = stage == 0 ? 0 : mix_coeff /
-    (tau * (fs / agc_coeff.decim));
+      (tau * (sample_rate / agc_coeff.decim));
     agc_coeff.agc_gain = total_dc_gain;
     agc_coeff.detect_scale = 1 / total_dc_gain;
     previous_stage_gain = agc_coeff.agc_gain;
     decim = agc_coeff.decim;
   }
 }
+
+FPType CARFAC::ERBHz (const FPType center_frequency_hz,
+                      const FPType erb_break_freq, const FPType erb_q) {
+  return (erb_break_freq + center_frequency_hz) / erb_q;
+}
\ No newline at end of file
--- a/trunk/carfac/carfac.h	Fri May 31 21:46:48 2013 +0000
+++ b/trunk/carfac/carfac.h	Tue Jun 04 18:30:22 2013 +0000
@@ -19,69 +19,76 @@
 // 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.
-//
-// *****************************************************************************
-// Class: CARFAC
-// *****************************************************************************
-// The CARFAC class is the top-level class implementing the CAR-FAC C++ model.
-// A CARFAC object knows how to design its details from a modest set of
-// parameters, and knows how to process sound signals to produce "neural
-// activity patterns" (NAPs) which are contained in a CARFACOutput object.
-//
-// The 'Design' method is used to intialize the CARFAC model, and is passed
-// a set of CAR, IHC and AGC parameters along with sound file information
-// (channels and sample rate).
-//
-// The two methods 'Run' and 'RunSegment' are responsible for
-// processing sound signals. These both take two dimensional Eigen float arrays
-// (samples x channels) as arguments and return CARFACOutput objects.
 
 #ifndef CARFAC_CARFAC_H
 #define CARFAC_CARFAC_H
 
 #include <vector>
-#include "carfac_common.h"
-#include "car_params.h"
-#include "car_coeffs.h"
-#include "ihc_params.h"
-#include "ihc_coeffs.h"
-#include "agc_params.h"
-#include "agc_coeffs.h"
+
+#include "common.h"
+#include "carfac_util.h"
+#include "car.h"
+#include "ihc.h"
+#include "agc.h"
 #include "ear.h"
 #include "carfac_output.h"
 
+// This is the top-level class implementing the CAR-FAC C++ model. See the
+// chapter entitled 'The CAR-FAC Digital Cochlear Model' in Lyon's book "Human
+// and Machine Hearing" for an overview.
+//
+// A CARFAC object knows how to design its details from a modest set of
+// parameters, and knows how to process sound signals to produce "neural
+// activity patterns" (NAPs) which are stored in a CARFACOutput object during
+// the call to CARFAC::RunSegment.
 class CARFAC {
  public:
   // The 'Design' method takes a set of CAR, IHC and AGC parameters along with
   // arguments specifying the number of 'ears' (audio file channels) and sample
   // rate. This initializes a vector of 'Ear' objects -- one for mono, two for
-  // stereo, or more.  Each 'Ear' includes various sub-objects representing the
-  // parameters, designs (coeffs) ,and states of different parts of the CAR-FAC
-  // model.
-  void Design(const int n_ears, const FPType fs, const CARParams& car_params,
-              const IHCParams& ihc_params, const AGCParams& agc_params);
-  // The 'RunSegment' method processes individual sound segments
+  // stereo, or more.
+  CARFAC(const int num_ears, const FPType sample_rate,
+              const CARParams& car_params, const IHCParams& ihc_params,
+              const AGCParams& agc_params);
+  
+  // The 'RunSegment' method processes individual sound segments and stores the
+  // output of the model in a CARFACOutput object.
   void RunSegment(const std::vector<std::vector<float>>& sound_data,
                   const int32_t start, const int32_t length,
                   const bool open_loop, CARFACOutput* seg_output);
+  void Reset();
 
  private:
-  void DesignCARCoeffs(const CARParams& car_params, const FPType fs,
-                       const FloatArray& pole_freqs, CARCoeffs* car_coeffs);
-  void DesignIHCCoeffs(const IHCParams& ihc_params, const FPType fs,
+  // TODO (alexbrandmeyer): figure out why this breaks object initialization.
+  //DISALLOW_COPY_AND_ASSIGN(CARFAC);
+  void DesignCARCoeffs(const CARParams& car_params, const FPType sample_rate,
+                       const ArrayX& pole_freqs, CARCoeffs* car_coeffs);
+  void DesignIHCCoeffs(const IHCParams& ihc_params, const FPType sample_rate,
                        IHCCoeffs* ihc_coeffs);
-  void DesignAGCCoeffs(const AGCParams& agc_params, const FPType fs,
+  void DesignAGCCoeffs(const AGCParams& agc_params, const FPType sample_rate,
                        std::vector<AGCCoeffs>* agc_coeffs);
   void CrossCouple();
   void CloseAGCLoop();
+  
+  // Function: ERBHz
+  // Auditory filter nominal Equivalent Rectangular Bandwidth
+  // Ref: Glasberg and Moore: Hearing Research, 47 (1990), 103-138
+  // See also the section 'Auditory Frequency Scales' of the chapter 'Acoustic
+  // Approaches and Auditory Influence' in "Human and Machine Hearing".
+  FPType ERBHz(const FPType center_frequency_hz, const FPType erb_break_freq,
+               const FPType erb_q);
 
-  int n_ears_;  // This is the number of ears.
-  FPType fs_;  // This is our current sample rate.
-  int n_ch_;  // This is the number of channels in the CARFAC model.
+  CARParams car_params_;
+  IHCParams ihc_params_;
+  AGCParams agc_params_;
+  int num_ears_;
+  FPType sample_rate_;
+  int num_channels_;
   FPType max_channels_per_octave_;
-  // We store an array of Ear objects for mono/stereo/multichannel processing:
+  
+  // We store a vector of Ear objects for mono/stereo/multichannel processing:
   std::vector<Ear> ears_;
-  FloatArray pole_freqs_;
+  ArrayX pole_freqs_;
 };
 
-#endif  // CARFAC_CARFAC_H
+#endif  // CARFAC_CARFAC_H
\ No newline at end of file
--- a/trunk/carfac/carfac_common.cc	Fri May 31 21:46:48 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-//
-//  carfac_common.cc
-//  CARFAC Open Source C++ Library
-//
-//  Created by Alex Brandmeyer on 5/10/13.
-//
-// 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.
-
-#include "carfac_common.h"
-
-FPType ERBHz (const FPType cf_hz, const FPType erb_break_freq,
-              const FPType erb_q) {
-  return (erb_break_freq + cf_hz) / erb_q;
-}
-
-FloatArray CARFACDetect (const FloatArray& x) {
-  FloatArray conductance, z, set;
-  FPType a = 0.175;
-  // This offsets the low-end tail into negative x territory.
-  // The parameter is adjusted for the book, to make the 20% DC response
-  // threshold at 0.1.
-  z  = x + a;
-  // Zero is the final answer for many points.
-  conductance = (z < 0).select(0.0, (z*z*z) / (z*z*z + z*z + 0.1));
-  return conductance;
-}
\ No newline at end of file
--- a/trunk/carfac/carfac_common.h	Fri May 31 21:46:48 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-//
-//  carfac_common.h
-//  CARFAC Open Source C++ Library
-//
-//  Created by Alex Brandmeyer on 5/10/13.
-//
-// 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.
-//
-// *****************************************************************************
-// carfac_common.h
-// *****************************************************************************
-// This file contains the base level definitions and includes used within the
-// CARFAC C++ library. It also defines some low level functions which are used
-// during the calculation of the various coefficient sets required by the model.
-//
-// The current implementation of the library is dependent on the use of the
-// Eigen C++ library for linear algebra. Specifically, Eigen Arrays are used
-// extensively for coefficient wise operations during both the design and run
-// stages of the model.
-//
-// The 'FPType' typedef is specified in this file in order to enable quick
-// switching between precision levels (i.e. float vs. double) throughout the
-// library. The remainder of the code uses this type for specifying floating
-// point scalars.
-//
-// An additional typedefs are defined for one dimensional arrays: FloatArray.
-// These in turn make use of FPType so that the precision level across floating
-// point data is consistent.
-//
-// The functions 'ERBHz' and 'CARFACDetect' are defined here, and are used
-// during the design stage of a CARFAC model.
-
-#ifndef CARFAC_CARFAC_COMMON_H
-#define CARFAC_CARFAC_COMMON_H
-
-// The Eigen library is used extensively for floating point arrays.
-// For more information, see: http://eigen.tuxfamily.org
-#include <Eigen/Dense>
-
-using namespace Eigen;
-
-// The 'FPType' typedef is used to enable easy switching in precision level.
-// It's currently set to double for during the unit testing phase of the
-// project.
-typedef double FPType;
-// A typedef is used to define a one-dimensional Eigen array with the same
-// precision level as FPType.
-typedef Eigen::Array<FPType, Dynamic, 1> FloatArray;
-typedef Eigen::Array<FPType, Dynamic, Dynamic> Float2dArray;
-
-// A fixed value of PI is defined throughout the project.
-static const FPType kPi = 3.141592653589793238;
-
-// Two helper functions are defined here for use by the different model stages
-// in calculating coeffecients and during model runtime.
-// Function: ERBHz
-// Auditory filter nominal Equivalent Rectangular Bandwidth
-// Ref: Glasberg and Moore: Hearing Research, 47 (1990), 103-138
-FPType ERBHz(const FPType cf_hz, const FPType erb_break_freq,
-             const FPType erb_q);
-
-// Function CARFACDetect
-// This returns the IHC detection nonilnearity function of the filter output
-// values.  This is here because it is called both in design and run phases.
-FloatArray CARFACDetect(const FloatArray& x);
-
-#endif  // CARFAC_CARFAC_COMMON_H
--- a/trunk/carfac/carfac_output.cc	Fri May 31 21:46:48 2013 +0000
+++ b/trunk/carfac/carfac_output.cc	Tue Jun 04 18:30:22 2013 +0000
@@ -24,10 +24,9 @@
 
 using std::vector;
 
-void CARFACOutput::Init(const int n_ears, const bool store_nap,
-                        const bool store_nap_decim, const bool store_bm,
-                        const bool store_ohc, const bool store_agc) {
-  n_ears_ = n_ears;
+CARFACOutput::CARFACOutput(const bool store_nap, const bool store_nap_decim,
+                        const bool store_bm, const bool store_ohc,
+                        const bool store_agc) {
   store_nap_ = store_nap;
   store_nap_decim_ = store_nap_decim;
   store_bm_ = store_bm;
@@ -36,27 +35,27 @@
 
 }
 
-void CARFACOutput::StoreOutput(const vector<Ear>& ears) {
+void CARFACOutput::AppendOutput(const vector<Ear>& ears) {
   if (store_nap_) {
-    nap_.push_back(vector<FloatArray>());
+    nap_.push_back(vector<ArrayX>());
     for (auto ear : ears) {
       nap_.back().push_back(ear.ihc_out());
     }
   }
   if (store_ohc_) {
-    ohc_.push_back(vector<FloatArray>());
+    ohc_.push_back(vector<ArrayX>());
     for (auto ear : ears) {
       ohc_.back().push_back(ear.za_memory());
     }
   }
   if (store_agc_) {
-    agc_.push_back(vector<FloatArray>());
+    agc_.push_back(vector<ArrayX>());
     for (auto ear : ears) {
       agc_.back().push_back(ear.zb_memory());
     }
   }
   if (store_bm_) {
-    bm_.push_back(vector<FloatArray>());
+    bm_.push_back(vector<ArrayX>());
     for (auto ear : ears) {
       bm_.back().push_back(ear.zy_memory());
     }
--- a/trunk/carfac/carfac_output.h	Fri May 31 21:46:48 2013 +0000
+++ b/trunk/carfac/carfac_output.h	Tue Jun 04 18:30:22 2013 +0000
@@ -19,53 +19,53 @@
 // 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.
-//
-// *****************************************************************************
-// Class: CARFACOutput
-// *****************************************************************************
-// The CARFACOutput object stores an array of EarOuput objects. It is meant as a
-// container for the output generated by the CARFAC object's 'Run' and
-// 'RunSegment' methods. Depending on the number of audio channels in the  input
-// data, the CARFACOutput will have 1 or more EarOutput obects, each of which
-// contains a set of two dimensional float arrays (FloatArray2d) representing
-// the neural activation patterns (NAPs) generated by the CARFAC model.
-//
-// The 'InitOutput' method is used to initialize the arrays in each of the
-// EarOutput sub-objects once the target data dimensions ears (n_ears), channels
-// (n_ch) and timepoints (n_tp) are known.
 
 #ifndef CARFAC_CARFAC_OUTPUT_H
 #define CARFAC_CARFAC_OUTPUT_H
 
 #include <deque>
 #include <vector>
-#include "carfac_common.h"
+
+#include "common.h"
 #include "ear.h"
 
+// A CARFACOutput object can store up to 5 different types of output from a
+// CARFAC model, and is provided as an argument to the CARFAC::RunSegment
+// method.
 class CARFACOutput {
  public:
-  void Init(const int n_ears, const bool store_nap, const bool  store_nap_decim,
-             const bool store_bm, const bool store_ohc, const bool store_agc);
-  void StoreOutput(const std::vector<Ear>& ears);
-  // Here we define several acessors for the data members.
-  const std::deque<std::vector<FloatArray>>& nap() { return nap_; }
-  const std::deque<std::vector<FloatArray>>& bm() { return bm_; }
-  const std::deque<std::vector<FloatArray>>& nap_decim() { return nap_decim_; }
-  const std::deque<std::vector<FloatArray>>& ohc() { return ohc_; }
-  const std::deque<std::vector<FloatArray>>& agc() { return agc_; }
+  // The constructor takes five boolean values as arguments which indicate
+  // the portions of the CARFAC model's output to be stored.
+  CARFACOutput(const bool store_nap, const bool  store_nap_decim,
+            const bool store_bm, const bool store_ohc, const bool store_agc);
+  
+  // The AppendOutput method is called on a sample by sample basis by the
+  // CARFAC::RunSegemtn method, appending a single frame of n_ears x n_channels
+  // data to the end of the individual data members selected for storage.
+  void AppendOutput(const std::vector<Ear>& ears);
+  const std::deque<std::vector<ArrayX>>& nap() const { return nap_; }
+  const std::deque<std::vector<ArrayX>>& bm() const { return bm_; }
+  const std::deque<std::vector<ArrayX>>& nap_decim() const {
+    return nap_decim_; }
+  const std::deque<std::vector<ArrayX>>& ohc() const { return ohc_; }
+  const std::deque<std::vector<ArrayX>>& agc() const { return agc_; }
 
  private:
-  int n_ears_;
+  // TODO (alexbrandmeyer): figure out why this breaks object initialization.
+  //DISALLOW_COPY_AND_ASSIGN(CARFACOutput);
   bool store_nap_;
   bool store_nap_decim_;
   bool store_bm_;
   bool store_ohc_;
   bool store_agc_;
-  std::deque<std::vector<FloatArray>> nap_;
-  std::deque<std::vector<FloatArray>> nap_decim_;
-  std::deque<std::vector<FloatArray>> bm_;
-  std::deque<std::vector<FloatArray>> ohc_;
-  std::deque<std::vector<FloatArray>> agc_;
+  
+  // CARFAC outputs are stored in nested containers with dimensions:
+  // n_frames x n_ears x n_channels.
+  std::deque<std::vector<ArrayX>> nap_;
+  std::deque<std::vector<ArrayX>> nap_decim_;
+  std::deque<std::vector<ArrayX>> bm_;
+  std::deque<std::vector<ArrayX>> ohc_;
+  std::deque<std::vector<ArrayX>> agc_;
 };
 
 #endif  // CARFAC_CARFAC_OUTPUT_H
\ No newline at end of file
--- a/trunk/carfac/carfac_test.cc	Fri May 31 21:46:48 2013 +0000
+++ b/trunk/carfac/carfac_test.cc	Tue Jun 04 18:30:22 2013 +0000
@@ -25,10 +25,12 @@
 #include <vector>
 
 #include "gtest/gtest.h"
-#include "car_params.h"
-#include "ihc_params.h"
-#include "agc_params.h"
+
+#include "car.h"
+#include "ihc.h"
+#include "agc.h"
 #include "carfac.h"
+#include "common.h"
 
 using std::vector;
 using std::string;
@@ -39,19 +41,19 @@
 // locate the text files produced by 'CARFAC_GenerateTestData.m' for comparing
 // the ouput of the Matlab version of CARFAC with this C++ version.
 static const char* kTestSourceDir= "./test_data/";
-// Here we specify the level to which the output should match (7 decimals).
-static const float kPrecisionLevel = 1.0e-7;
+// Here we specify the level to which the output should match (2 decimals).
+static const float kPrecisionLevel = 1.0e-2;
 
 // Three helper functions are defined here for loading the test data generated
 // by the Matlab version of CARFAC.
-// This loads one-dimensional FloatArrays from single-column text files.
-void WriteNAPOutput(CARFACOutput output, const string filename, int ear) {
+// This loads one-dimensional ArrayXs from single-column text files.
+void WriteNAPOutput(CARFACOutput& output, const string filename, int ear) {
   string fullfile = kTestSourceDir + filename;
   ofstream ofile(fullfile.c_str());
-  int32_t n_timepoints = output.nap().size();
+  int32_t num_timepoints = output.nap().size();
   int channels = output.nap()[0][0].size();
   if (ofile.is_open()) {
-    for (int32_t i = 0; i < n_timepoints; ++i) {
+    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) {
@@ -64,11 +66,11 @@
   ofile.close();
 }
 
-FloatArray LoadTestData(const string filename, const int number_points) {
+ArrayX LoadTestData(const string filename, const int number_points) {
   string fullfile = kTestSourceDir + filename;
   ifstream file(fullfile.c_str());
   FPType myarray[number_points];
-  FloatArray output(number_points);
+  ArrayX output(number_points);
   if (file.is_open()) {
     for (int i = 0; i < number_points; ++i) {
       file >> myarray[i];
@@ -79,13 +81,13 @@
   return output;
 }
 
-// This loads a vector of FloatArrays from multi-column text files.
-vector<FloatArray> Load2dTestData(const string filename, const int rows,
+// This loads a vector of ArrayXs from multi-column text files.
+vector<ArrayX> Load2dTestData(const string filename, const int rows,
                             const int columns) {
   string fullfile = kTestSourceDir + filename;
   ifstream file(fullfile.c_str());
   FPType myarray[rows][columns];
-  vector<FloatArray> output;
+  vector<ArrayX> output;
   output.resize(rows);
   for (auto& timepoint : output) {
     timepoint.resize(columns);
@@ -125,28 +127,25 @@
 }
 
 TEST(CARFACTest, Binaural_Output_test) {
-  int n_timepoints = 882;
-  int n_channels = 71;
-  int n_ears = 2;
+  int num_timepoints = 882;
+  int num_channels = 71;
+  int num_ears = 2;
   string filename = "binaural_test_nap1.txt";
-  vector<FloatArray> nap1 = Load2dTestData(filename, n_timepoints, n_channels);
+  vector<ArrayX> nap1 = Load2dTestData(filename, num_timepoints, num_channels);
   filename = "binaural_test_bm1.txt";
-  vector<FloatArray> bm1 = Load2dTestData(filename, n_timepoints, n_channels);
+  vector<ArrayX> bm1 = Load2dTestData(filename, num_timepoints, num_channels);
   filename = "binaural_test_nap2.txt";
-  vector<FloatArray> nap2 = Load2dTestData(filename, n_timepoints, n_channels);
+  vector<ArrayX> nap2 = Load2dTestData(filename, num_timepoints, num_channels);
   filename = "binaural_test_bm2.txt";
-  vector<FloatArray> bm2 = Load2dTestData(filename, n_timepoints, n_channels);
+  vector<ArrayX> bm2 = Load2dTestData(filename, num_timepoints, num_channels);
   filename = "file_signal_binaural_test.txt";
-  vector<vector<float>> sound_data = Load2dAudioVector(filename, n_timepoints,
-                                                       n_ears);
+  vector<vector<float>> sound_data = Load2dAudioVector(filename, num_timepoints,
+                                                       num_ears);
   CARParams car_params;
   IHCParams ihc_params;
   AGCParams agc_params;
-  CARFAC mycf;
-  mycf.Design(n_ears, 22050, car_params, ihc_params,
-              agc_params);
-  CARFACOutput my_output;
-  my_output.Init(n_ears, true, false, true, false, false);
+  CARFAC mycf(num_ears, 22050, car_params, ihc_params, agc_params);
+  CARFACOutput my_output(true, false, true, false, false);
   const bool kOpenLoop = false;
   const int length = sound_data[0].size();
   mycf.RunSegment(sound_data, 0, length, kOpenLoop, &my_output);
@@ -156,7 +155,7 @@
   WriteNAPOutput(my_output, filename, 1);
   int ear = 0;
   int n_ch = 71;
-  for (int timepoint = 0; timepoint < n_timepoints; ++timepoint) {
+  for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
     for (int channel = 0; channel < n_ch; ++channel) {
       FPType cplusplus = my_output.nap()[timepoint][ear](channel);
       FPType matlab = nap1[timepoint](channel);
@@ -167,7 +166,7 @@
     }
   }
   ear = 1;
-  for (int timepoint = 0; timepoint < n_timepoints; ++timepoint) {
+  for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
     for (int channel = 0; channel < n_ch; ++channel) {
       FPType cplusplus = my_output.nap()[timepoint][ear](channel);
       FPType matlab = nap2[timepoint](channel);
@@ -180,28 +179,25 @@
 }
 
 TEST(CARFACTest, Long_Output_test) {
-  int n_timepoints = 2000;
-  int n_channels = 83;
-  int n_ears = 2;
+  int num_timepoints = 2000;
+  int num_channels = 83;
+  int num_ears = 2;
   string filename = "long_test_nap1.txt";
-  vector<FloatArray> nap1 = Load2dTestData(filename, n_timepoints, n_channels);
+  vector<ArrayX> nap1 = Load2dTestData(filename, num_timepoints, num_channels);
   filename = "long_test_bm1.txt";
-  vector<FloatArray> bm1 = Load2dTestData(filename, n_timepoints, n_channels);
+  vector<ArrayX> bm1 = Load2dTestData(filename, num_timepoints, num_channels);
   filename = "long_test_nap2.txt";
-  vector<FloatArray> nap2 = Load2dTestData(filename, n_timepoints, n_channels);
+  vector<ArrayX> nap2 = Load2dTestData(filename, num_timepoints, num_channels);
   filename = "long_test_bm2.txt";
-  vector<FloatArray> bm2 = Load2dTestData(filename, n_timepoints, n_channels);
+  vector<ArrayX> bm2 = Load2dTestData(filename, num_timepoints, num_channels);
   filename = "file_signal_long_test.txt";
-  vector<vector<float>> sound_data = Load2dAudioVector(filename, n_timepoints,
-                                                       n_ears);
+  vector<vector<float>> sound_data = Load2dAudioVector(filename, num_timepoints,
+                                                       num_ears);
   CARParams car_params;
   IHCParams ihc_params;
   AGCParams agc_params;
-  CARFAC mycf;
-  mycf.Design(n_ears, 44100, car_params, ihc_params,
-              agc_params);
-  CARFACOutput my_output;
-  my_output.Init(n_ears, true, false, true, false, false);
+  CARFAC mycf(num_ears, 44100, car_params, ihc_params, agc_params);
+  CARFACOutput my_output(true, false, true, false, false);
   const bool kOpenLoop = false;
   const int length = sound_data[0].size();
   mycf.RunSegment(sound_data, 0, length, kOpenLoop, &my_output);
@@ -210,8 +206,8 @@
   filename = "cpp_nap_output_2_long_test.txt";
   WriteNAPOutput(my_output, filename, 1);
   int ear = 0;
-  for (int timepoint = 0; timepoint < n_timepoints; ++timepoint) {
-    for (int channel = 0; channel < n_channels; ++channel) {
+  for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
+    for (int channel = 0; channel < num_channels; ++channel) {
       FPType cplusplus = my_output.nap()[timepoint][ear](channel);
       FPType matlab = nap1[timepoint](channel);
       ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
@@ -221,8 +217,8 @@
     }
   }
   ear = 1;
-  for (int timepoint = 0; timepoint < n_timepoints; ++timepoint) {
-    for (int channel = 0; channel < n_channels; ++channel) {
+  for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
+    for (int channel = 0; channel < num_channels; ++channel) {
       FPType cplusplus = my_output.nap()[timepoint][ear](channel);
       FPType matlab = nap2[timepoint](channel);
       ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
@@ -231,4 +227,4 @@
       ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
     }
   }
-}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/carfac/carfac_util.cc	Tue Jun 04 18:30:22 2013 +0000
@@ -0,0 +1,35 @@
+//
+//  carfac_util.cc
+//  CARFAC Open Source C++ Library
+//
+//  Created by Alex Brandmeyer on 6/3/13.
+//
+// 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.
+
+#include "carfac_util.h"
+
+ArrayX CARFACDetect (const ArrayX& x) {
+  ArrayX conductance, z, set;
+  FPType a = 0.175;
+  // This offsets the low-end tail into negative x territory.
+  // The parameter is adjusted for the book, to make the 20% DC response
+  // threshold at 0.1.
+  z  = x + a;
+  // Zero is the final answer for many points.
+  conductance = (z < 0).select(0.0, (z*z*z) / (z*z*z + z*z + 0.1));
+  return conductance;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/carfac/carfac_util.h	Tue Jun 04 18:30:22 2013 +0000
@@ -0,0 +1,33 @@
+//
+//  carfac_util.h
+//  CARFAC Open Source C++ Library
+//
+//  Created by Alex Brandmeyer on 5/10/13.
+//
+// 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.
+
+#ifndef CARFAC_CARFAC_UTIL_H
+#define CARFAC_CARFAC_UTIL_H
+
+#include "common.h"
+
+// Function CARFACDetect
+// This returns the IHC detection nonilnearity function of the filter output
+// values.  This is here because it is called both in design and run phases.
+ArrayX CARFACDetect(const ArrayX& x);
+
+#endif  // CARFAC_CARFAC_UTIL_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/carfac/common.h	Tue Jun 04 18:30:22 2013 +0000
@@ -0,0 +1,48 @@
+//
+//  common.h
+//  CARFAC Open Source C++ Library
+//
+//  Created by Alex Brandmeyer on 5/10/13.
+//
+// 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.
+
+#ifndef CARFAC_COMMON_H
+#define CARFAC_COMMON_H
+
+// This macro disallows the copy constructor and operator= functions.
+// This should be used in the private: declarations for a class.
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+
+// The Eigen library is used extensively for floating point arrays.
+// For more information, see: http://eigen.tuxfamily.org
+#include <Eigen/Dense>
+
+// The 'FPType' typedef is used to enable easy switching in precision level.
+// It's currently set to double for during the unit testing phase of the
+// project.
+typedef float FPType;
+// A typedef is used to define a one-dimensional Eigen array with the same
+// precision level as FPType.
+typedef Eigen::Array<FPType, Eigen::Dynamic, 1> ArrayX;
+typedef Eigen::Array<FPType, Eigen::Dynamic, Eigen::Dynamic> ArrayXX;
+
+// A fixed value of PI is defined throughout the project.
+static const FPType kPi = 3.141592653589793238;
+
+#endif  // CARFAC_COMMON_H
\ No newline at end of file
--- a/trunk/carfac/ear.cc	Fri May 31 21:46:48 2013 +0000
+++ b/trunk/carfac/ear.cc	Tue Jun 04 18:30:22 2013 +0000
@@ -23,48 +23,40 @@
 #include <assert.h>
 #include "ear.h"
 
-// The 'InitEar' function takes a set of model parameters and initializes the
-// design coefficients and model state variables needed for running the model
-// on a single audio channel.
-void Ear::InitEar(const int n_ch, const FPType fs, const CARCoeffs& car_coeffs,
-                  const IHCCoeffs& ihc_coeffs,
-                  const std::vector<AGCCoeffs>& agc_coeffs) {
-  // The first section of code determines the number of channels that will be
-  // used in the model on the basis of the sample rate and the CAR parameters
-  // that have been passed to this function.
-  n_ch_ = n_ch;
+void Ear::Init(const int num_channels, const CARCoeffs& car_coeffs,
+               const IHCCoeffs& ihc_coeffs,
+               const std::vector<AGCCoeffs>& agc_coeffs) {
+  num_channels_ = num_channels;
   car_coeffs_ = car_coeffs;
   ihc_coeffs_ = ihc_coeffs;
   agc_coeffs_ = agc_coeffs;
-  // Once the coefficients have been determined, we can initialize the state
-  // variables that will be used during runtime.
   InitCARState();
   InitIHCState();
   InitAGCState();
 }
 
 void Ear::InitCARState() {
-  car_state_.z1_memory.setZero(n_ch_);
-  car_state_.z2_memory.setZero(n_ch_);
-  car_state_.za_memory.setZero(n_ch_);
+  car_state_.z1_memory.setZero(num_channels_);
+  car_state_.z2_memory.setZero(num_channels_);
+  car_state_.za_memory.setZero(num_channels_);
   car_state_.zb_memory = car_coeffs_.zr_coeffs;
-  car_state_.dzb_memory.setZero(n_ch_);
-  car_state_.zy_memory.setZero(n_ch_);
+  car_state_.dzb_memory.setZero(num_channels_);
+  car_state_.zy_memory.setZero(num_channels_);
   car_state_.g_memory = car_coeffs_.g0_coeffs;
-  car_state_.dg_memory.setZero(n_ch_);
+  car_state_.dg_memory.setZero(num_channels_);
 }
 
 void Ear::InitIHCState() {
-  ihc_state_.ihc_accum = FloatArray::Zero(n_ch_);
+  ihc_state_.ihc_accum = ArrayX::Zero(num_channels_);
   if (! ihc_coeffs_.just_half_wave_rectify) {
-    ihc_state_.ac_coupler.setZero(n_ch_);
-    ihc_state_.lpf1_state.setConstant(n_ch_, ihc_coeffs_.rest_output);
-    ihc_state_.lpf2_state.setConstant(n_ch_, ihc_coeffs_.rest_output);
+    ihc_state_.ac_coupler.setZero(num_channels_);
+    ihc_state_.lpf1_state.setConstant(num_channels_, ihc_coeffs_.rest_output);
+    ihc_state_.lpf2_state.setConstant(num_channels_, ihc_coeffs_.rest_output);
     if (ihc_coeffs_.one_capacitor) {
-      ihc_state_.cap1_voltage.setConstant(n_ch_, ihc_coeffs_.rest_cap1);
+      ihc_state_.cap1_voltage.setConstant(num_channels_, ihc_coeffs_.rest_cap1);
     } else {
-      ihc_state_.cap1_voltage.setConstant(n_ch_, ihc_coeffs_.rest_cap1);
-      ihc_state_.cap2_voltage.setConstant(n_ch_, ihc_coeffs_.rest_cap2);
+      ihc_state_.cap1_voltage.setConstant(num_channels_, ihc_coeffs_.rest_cap1);
+      ihc_state_.cap2_voltage.setConstant(num_channels_, ihc_coeffs_.rest_cap2);
     }
   }
 }
@@ -74,8 +66,8 @@
   agc_state_.resize(n_agc_stages);
   for (auto& stage_state : agc_state_) {
     stage_state.decim_phase = 0;
-    stage_state.agc_memory.setZero(n_ch_);
-    stage_state.input_accum.setZero(n_ch_);
+    stage_state.agc_memory.setZero(num_channels_);
+    stage_state.input_accum.setZero(num_channels_);
   }
 }
 
@@ -86,16 +78,15 @@
   car_state_.zb_memory = car_state_.zb_memory + car_state_.dzb_memory;
   // This updates the nonlinear function of 'velocity' along with zA, which is
   // a delay of z2.
-  FloatArray nonlinear_fun(n_ch_);
-  FloatArray velocities = car_state_.z2_memory - car_state_.za_memory;
+  ArrayX nonlinear_fun(num_channels_);
+  ArrayX velocities = car_state_.z2_memory - car_state_.za_memory;
   OHCNonlinearFunction(velocities, &nonlinear_fun);
   // Here, zb_memory_ * nonlinear_fun is "undamping" delta r.
-  FloatArray r = car_coeffs_.r1_coeffs + (car_state_.zb_memory *
-                                           nonlinear_fun);
+  ArrayX r = car_coeffs_.r1_coeffs + (car_state_.zb_memory * nonlinear_fun);
   car_state_.za_memory = car_state_.z2_memory;
   // Here we reduce the CAR state by r and rotate with the fixed cos/sin coeffs.
-  FloatArray z1  = r * ((car_coeffs_.a0_coeffs * car_state_.z1_memory) -
-                        (car_coeffs_.c0_coeffs * car_state_.z2_memory));
+  ArrayX z1  = r * ((car_coeffs_.a0_coeffs * car_state_.z1_memory) -
+                    (car_coeffs_.c0_coeffs * car_state_.z2_memory));
   car_state_.z2_memory = r *
     ((car_coeffs_.c0_coeffs * car_state_.z1_memory) +
      (car_coeffs_.a0_coeffs * car_state_.z2_memory));
@@ -103,11 +94,12 @@
   // This section ripples the input-output path, to avoid delay...
   // It's the only part that doesn't get computed "in parallel":
   FPType in_out = input;
-  for (int ch = 0; ch < n_ch_; ch++) {
-    z1(ch) = z1(ch) + in_out;
+  for (int channel = 0; channel < num_channels_; channel++) {
+    z1(channel) = z1(channel) + in_out;
     // This performs the ripple, and saves the final channel outputs in zy.
-    in_out = car_state_.g_memory(ch) * (in_out + car_state_.zy_memory(ch));
-    car_state_.zy_memory(ch) = in_out;
+    in_out = car_state_.g_memory(channel) *
+      (in_out + car_state_.zy_memory(channel));
+    car_state_.zy_memory(channel) = in_out;
   }
   car_state_.z1_memory = z1;
 }
@@ -115,8 +107,8 @@
 // We start with a quadratic nonlinear function, and limit it via a
 // rational function. This makes the result go to zero at high
 // absolute velocities, so it will do nothing there.
-void Ear::OHCNonlinearFunction(const FloatArray& velocities,
-                               FloatArray* nonlinear_fun) {
+void Ear::OHCNonlinearFunction(const ArrayX& velocities,
+                               ArrayX* nonlinear_fun) {
   *nonlinear_fun = (1 + ((velocities * car_coeffs_.velocity_scale) +
                          car_coeffs_.v_offset).square()).inverse();
 }
@@ -124,19 +116,19 @@
 // This step is a one sample-time update of the inner-hair-cell (IHC) model,
 // including the detection nonlinearity and either one or two capacitor state
 // variables.
-void Ear::IHCStep(const FloatArray& car_out) {
-  FloatArray ac_diff = car_out - ihc_state_.ac_coupler;
+void Ear::IHCStep(const ArrayX& car_out) {
+  ArrayX ac_diff = car_out - ihc_state_.ac_coupler;
   ihc_state_.ac_coupler = ihc_state_.ac_coupler +
     (ihc_coeffs_.ac_coeff * ac_diff);
   if (ihc_coeffs_.just_half_wave_rectify) {
-    FloatArray output(n_ch_);
-    for (int ch = 0; ch < n_ch_; ++ch) {
-      FPType a = (ac_diff(ch) > 0.0) ? ac_diff(ch) : 0.0;
-      output(ch) = (a < 2) ? a : 2;
+    ArrayX output(num_channels_);
+    for (int channel = 0; channel < num_channels_; ++channel) {
+      FPType a = (ac_diff(channel) > 0.0) ? ac_diff(channel) : 0.0;
+      output(channel) = (a < 2) ? a : 2;
     }
     ihc_state_.ihc_out = output;
   } else {
-    FloatArray conductance = CARFACDetect(ac_diff);
+    ArrayX conductance = CARFACDetect(ac_diff);
     if (ihc_coeffs_.one_capacitor) {
       ihc_state_.ihc_out = conductance * ihc_state_.cap1_voltage;
       ihc_state_.cap1_voltage = ihc_state_.cap1_voltage -
@@ -164,15 +156,15 @@
   ihc_state_.ihc_accum += ihc_state_.ihc_out;
 }
 
-bool Ear::AGCStep(const FloatArray& ihc_out) {
+bool Ear::AGCStep(const ArrayX& ihc_out) {
   int stage = 0;
-  int n_stages = agc_coeffs_[0].n_agc_stages;
-  FPType detect_scale = agc_coeffs_[n_stages - 1].detect_scale;
+  int num_stages = agc_coeffs_[0].num_agc_stages;
+  FPType detect_scale = agc_coeffs_[num_stages - 1].detect_scale;
   bool updated = AGCRecurse(stage, detect_scale * ihc_out);
   return updated;
 }
 
-bool Ear::AGCRecurse(const int stage, FloatArray agc_in) {
+bool Ear::AGCRecurse(const int stage, ArrayX agc_in) {
   bool updated = true;
   const auto& agc_coeffs = agc_coeffs_[stage];
   auto& agc_state = agc_state_[stage];
@@ -191,7 +183,7 @@
     // decimated at the next stage.
     agc_in = agc_state.input_accum / decim;
     // This resets the accumulator.
-    agc_state.input_accum = FloatArray::Zero(n_ch_);
+    agc_state.input_accum = ArrayX::Zero(num_channels_);
     if (stage < (agc_coeffs_.size() - 1)) {
       // Now we recurse to evaluate the next stage(s).
       updated = AGCRecurse(stage + 1, agc_in);
@@ -212,25 +204,27 @@
 }
 
 void Ear::AGCSpatialSmooth(const AGCCoeffs& agc_coeffs,
-                           FloatArray* stage_state) {
-  int n_iterations = agc_coeffs.agc_spatial_iterations;
+                           ArrayX* stage_state) {
+  int num_iterations = agc_coeffs.agc_spatial_iterations;
   bool use_fir;
-  use_fir = (n_iterations < 4) ? true : false;
+  use_fir = (num_iterations < 4) ? true : false;
   if (use_fir) {
     FPType fir_coeffs_left = agc_coeffs.agc_spatial_fir_left;
     FPType fir_coeffs_mid = agc_coeffs.agc_spatial_fir_mid;
     FPType fir_coeffs_right = agc_coeffs.agc_spatial_fir_right;
-    FloatArray ss_tap1(n_ch_);
-    FloatArray ss_tap2(n_ch_);
-    FloatArray ss_tap3(n_ch_);
-    FloatArray ss_tap4(n_ch_);
+    ArrayX ss_tap1(num_channels_);
+    ArrayX ss_tap2(num_channels_);
+    ArrayX ss_tap3(num_channels_);
+    ArrayX ss_tap4(num_channels_);
     int n_taps = agc_coeffs.agc_spatial_n_taps;
     // This initializes the first two taps of stage state, which are used for
     // both possible cases.
     ss_tap1(0) = (*stage_state)(0);
-    ss_tap1.block(1, 0, n_ch_ - 1, 1) = stage_state->block(0, 0, n_ch_ - 1, 1);
-    ss_tap2(n_ch_ - 1) = (*stage_state)(n_ch_ - 1);
-    ss_tap2.block(0, 0, n_ch_ - 1, 1) = stage_state->block(1, 0, n_ch_ - 1, 1);
+    ss_tap1.block(1, 0, num_channels_ - 1, 1) =
+      stage_state->block(0, 0, num_channels_ - 1, 1);
+    ss_tap2(num_channels_ - 1) = (*stage_state)(num_channels_ - 1);
+    ss_tap2.block(0, 0, num_channels_ - 1, 1) =
+      stage_state->block(1, 0, num_channels_ - 1, 1);
     switch (n_taps) {
       case 3:
         *stage_state = (fir_coeffs_left * ss_tap1) +
@@ -241,12 +235,12 @@
         // for the 5-tap case.
         ss_tap3(0) = (*stage_state)(0);
         ss_tap3(1) = (*stage_state)(1);
-        ss_tap3.block(2, 0, n_ch_ - 2, 1) =
-          stage_state->block(0, 0, n_ch_ - 2, 1);
-        ss_tap4(n_ch_ - 2) = (*stage_state)(n_ch_ - 1);
-        ss_tap4(n_ch_ - 1) = (*stage_state)(n_ch_ - 2);
-        ss_tap4.block(0, 0, n_ch_ - 2, 1) =
-        stage_state->block(2, 0, n_ch_ - 2, 1);
+        ss_tap3.block(2, 0, num_channels_ - 2, 1) =
+          stage_state->block(0, 0, num_channels_ - 2, 1);
+        ss_tap4(num_channels_ - 2) = (*stage_state)(num_channels_ - 1);
+        ss_tap4(num_channels_ - 1) = (*stage_state)(num_channels_ - 2);
+        ss_tap4.block(0, 0, num_channels_ - 2, 1) =
+        stage_state->block(2, 0, num_channels_ - 2, 1);
         *stage_state = (fir_coeffs_left * (ss_tap3 + ss_tap1)) +
           (fir_coeffs_mid * *stage_state) +
           (fir_coeffs_right * (ss_tap2 + ss_tap4));
@@ -261,30 +255,31 @@
   }
 }
 
-void Ear::AGCSmoothDoubleExponential(const FPType pole_z1,  const FPType pole_z2,
-                                FloatArray* stage_state) {
-  int32_t n_pts = stage_state->size();
+void Ear::AGCSmoothDoubleExponential(const FPType pole_z1,
+                                     const FPType pole_z2,
+                                     ArrayX* stage_state) {
+  int32_t num_points = stage_state->size();
   FPType input;
   FPType state = 0.0;
   // TODO (alexbrandmeyer): I'm assuming one dimensional input for now, but this
   // should be verified with Dick for the final version
-  for (int i = n_pts - 11; i < n_pts; ++i) {
+  for (int i = num_points - 11; i < num_points; ++i) {
     input = (*stage_state)(i);
     state = state + (1 - pole_z1) * (input - state);
   }
-  for (int i = n_pts - 1; i > -1; --i) {
+  for (int i = num_points - 1; i > -1; --i) {
     input = (*stage_state)(i);
     state = state + (1 - pole_z2) * (input - state);
   }
-  for (int i = 0; i < n_pts; ++i) {
+  for (int i = 0; i < num_points; ++i) {
     input = (*stage_state)(i);
     state = state + (1 - pole_z1) * (input - state);
     (*stage_state)(i) = state;
   }
 }
 
-FloatArray Ear::StageGValue(const FloatArray& undamping) {
-  FloatArray r = car_coeffs_.r1_coeffs + car_coeffs_.zr_coeffs * undamping;
+ArrayX Ear::StageGValue(const ArrayX& undamping) {
+  ArrayX r = car_coeffs_.r1_coeffs + car_coeffs_.zr_coeffs * undamping;
   return (1 - 2 * r * car_coeffs_.a0_coeffs + (r * r)) /
     (1 - 2 * r * car_coeffs_.a0_coeffs + car_coeffs_.h_coeffs * r *
      car_coeffs_.c0_coeffs + (r * r));
--- a/trunk/carfac/ear.h	Fri May 31 21:46:48 2013 +0000
+++ b/trunk/carfac/ear.h	Tue Jun 04 18:30:22 2013 +0000
@@ -24,84 +24,97 @@
 #define CARFAC_EAR_H
 
 #include <vector>
-#include "carfac_common.h"
-#include "car_coeffs.h"
-#include "ihc_coeffs.h"
-#include "agc_coeffs.h"
-#include "car_state.h"
-#include "ihc_state.h"
-#include "agc_state.h"
 
+#include "common.h"
+#include "carfac_util.h"
+#include "car.h"
+#include "agc.h"
+#include "ihc.h"
+
+// The Ear object carries out the three steps of the CARFAC model on a single
+// channel of audio data, and stores information about the CAR, IHC and AGC
+// coefficients and states. 
 class Ear {
  public:
+  
   // This is the primary initialization function that is called for each
-  // Ear object in the CARFAC 'Design' method.
-  void InitEar(const int n_ch, const FPType fs,
-               const CARCoeffs& car_coeffs, const IHCCoeffs& ihc_coeffs,
-               const std::vector<AGCCoeffs>& agc_coeffs);
-  // These three methods apply the different stages of the model in sequence
-  // to individual audio samples.
+  // Ear object by the CARFAC::Design method.
+  void Init(const int num_channels, const CARCoeffs& car_coeffs,
+            const IHCCoeffs& ihc_coeffs,
+            const std::vector<AGCCoeffs>& agc_coeffs);
+  
+  // These three methods apply the different steps of the model in sequence
+  // to individual audio samples during the call to CARFAC::RunSegment.
   void CARStep(const FPType input);
-  void IHCStep(const FloatArray& car_out);
-  bool AGCStep(const FloatArray& ihc_out);
+  void IHCStep(const ArrayX& car_out);
+  bool AGCStep(const ArrayX& ihc_out);
+  
   // These accessor functions return portions of the CAR state for storage in
   // the CAROutput structures.
-  const FloatArray& za_memory() { return car_state_.za_memory; }
-  const FloatArray& zb_memory() { return car_state_.zb_memory; }
+  const ArrayX& za_memory() const { return car_state_.za_memory; }
+  const ArrayX& zb_memory() const { return car_state_.zb_memory; }
+  
   // The zy_memory_ of the CARState is equivalent to the CAR output. A second
   // accessor function is included for documentation purposes.
-  const FloatArray& zy_memory() { return car_state_.zy_memory; }
-  const FloatArray& car_out() { return car_state_.zy_memory; }
-  const FloatArray& g_memory() { return car_state_.g_memory; }
-  // This returns the IHC output for storage.
-  const FloatArray& ihc_out() { return ihc_state_.ihc_out; }
-  const FloatArray& dzb_memory() { return car_state_.dzb_memory; }
-  // These accessor functions return CAR coefficients.
-  const FloatArray& zr_coeffs() { return car_coeffs_.zr_coeffs; }
+  const ArrayX& zy_memory() const { return car_state_.zy_memory; }
+  const ArrayX& car_out() const { return car_state_.zy_memory; }
+  const ArrayX& g_memory() const { return car_state_.g_memory; }
+  const ArrayX& ihc_out() const { return ihc_state_.ihc_out; }
+  const ArrayX& dzb_memory() const { return car_state_.dzb_memory; }
+  const ArrayX& zr_coeffs() const { return car_coeffs_.zr_coeffs; }
+  
   // These accessor functions return portions of the AGC state during the cross
   // coupling of the ears.
-  const int agc_nstages() { return agc_coeffs_.size(); }
-  const int agc_decim_phase(const int stage) {
+  const int agc_num_stages() const { return agc_coeffs_.size(); }
+  const int agc_decim_phase(const int stage) const {
     return agc_state_[stage].decim_phase; }
-  const FPType agc_mix_coeff(const int stage) {
+  const FPType agc_mix_coeff(const int stage) const {
     return agc_coeffs_[stage].agc_mix_coeffs; }
-  const FloatArray& agc_memory(const int stage) {
+  const ArrayX& agc_memory(const int stage) const {
     return agc_state_[stage].agc_memory; }
-  const int agc_decimation(const int stage) {
+  const int agc_decimation(const int stage) const {
     return agc_coeffs_[stage].decimation; }
+  
   // This returns the stage G value during the closing of the AGC loop.
-  FloatArray StageGValue(const FloatArray& undamping);
+  ArrayX StageGValue(const ArrayX& undamping);
+  
   // This function sets the AGC memory during the cross coupling stage.
-  void set_agc_memory(const int stage, const FloatArray& new_values) {
+  void set_agc_memory(const int stage, const ArrayX& new_values) {
     agc_state_[stage].agc_memory = new_values; }
+  
   // These are the setter functions for the CAR memory states.
-  void set_dzb_memory(const FloatArray& new_values) {
+  void set_dzb_memory(const ArrayX& new_values) {
     car_state_.dzb_memory = new_values; }
-  void set_dg_memory(const FloatArray& new_values) {
+  void set_dg_memory(const ArrayX& new_values) {
     car_state_.dg_memory = new_values; }
 
  private:
-  // These are the corresponding methods that initialize the model state
-  // variables before runtime using the model coefficients.
+  // TODO (alexbrandmeyer): figure out why this breaks object initialization.
+  //DISALLOW_COPY_AND_ASSIGN(Ear);
+  
+  // These methodsinitialize the model state variables prior to runtime.
   void InitIHCState();
   void InitAGCState();
   void InitCARState();
-  // These are the various helper functions called during the model runtime.
-  void OHCNonlinearFunction(const FloatArray& velocities,
-                            FloatArray* nonlinear_fun);
-  bool AGCRecurse(const int stage, FloatArray agc_in);
-  void AGCSpatialSmooth(const AGCCoeffs& agc_coeffs , FloatArray* stage_state);
+  
+  // These are the helper sub-functions called during the model runtime.
+  void OHCNonlinearFunction(const ArrayX& velocities,
+                            ArrayX* nonlinear_fun);
+  bool AGCRecurse(const int stage, ArrayX agc_in);
+  void AGCSpatialSmooth(const AGCCoeffs& agc_coeffs , ArrayX* stage_state);
   void AGCSmoothDoubleExponential(const FPType pole_z1, const FPType pole_z2,
-                                  FloatArray* stage_state);
-  // These are the private data members that store the state and coefficient
-  // information.
+                                  ArrayX* stage_state);
+
   CARCoeffs car_coeffs_;
+  CARState car_state_;
   IHCCoeffs ihc_coeffs_;
+  IHCState ihc_state_;
+  
+  // The AGC coefficient and state variables are both stored in vectors
+  // containing one element for each stage (default = 4). 
   std::vector<AGCCoeffs> agc_coeffs_;
-  CARState car_state_;
-  IHCState ihc_state_;
   std::vector<AGCState> agc_state_;
-  int n_ch_;
+  int num_channels_;
 };
 
 #endif  // CARFAC_EAR_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/carfac/ihc.h	Tue Jun 04 18:30:22 2013 +0000
@@ -0,0 +1,76 @@
+//
+//  ihc.h
+//  CARFAC Open Source C++ Library
+//
+//  Created by Alex Brandmeyer on 5/30/13.
+//
+// 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.
+
+#ifndef CARFAC_IHC_H
+#define CARFAC_IHC_H
+
+#include "common.h"
+
+struct IHCParams {
+  IHCParams() {
+    just_half_wave_rectify = false;
+    one_capacitor = true;
+    tau_lpf = 0.000080;
+    tau1_out = 0.0005;
+    tau1_in = 0.010;
+    tau2_out = 0.0025;
+    tau2_in = 0.005;
+    ac_corner_hz = 20.0;
+  };
+  bool just_half_wave_rectify;
+  bool one_capacitor;
+  FPType tau_lpf;
+  FPType tau1_out;
+  FPType tau1_in;
+  FPType tau2_out;
+  FPType tau2_in;
+  FPType ac_corner_hz;
+};
+
+struct IHCCoeffs {
+  bool just_half_wave_rectify;
+  bool one_capacitor;
+  FPType lpf_coeff;
+  FPType out1_rate;
+  FPType in1_rate;
+  FPType out2_rate;
+  FPType in2_rate;
+  FPType output_gain;
+  FPType rest_output;
+  FPType rest_cap1;
+  FPType rest_cap2;
+  FPType ac_coeff;
+  FPType cap1_voltage;
+  FPType cap2_voltage;
+};
+
+struct IHCState {
+  ArrayX ihc_out;
+  ArrayX ihc_accum;
+  ArrayX cap1_voltage;
+  ArrayX cap2_voltage;
+  ArrayX lpf1_state;
+  ArrayX lpf2_state;
+  ArrayX ac_coupler;
+};
+
+#endif  // CARFAC_IHC_H
\ No newline at end of file
--- a/trunk/carfac/ihc_coeffs.h	Fri May 31 21:46:48 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-//
-//  ihc_coeffs.h
-//  CARFAC Open Source C++ Library
-//
-//  Created by Alex Brandmeyer on 5/10/13.
-//
-// 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.
-
-#ifndef CARFAC_IHC_COEFFS_H
-#define CARFAC_IHC_COEFFS_H
-
-#include "carfac_common.h"
-
-struct IHCCoeffs {
-  bool just_half_wave_rectify;
-  bool one_capacitor;
-  FPType lpf_coeff;
-  FPType out1_rate;
-  FPType in1_rate;
-  FPType out2_rate;
-  FPType in2_rate;
-  FPType output_gain;
-  FPType rest_output;
-  FPType rest_cap1;
-  FPType rest_cap2;
-  FPType ac_coeff;
-  FPType cap1_voltage;
-  FPType cap2_voltage;
-};
-
-#endif  // CARFAC_IHC_COEFFS_H
\ No newline at end of file
--- a/trunk/carfac/ihc_params.h	Fri May 31 21:46:48 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-//
-//  ihc_params.h
-//  CARFAC Open Source C++ Library
-//
-//  Created by Alex Brandmeyer on 5/10/13.
-//
-// 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.
-
-#ifndef CARFAC_IHC_PARAMS_H
-#define CARFAC_IHC_PARAMS_H
-
-#include "carfac_common.h"
-
-struct IHCParams {
-  IHCParams() {
-    just_half_wave_rectify = false;
-    one_capacitor = true;
-    tau_lpf = 0.000080;
-    tau1_out = 0.0005;
-    tau1_in = 0.010;
-    tau2_out = 0.0025;
-    tau2_in = 0.005;
-    ac_corner_hz = 20.0;
-  };
-  bool just_half_wave_rectify;
-  bool one_capacitor;
-  FPType tau_lpf;
-  FPType tau1_out;
-  FPType tau1_in;
-  FPType tau2_out;
-  FPType tau2_in;
-  FPType ac_corner_hz;
-};
-
-#endif  // CARFAC_IHC_PARAMS_H
\ No newline at end of file
--- a/trunk/carfac/ihc_state.h	Fri May 31 21:46:48 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-//
-//  ihc_state.h
-//  CARFAC Open Source C++ Library
-//
-//  Created by Alex Brandmeyer on 5/10/13.
-//
-// 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.
-
-#ifndef CARFAC_IHC_STATE_H
-#define CARFAC_IHC_STATE_H
-
-#include "carfac_common.h"
-
-struct IHCState {
-  FloatArray ihc_out;
-  FloatArray ihc_accum;
-  FloatArray cap1_voltage;
-  FloatArray cap2_voltage;
-  FloatArray lpf1_state;
-  FloatArray lpf2_state;
-  FloatArray ac_coupler;
-};
-
-#endif  // CARFAC_IHC_STATE_H
\ No newline at end of file
--- a/trunk/carfac/sai.cc	Fri May 31 21:46:48 2013 +0000
+++ b/trunk/carfac/sai.cc	Tue Jun 04 18:30:22 2013 +0000
@@ -35,8 +35,8 @@
       .sin();
 }
 
-void SAI::RunSegment(const std::vector<FloatArray>& input,
-                     Float2dArray* output_frame) {
+void SAI::RunSegment(const std::vector<ArrayX>& input,
+                     ArrayXX* output_frame) {
   assert(!input.empty() || input.size() <= params_.window_width &&
          "Unexpected input size.");
   assert(input[0].size() == params_.n_ch &&
@@ -60,8 +60,8 @@
   *output_frame = output_buffer_;
 }
 
-void SAI::StabilizeSegment(const Float2dArray& input_buffer,
-                           Float2dArray* output_buffer) const {
+void SAI::StabilizeSegment(const ArrayXX& input_buffer,
+                           ArrayXX* output_buffer) const {
   // Windows are always approximately 50% overlapped.
   float window_hop = params_.window_width / 2;
   int window_start = (input_buffer.cols() - params_.window_width) -
@@ -72,14 +72,14 @@
   for (int i = 0; i < params_.n_ch; ++i) {
     // TODO(ronw): Rename this here and in the Matlab code since the
     // input doesn't have to contain naps.
-    const FloatArray& nap_wave = input_buffer.row(i);
+    const ArrayX& nap_wave = input_buffer.row(i);
     // TODO(ronw): Smooth row.
 
     for (int w = 0; w < params_.n_window_pos; ++w) {
       int current_window_offset = w * window_hop;
       // Choose a trigger point.
       int trigger_time;
-      const FloatArray& trigger_window =
+      const ArrayX& trigger_window =
           nap_wave.segment(window_range_start + current_window_offset,
                            params_.window_width);
       FPType peak_val = (trigger_window * window_).maxCoeff(&trigger_time);
--- a/trunk/carfac/sai.h	Fri May 31 21:46:48 2013 +0000
+++ b/trunk/carfac/sai.h	Tue Jun 04 18:30:22 2013 +0000
@@ -22,8 +22,7 @@
 
 #include <vector>
 
-// TODO(ronw): Rename this file to common.h
-#include "carfac_common.h"
+#include "common.h"
 
 // Design parameters for a single SAI.
 struct SAIParams {
@@ -57,25 +56,25 @@
   //
   // The input should have dimensionality of params_.window_width by
   // params_.n_ch.  Inputs containing too few frames are zero-padded.
-  // FIXME: Float2DArray input type would be less awkward.
-  void RunSegment(const std::vector<FloatArray>& input,
-                  Float2dArray* output_output_frame);
+  // FIXME: ArrayXX input type would be less awkward.
+  void RunSegment(const std::vector<ArrayX>& input,
+                  ArrayXX* output_output_frame);
 
  private:
   // Process successive windows within input_buffer, choose trigger
   // points, and blend each window into output_buffer.
-  void StabilizeSegment(const Float2dArray& input_buffer,
-                        Float2dArray* output_buffer) const;
+  void StabilizeSegment(const ArrayXX& input_buffer,
+                        ArrayXX* output_buffer) const;
 
   SAIParams params_;
   // Window function to apply before selecting a trigger point.
   // Size: params_.window_width.
-  FloatArray window_;
+  ArrayX window_;
   // Buffer to store a large enough window of input frames to compute
   // a full SAI frame.  Size: params_.n_ch by params_.buffer_width.
-  Float2dArray input_buffer_;
+  ArrayXX input_buffer_;
   // Output frame buffer.  Size: params_.n_ch by params_.width.
-  Float2dArray output_buffer_;
+  ArrayXX output_buffer_;
 };
 
-#endif  // CARFAC_SAI_H_
+#endif  // CARFAC_SAI_H_
\ No newline at end of file
--- a/trunk/carfac/sai_test.cc	Fri May 31 21:46:48 2013 +0000
+++ b/trunk/carfac/sai_test.cc	Tue Jun 04 18:30:22 2013 +0000
@@ -27,15 +27,15 @@
 using testing::Values;
 using std::vector;
 
-vector<FloatArray> CreateZeroSegment(int n_ch, int length) {
-  vector<FloatArray> segment;
+vector<ArrayX> CreateZeroSegment(int n_ch, int length) {
+  vector<ArrayX> segment;
   for (int i = 0; i < length; ++i) {
-    segment.push_back(FloatArray::Zero(n_ch));
+    segment.push_back(ArrayX::Zero(n_ch));
   }
   return segment;
 }
 
-bool HasPeakAt(const Float2dArray& frame, int index) {
+bool HasPeakAt(const ArrayXX& frame, int index) {
   if (index == 0) {
     return frame(index) > frame(index + 1);
   } else if (index == frame.size() - 1) {
@@ -57,7 +57,7 @@
 };
 
 TEST_P(SAIPeriodicInputTest, SingleChannelPulseTrain) {
-  vector<FloatArray> segment = CreateZeroSegment(1, 38);
+  vector<ArrayX> segment = CreateZeroSegment(1, 38);
   for (int i = phase_; i < segment.size(); i += period_) {
     segment[i](0) = 1;
   }
@@ -72,7 +72,7 @@
   sai_params.n_window_pos = 2;
 
   SAI sai(sai_params);
-  Float2dArray sai_frame;
+  ArrayXX sai_frame;
   sai.RunSegment(segment, &sai_frame);
 
   // The output should have peaks at the same positions, regardless of