changeset 564:9c4c3675c3f8

* Added class Ear, and moved the CARFAC members AGC CAR IHC into Ear. CARFAC now holds an array of Ear. TBD what is best. * Moved the files around, and introduced a makefile that builds unittests using GTest. (Note, GTest path is configured in makefile atm.). - two moronic tests implemented. :)
author Ulf.Hammarqvist@gmail.com
date Sun, 20 May 2012 22:36:47 +0000
parents fb602edc2d55
children 3e2e0ab4f708
files branches/carfac_cpp/include/AGC.h branches/carfac_cpp/include/CAR.h branches/carfac_cpp/include/CARFAC.h branches/carfac_cpp/include/CARFAC_common.h branches/carfac_cpp/include/Ear.h branches/carfac_cpp/include/IHC.h branches/carfac_cpp/makefile branches/carfac_cpp/src/AGC.cpp branches/carfac_cpp/src/AGC.h branches/carfac_cpp/src/CAR.cpp branches/carfac_cpp/src/CAR.h branches/carfac_cpp/src/CARFAC.cpp branches/carfac_cpp/src/CARFAC.h branches/carfac_cpp/src/CARFAC_common.h branches/carfac_cpp/src/Ear.cpp branches/carfac_cpp/src/IHC.cpp branches/carfac_cpp/src/IHC.h branches/carfac_cpp/unittest/AGC_unittest.cpp branches/carfac_cpp/unittest/CARFAC_unittest.cpp
diffstat 19 files changed, 388 insertions(+), 301 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/branches/carfac_cpp/include/AGC.h	Sun May 20 22:36:47 2012 +0000
@@ -0,0 +1,58 @@
+#ifndef AGC_H_
+#define AGC_H_
+
+#include "CARFAC_common.h"
+
+class AGC_parameters {
+public:
+  AGC_parameters():
+    n_stages_(4),
+    time_constants_({0.002*1, 0.002*4, 0.002*16, 0.002*64}),
+    agc_stage_gain_(2),
+    decimation_({8, 2, 2, 2}),
+    agc1_scales_({1.0, 1.4,  2.0, 2.8}),
+    agc2_scales_({1.6, 2.25, 3.2, 4.5}),
+    detect_scale_(0.25),
+    agc_mix_coeff_(0.5){
+    // do nothing more
+  }
+
+  virtual ~AGC_parameters(){
+    // do nothing
+  }
+
+  int n_stages_;
+  FloatArray time_constants_;
+  float agc_stage_gain_;
+  FloatArray decimation_;
+  FloatArray agc1_scales_;
+  FloatArray agc2_scales_;
+  float detect_scale_;
+  float agc_mix_coeff_;
+};
+
+class AGC_coefficients {
+public:
+  AGC_coefficients(AGC_parameters*, float, int);
+  virtual ~AGC_coefficients();
+
+  int n_ch_;
+  int n_agc_stages_;
+  float agc_stage_gain_;
+  FloatArray agc_epsilon_;
+  FloatArray decimation_;
+  FloatArray agc_polez1_;
+  FloatArray agc_polez2_;
+  FloatArray agc_spatial_iterations_;
+  FloatMatrix agc_spatial_fir_;
+  FloatArray agc_spatial_n_taps_;
+  FloatArray agc_mix_coeffs_;
+  float agc_gain_;
+  float detect_scale_;
+  
+private:
+  AGC_coefficients();
+  FloatArray Build_FIR_coeffs(float, float, int*, int*);
+};
+
+#endif /* AGC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/branches/carfac_cpp/include/CAR.h	Sun May 20 22:36:47 2012 +0000
@@ -0,0 +1,63 @@
+#ifndef CAR_H_
+#define CAR_H_
+
+#include "CARFAC_common.h"
+#include <cmath>
+
+const double kDefaultErbBreakFreq = 165.3;
+const double kDefaultErbQ = 1000/(24.7*4.37);
+
+class CAR_parameters{
+public:
+  CAR_parameters():
+    velocity_scale_(0.2),
+    v_offset_(0.01),
+    v2_corner_(0.2),
+    v_damp_max_(0.01),
+    min_zeta_(0.10),
+    first_pole_theta_(0.085*kPi),
+    zero_ratio_(sqrt(2)),
+    high_f_damping_compression_(0.5),
+    erb_per_step_(0.5),
+    min_pole_hz_(30),
+    erb_break_freq_(kDefaultErbBreakFreq),
+    erb_q_(kDefaultErbQ)
+  {
+    // do nothing more
+  }
+
+  virtual ~CAR_parameters(){
+    // do nothing
+  }
+
+  float velocity_scale_;
+  float v_offset_;
+  float v2_corner_;
+  float v_damp_max_;
+  float min_zeta_;
+  float first_pole_theta_;
+  float zero_ratio_;
+  float high_f_damping_compression_;
+  float erb_per_step_;
+  float min_pole_hz_;
+  float erb_break_freq_;
+  float erb_q_;
+};
+
+class CAR_coefficients{
+public:
+  CAR_coefficients(CAR_parameters*, float, FloatArray);
+  virtual ~CAR_coefficients();
+
+  FloatArray r1_coeffs_;
+  FloatArray a0_coeffs_;
+  FloatArray c0_coeffs_;
+  FloatArray h_coeffs_;
+  FloatArray g0_coeffs_;
+  FloatArray zr_coeffs_;
+
+private:
+  CAR_coefficients();
+};
+
+#endif /* CAR_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/branches/carfac_cpp/include/CARFAC.h	Sun May 20 22:36:47 2012 +0000
@@ -0,0 +1,32 @@
+#ifndef CARFAC_H_
+#define CARFAC_H_
+
+#include "CAR.h"
+#include "IHC.h"
+#include "AGC.h"
+#include "Ear.h"
+#include <vector>
+
+const double kDefaultFs = 22050;
+
+class CARFAC{
+public:
+  CARFAC(int, CAR_parameters*, IHC_parameters*, AGC_parameters*, int);
+  virtual ~CARFAC();
+  static float ERB_Hz(float, float, float);
+
+  float fs_;
+
+  int n_ch_; // these three, push down to ear level?
+  float max_channels_per_octave_;
+  FloatArray pole_freqs_;
+
+  int n_ears_;
+  std::vector<Ear> ears_;
+
+private:
+  CARFAC(){};
+
+};
+
+#endif /* CARFAC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/branches/carfac_cpp/include/CARFAC_common.h	Sun May 20 22:36:47 2012 +0000
@@ -0,0 +1,10 @@
+#ifndef CARFAC_COMMON_TYPEDEFS_H_
+#define CARFAC_COMMON_TYPEDEFS_H_
+
+#include <vector>
+
+typedef std::vector<float> FloatArray;
+typedef std::vector<FloatArray> FloatMatrix;
+const double kPi = 3.1415926;
+
+#endif /* CARFAC_COMMON_TYPEDEFS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/branches/carfac_cpp/include/Ear.h	Sun May 20 22:36:47 2012 +0000
@@ -0,0 +1,35 @@
+/*
+ * Ear.h
+ *
+ *  Created on: 16 maj 2012
+ *      Author: ulha
+ */
+
+#ifndef EAR_H_
+#define EAR_H_
+
+#include "CAR.h"
+#include "IHC.h"
+#include "AGC.h"
+
+class Ear {
+public:
+  Ear(CAR_parameters*, IHC_parameters*, AGC_parameters*, FloatArray, int, float);
+
+  CAR_parameters car_params_;
+  IHC_parameters ihc_params_;
+  AGC_parameters agc_params_;
+
+  CAR_coefficients* car_coeffs_p_;
+  IHC_coefficients* ihc_coeffs_p_;
+  AGC_coefficients* agc_coeffs_p_;
+
+  virtual
+  ~Ear();
+
+private:
+  Ear();
+
+};
+
+#endif /* EAR_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/branches/carfac_cpp/include/IHC.h	Sun May 20 22:36:47 2012 +0000
@@ -0,0 +1,38 @@
+#ifndef IHC_H_
+#define IHC_H_
+
+// not sure how to best deal with the "three style" IHC - ulha
+class IHC_parameters{
+public:
+  IHC_parameters() :
+    tau_lpf_(0.000080),
+    tau1_out_(0.010),
+    tau1_in_(0.20),
+    tau2_out_(0.0025),
+    tau2_in_(0.005){
+    // do nothing more
+  }
+
+  virtual ~IHC_parameters(){
+    // do nothing
+  }
+
+  float tau_lpf_;
+  float tau1_out_;
+  float tau1_in_;
+  float tau2_out_;
+  float tau2_in_;
+};
+
+class IHC_coefficients{
+public:
+  IHC_coefficients(IHC_parameters*, float, int);
+  virtual ~IHC_coefficients();
+
+  float saturation_output_;
+
+private:
+  IHC_coefficients();
+};
+
+#endif /* IHC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/branches/carfac_cpp/makefile	Sun May 20 22:36:47 2012 +0000
@@ -0,0 +1,63 @@
+# How to use:
+# Add your cpp code to the list in UNITS.
+#
+# Unit test:
+# If you want to add a test build target for that cpp file ONLY, please see 
+# example "AGC_unittest". (no need to add explicit build rule)
+#
+# If you intend to test a class including instanciated members, you need to 
+# make a explicit rule to link properly. See example "CARFAC_unittest".
+
+SRC_HEADERDIR = include
+SRC_DIR = src
+SRC_TESTDIR = unittest
+
+GTEST_DIR = ../../../googletest
+
+SRC_HEADERS = $(SRC_HEADERDIR)/*.h
+
+CPPFLAGS += -I$(SRC_HEADERDIR) -I$(GTEST_DIR)/include
+CXXFLAGS += -g -Wall -Wextra -std=gnu++0x #IMPORTANT note gnu++0x
+
+UNITS = AGC CAR CARFAC Ear IHC #Add build units here (without the .cpp)
+SRC_OBJ = $(addprefix $(SRC_DIR)/, $(addsuffix .o, $(UNITS)))
+
+GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
+                $(GTEST_DIR)/include/gtest/internal/*.h
+                
+GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
+
+all : CARFAC_unittest AGC_unittest #make some other "main" target
+
+clean :
+	rm -f *.o *.a src/*.o unittest/*.o *_unittest.exe
+
+CARFAC_unittest : $(SRC_TESTDIR)/CARFAC_unittest.o $(SRC_OBJ)
+
+# pattern magic
+$(SRC_DIR)/%.o : %.cpp $(SRC_HEADERS) #normal source
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(.SOURCE)
+
+$(SRC_TESTDIR)/%.o : %.cpp $(SRC_HEADERS) $(GTEST_HEADERS) # unittest
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(.SOURCE)
+
+%_unittest : $(SRC_DIR)/%.o $(SRC_TESTDIR)/%_unittest.o gtest_main.a #unittest
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
+#	./$@.exe # launches the test - disabled, as failing tests stops the build
+# end pattern magic
+
+# gtest stuff
+gtest-all.o : $(GTEST_SRCS_)
+	$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
+            $(GTEST_DIR)/src/gtest-all.cc
+            
+gtest_main.o : $(GTEST_SRCS_)
+	$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
+            $(GTEST_DIR)/src/gtest_main.cc
+
+gtest.a : gtest-all.o
+	$(AR) $(ARFLAGS) $@ $^
+
+gtest_main.a : gtest-all.o gtest_main.o
+	$(AR) $(ARFLAGS) $@ $^
+# end gtest stuff
\ No newline at end of file
--- a/branches/carfac_cpp/src/AGC.cpp	Sat May 12 04:31:59 2012 +0000
+++ b/branches/carfac_cpp/src/AGC.cpp	Sun May 20 22:36:47 2012 +0000
@@ -3,17 +3,16 @@
 #include <stdlib.h>
 #include <stdio.h>  
 
-AGC_coefficients::AGC_coefficients(AGC_parameters* AGC_params,
+AGC_coefficients::AGC_coefficients(AGC_parameters* AGC_params_p,
                                    float fs, int n_ch){
   float decim = 1.0;
   float total_DC_gain = 0.0;
   float tau, ntimes, delay, spread_sq, u, p, dp;
   int n_taps = 0, n_iterations = 1;
-//  bool FIR_OK = false;
 
   n_ch_ = n_ch;
-  n_agc_stages_ = AGC_params->n_stages_;
-  agc_stage_gain_ = AGC_params->agc_stage_gain_;
+  n_agc_stages_ = AGC_params_p->n_stages_;
+  agc_stage_gain_ = AGC_params_p->agc_stage_gain_;
   
   // FloatArray initialization using assign method - dont know if this is good enough
   agc_epsilon_.assign(n_agc_stages_, 0.0); //the 1/(tau*fs) roughly
@@ -22,14 +21,14 @@
   agc_spatial_iterations_ = agc_epsilon_;
   agc_spatial_n_taps_ = agc_epsilon_;
   agc_mix_coeffs_ = agc_epsilon_;
-  FloatArray agc1_scales = AGC_params->agc1_scales_;
-  FloatArray agc2_scales = AGC_params->agc2_scales_;
+  FloatArray agc1_scales = AGC_params_p->agc1_scales_;
+  FloatArray agc2_scales = AGC_params_p->agc2_scales_;
   FloatArray agc_spatial_FIR;
-  decimation_ = AGC_params->decimation_;
+  decimation_ = AGC_params_p->decimation_;
   
   for(int stage=0; stage < n_agc_stages_; stage++){
-    tau = AGC_params->time_constants_[stage];
-    decim *= AGC_params->decimation_[stage];
+    tau = AGC_params_p->time_constants_[stage];
+    decim *= AGC_params_p->decimation_[stage];
     agc_epsilon_[stage] = 1.0 - exp(-decim/(tau*fs));
     ntimes = tau * (fs/decim);
     delay = (agc2_scales[stage]-agc1_scales[stage])/ntimes;
@@ -41,28 +40,6 @@
     agc_polez1_[stage] = p - dp;
     agc_polez2_[stage] = p + dp;
 
-//    while(!FIR_OK){
-//      switch(n_taps){
-//        case 0:
-//          n_taps = 3;
-//          break;
-//        case 3:
-//          n_taps = 5;
-//          break;
-//        case 5:
-//          n_iterations++;
-//          if(n_iterations > 16){
-//            printf("Too many n_iterations in CARFAC_DesignAGC\n");
-//            exit(1);
-//          }
-//          break;
-//        default:
-//          printf("Bad n_taps in CARFAC_DesignAGC\n");
-//          exit(1);
-//      }
-//      agc_spatial_FIR = FIR_coeffs(n_taps, spread_sq, delay, n_iterations, &FIR_OK);
-//    }
-
     agc_spatial_FIR = Build_FIR_coeffs(spread_sq, delay, &n_iterations, &n_taps);
 
     agc_spatial_iterations_[stage] = (float) n_iterations;
@@ -72,54 +49,20 @@
     for(int i =0; i < 3; i++)
       agc_spatial_fir_[stage].push_back(agc_spatial_FIR[i]);
       
-    total_DC_gain += pow(AGC_params->agc_stage_gain_,stage);
+    total_DC_gain += pow(AGC_params_p->agc_stage_gain_,stage);
     
     if(stage == 0)
       agc_mix_coeffs_[stage] = 0.0;
     else
-      agc_mix_coeffs_[stage] = AGC_params->agc_mix_coeff_/(tau * (fs/decim));
+      agc_mix_coeffs_[stage] = AGC_params_p->agc_mix_coeff_/(tau * (fs/decim));
   }
   agc_gain_ = total_DC_gain;
-  detect_scale_ = AGC_params->detect_scale_/total_DC_gain;
+  detect_scale_ = AGC_params_p->detect_scale_/total_DC_gain;
 }
 AGC_coefficients::~AGC_coefficients(){
   // TODO Auto-generated destructor stub
 }
 
-//FloatArray  AGC_coefficients::FIR_coeffs(int n_taps, float var, float mn, int n_iter, bool* ptr_FIR_OK)
-//{
-//  float a, b;
-//  FloatArray FIR(3);
-//  mn /= n_iter;
-//  var /= n_iter;
-//
-//  switch(n_taps){
-//    case 3:
-//      a = (var + mn*mn - mn)/2;
-//      b = (var + mn*mn + mn)/2;
-//      FIR[0] = a;
-//      FIR[1] = 1.0 - a - b;
-//      FIR[2] = b;
-//      if(FIR[1] >= 0.2)
-//        *ptr_FIR_OK = true;
-//      break;
-//    case 5:
-//      a = ((var + mn*mn)*2/5 - mn*2/3)/2;
-//      b = ((var + mn*mn)*2/5 + mn*2/3)/2;
-//      FIR[0] = a/2;
-//      FIR[1] = 1.0 - a - b;
-//      FIR[2] = b;
-//      if(FIR[1] >= 0.1)
-//        *ptr_FIR_OK = true;
-//      break;
-//    default:
-//      printf("Bad n_taps in AGC_spatial_FIR\n");
-//      exit(1);
-//  }
-//
-//  return FIR;
-//}
-
 FloatArray AGC_coefficients::Build_FIR_coeffs(float var, float mn, int* ptr_iters, int* ptr_taps){
   float a, b;
   FloatArray FIR(3);
--- a/branches/carfac_cpp/src/AGC.h	Sat May 12 04:31:59 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-#ifndef AGC_H_
-#define AGC_H_
-
-#include "CARFAC_common.h"
-
-class AGC_parameters {
-public:
-  AGC_parameters():
-    n_stages_(4),
-    time_constants_({0.002*1, 0.002*4, 0.002*16, 0.002*64}),
-    agc_stage_gain_(2),
-    decimation_({8, 2, 2, 2}),
-    agc1_scales_({1.0, 1.4,  2.0, 2.8}),
-    agc2_scales_({1.6, 2.25, 3.2, 4.5}),
-    detect_scale_(0.25),
-    agc_mix_coeff_(0.5){
-    // do nothing more
-  }
-
-  virtual ~AGC_parameters(){
-    // do nothing
-  }
-
-  int n_stages_;
-  FloatArray time_constants_;
-  float agc_stage_gain_;
-  FloatArray decimation_;
-  FloatArray agc1_scales_;
-  FloatArray agc2_scales_;
-  float detect_scale_;
-  float agc_mix_coeff_;
-};
-
-class AGC_coefficients {
-public:
-  AGC_coefficients(AGC_parameters*, float, int);
-  virtual ~AGC_coefficients();
-
-  int n_ch_;
-  int n_agc_stages_;
-  float agc_stage_gain_;
-  FloatArray agc_epsilon_;
-  FloatArray decimation_;
-  FloatArray agc_polez1_;
-  FloatArray agc_polez2_;
-  FloatArray agc_spatial_iterations_;
-  FloatMatrix agc_spatial_fir_;
-  FloatArray agc_spatial_n_taps_;
-  FloatArray agc_mix_coeffs_;
-  float agc_gain_;
-  float detect_scale_;
-  
-private:
-  AGC_coefficients();
-//  FloatArray FIR_coeffs(int, float, float, int, bool*);
-  FloatArray Build_FIR_coeffs(float, float, int*, int*);
-};
-
-#endif /* AGC_H_ */
--- a/branches/carfac_cpp/src/CAR.cpp	Sat May 12 04:31:59 2012 +0000
+++ b/branches/carfac_cpp/src/CAR.cpp	Sun May 20 22:36:47 2012 +0000
@@ -3,10 +3,10 @@
 #include "CARFAC.h"
 #include <cmath>
 
-CAR_coefficients::CAR_coefficients(CAR_parameters* car_params, float fs,
+CAR_coefficients::CAR_coefficients(CAR_parameters* car_params_p, float fs,
                                    FloatArray pole_freqs){
 
-  float f = pow(car_params->zero_ratio_, 2) + 1;
+  float f = pow(car_params_p->zero_ratio_, 2) + 1;
 
   // TODO: dirty FloatArray initialization.
   r1_coeffs_= pole_freqs;
@@ -20,7 +20,7 @@
 
   float min_zeta_mod;
   float x;
-  float ff = car_params->high_f_damping_compression_;
+  float ff = car_params_p->high_f_damping_compression_;
 
   // TODO: temp loop until we get eigen in  (or we just leave it like this)
   for(float i=0; i<pole_freqs.size(); i++){
@@ -31,10 +31,10 @@
       x = theta[i]/kPi;
       zr_coeffs_[i] = kPi * (x - ff * x*x*x);
 
-      min_zeta_mod = (car_params->min_zeta_ + 0.25 * (CARFAC::ERB_Hz(
-                      pole_freqs[i], car_params->erb_break_freq_,
-                      car_params->erb_q_) / pole_freqs[i]
-                     - car_params->min_zeta_));
+      min_zeta_mod = (car_params_p->min_zeta_ + 0.25 * (CARFAC::ERB_Hz(
+                      pole_freqs[i], car_params_p->erb_break_freq_,
+                      car_params_p->erb_q_) / pole_freqs[i]
+                     - car_params_p->min_zeta_));
 
       r1_coeffs_[i] = 1-zr_coeffs_[i]*min_zeta_mod;
 
--- a/branches/carfac_cpp/src/CAR.h	Sat May 12 04:31:59 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-#ifndef CAR_H_
-#define CAR_H_
-
-#include "CARFAC_common.h"
-#include <cmath>
-
-const double kDefaultErbBreakFreq = 165.3;
-const double kDefaultErbQ = 1000/(24.7*4.37);
-
-class CAR_parameters{
-public:
-  CAR_parameters():
-    velocity_scale_(0.2),
-    v_offset_(0.01),
-    v2_corner_(0.2),
-    v_damp_max_(0.01),
-    min_zeta_(0.10),
-    first_pole_theta_(0.085*kPi),
-    zero_ratio_(sqrt(2)),
-    high_f_damping_compression_(0.5),
-    erb_per_step_(0.5),
-    min_pole_hz_(30),
-    erb_break_freq_(kDefaultErbBreakFreq),
-    erb_q_(kDefaultErbQ)
-  {
-    // do nothing more
-  }
-
-  virtual ~CAR_parameters(){
-    // do nothing
-  }
-
-  float velocity_scale_;
-  float v_offset_;
-  float v2_corner_;
-  float v_damp_max_;
-  float min_zeta_;
-  float first_pole_theta_;
-  float zero_ratio_;
-  float high_f_damping_compression_;
-  float erb_per_step_;
-  float min_pole_hz_;
-  float erb_break_freq_;
-  float erb_q_;
-};
-
-class CAR_coefficients{
-public:
-  CAR_coefficients(CAR_parameters*, float, FloatArray);
-  virtual ~CAR_coefficients();
-
-  FloatArray r1_coeffs_;
-  FloatArray a0_coeffs_;
-  FloatArray c0_coeffs_;
-  FloatArray h_coeffs_;
-  FloatArray g0_coeffs_;
-  FloatArray zr_coeffs_;
-
-private:
-  CAR_coefficients();
-};
-
-#endif /* CAR_H_ */
--- a/branches/carfac_cpp/src/CARFAC.cpp	Sat May 12 04:31:59 2012 +0000
+++ b/branches/carfac_cpp/src/CARFAC.cpp	Sun May 20 22:36:47 2012 +0000
@@ -4,18 +4,17 @@
 #include "CAR.h"
 #include "IHC.h"
 #include "AGC.h"
+#include "Ear.h"
 
 #include "CARFAC_common.h"
 
 CARFAC::CARFAC(int fs = kDefaultFs,
               CAR_parameters* car_params = new CAR_parameters(),
               IHC_parameters* ihc_params = new IHC_parameters(),
-              AGC_parameters* agc_params = new AGC_parameters()) : n_ears_(0) {
+              AGC_parameters* agc_params = new AGC_parameters(),
+              int n_ears = 1){
 
-  // Design is to take ownership. Preferences? Make copies, call by value, etc?
-  car_params_ = car_params;
-  ihc_params_ = ihc_params;
-  agc_params_ = agc_params;
+  fs_ = fs;
 
   float pole_hz = car_params->first_pole_theta_* fs / (2*kPi);
   while (pole_hz > car_params->min_pole_hz_){
@@ -25,14 +24,11 @@
                     car_params->erb_q_);
   }
   n_ch_ = pole_freqs_.size();
-
   max_channels_per_octave_ = log(2) / log(pole_freqs_[0]/pole_freqs_[1]);
 
-  //TODO: pass const references?
-  car_coeffs_ = new CAR_coefficients(car_params_, fs_, pole_freqs_);
-  ihc_coeffs_ = new IHC_coefficients(ihc_params_, fs_, n_ch_);
-  agc_coeffs_ = new AGC_coefficients(agc_params_, fs_, n_ch_);
-
+  n_ears_ = n_ears;
+  Ear* ear = new Ear(car_params, ihc_params, agc_params, pole_freqs_, n_ch_, fs);
+  ears_.assign(n_ears_, *ear);
 }
 
 float CARFAC::ERB_Hz(float cf_hz, float erb_break_freq, float erb_q){
@@ -40,14 +36,5 @@
 }
 
 CARFAC::~CARFAC() {
-  delete car_coeffs_;
-  delete ihc_coeffs_;
-  delete agc_coeffs_;
-
-  //TODO: as the current design takes ownership OR creates news params,
-  //deletion is a ambiguos. Revise this design?
-
-  //delete car_params_;
-  //delete ihc_params_;
-  //delete agc_params_;
+  //TODO: clean up
 }
--- a/branches/carfac_cpp/src/CARFAC.h	Sat May 12 04:31:59 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#ifndef CARFAC_H_
-#define CARFAC_H_
-
-#include "CAR.h"
-#include "IHC.h"
-#include "AGC.h"
-
-const double kDefaultFs = 22050;
-
-class CARFAC{
-public:
-  CARFAC(int, CAR_parameters*, IHC_parameters*, AGC_parameters*);
-  virtual ~CARFAC();
-  static float ERB_Hz(float, float, float);
-
-  float fs_;
-  float max_channels_per_octave_;
-
-  CAR_coefficients* car_coeffs_;
-  CAR_parameters* car_params_;
-
-  IHC_coefficients* ihc_coeffs_;
-  IHC_parameters* ihc_params_;
-
-  int n_ch_;
-  FloatArray pole_freqs_;
-
-  AGC_coefficients* agc_coeffs_;
-  AGC_parameters* agc_params_;
-
-  int n_ears_;
-};
-
-#endif /* CARFAC_H_ */
--- a/branches/carfac_cpp/src/CARFAC_common.h	Sat May 12 04:31:59 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-#ifndef CARFAC_COMMON_TYPEDEFS_H_
-#define CARFAC_COMMON_TYPEDEFS_H_
-
-#include <vector>
-
-typedef std::vector<float> FloatArray;
-typedef std::vector<FloatArray> FloatMatrix;
-const double kPi = 3.1415926;
-
-#endif /* CARFAC_COMMON_TYPEDEFS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/branches/carfac_cpp/src/Ear.cpp	Sun May 20 22:36:47 2012 +0000
@@ -0,0 +1,25 @@
+/*
+ * Ear.cpp
+ *
+ *  Created on: 16 maj 2012
+ *      Author: ulha
+ */
+
+#include "Ear.h"
+#include "CAR.h"
+#include "IHC.h"
+#include "AGC.h"
+
+Ear::Ear(CAR_parameters* car_params, IHC_parameters* ihc_params, AGC_parameters* agc_params, FloatArray pole_freqs, int n_ch, float fs){
+  car_params_ = *car_params;
+  ihc_params_ = *ihc_params;
+  agc_params_ = *agc_params;
+
+  car_coeffs_p_ = new CAR_coefficients(&car_params_, fs, pole_freqs);
+  ihc_coeffs_p_ = new IHC_coefficients(&ihc_params_, fs, n_ch);
+  agc_coeffs_p_ = new AGC_coefficients(&agc_params_, fs, n_ch);
+}
+
+Ear::~Ear() {
+  // TODO Auto-generated destructor stub
+}
--- a/branches/carfac_cpp/src/IHC.cpp	Sat May 12 04:31:59 2012 +0000
+++ b/branches/carfac_cpp/src/IHC.cpp	Sun May 20 22:36:47 2012 +0000
@@ -1,6 +1,6 @@
 #include "IHC.h"
 
-IHC_coefficients::IHC_coefficients(IHC_parameters* IHC_params, float fs, int n_ch){
+IHC_coefficients::IHC_coefficients(IHC_parameters* IHC_params_p, float fs, int n_ch){
   // TODO stuff!
 }
 
--- a/branches/carfac_cpp/src/IHC.h	Sat May 12 04:31:59 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-#ifndef IHC_H_
-#define IHC_H_
-
-// not sure how to best deal with the "three style" IHC - ulha
-class IHC_parameters{
-public:
-  IHC_parameters() :
-    tau_lpf_(0.000080),
-    tau1_out_(0.010),
-    tau1_in_(0.20),
-    tau2_out_(0.0025),
-    tau2_in_(0.005){
-    // do nothing more
-  }
-
-  virtual ~IHC_parameters(){
-    // do nothing
-  }
-
-  float tau_lpf_;
-  float tau1_out_;
-  float tau1_in_;
-  float tau2_out_;
-  float tau2_in_;
-};
-
-class IHC_coefficients{
-public:
-  IHC_coefficients(IHC_parameters*, float, int);
-  virtual ~IHC_coefficients();
-
-  float saturation_output_;
-
-private:
-  IHC_coefficients();
-};
-
-#endif /* IHC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/branches/carfac_cpp/unittest/AGC_unittest.cpp	Sun May 20 22:36:47 2012 +0000
@@ -0,0 +1,9 @@
+#include "AGC.h"
+#include "gtest/gtest.h"
+
+// Tests Bar().
+TEST(BarTest, Foo) {
+  // This test is named "Foo", and belongs to the "BarTest"
+  // test case.
+  EXPECT_EQ(1, -2);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/branches/carfac_cpp/unittest/CARFAC_unittest.cpp	Sun May 20 22:36:47 2012 +0000
@@ -0,0 +1,28 @@
+#include "CARFAC.h"
+#include "CARFAC_common.h"
+#include "gtest/gtest.h"
+
+/*
+ * CARFACDesignTest - Test suite for constructor related tests.
+ */
+TEST(CARFACDesignTest, SampleRate) {
+  CAR_parameters * car_params = new CAR_parameters();;
+  IHC_parameters * ihc_params = new IHC_parameters();
+  AGC_parameters * agc_params = new AGC_parameters();
+
+  int arbitrary_number = 1347;
+
+  CARFAC* fooCarfac = new CARFAC(arbitrary_number, car_params, ihc_params, agc_params, 1);
+  EXPECT_EQ(fooCarfac->fs_, arbitrary_number);
+}
+
+TEST(CARFACDesignTest, NumberOfEars) {
+  CAR_parameters * car_params = new CAR_parameters();;
+  IHC_parameters * ihc_params = new IHC_parameters();
+  AGC_parameters * agc_params = new AGC_parameters();
+
+  int arbitrary_number = 1347;
+
+  CARFAC* fooCarfac = new CARFAC(arbitrary_number, car_params, ihc_params, agc_params, 2);
+  EXPECT_EQ(fooCarfac->n_ears_, foobadooba->ears_.size());
+}