changeset 645:3f01a136c537

DISALLOW_COPY_AND_ASSIGN in CARFAC classes and fix a few funny indentations.
author ronw@google.com
date Tue, 11 Jun 2013 17:59:08 +0000
parents 16dfff1de47a
children e76951e4da20
files carfac/carfac.cc carfac/carfac.h carfac/carfac_output.cc carfac/carfac_output.h carfac/common.h carfac/ear.cc carfac/ear.h
diffstat 7 files changed, 112 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/carfac/carfac.cc	Tue Jun 11 15:04:55 2013 +0000
+++ b/carfac/carfac.cc	Tue Jun 11 17:59:08 2013 +0000
@@ -27,18 +27,19 @@
 using std::vector;
 
 CARFAC::CARFAC(const int num_ears, const FPType sample_rate,
-                    const CARParams& car_params, const IHCParams& ihc_params,
-                    const AGCParams& agc_params) {
+               const CARParams& car_params, const IHCParams& ihc_params,
+               const AGCParams& agc_params) {
+  Reset(num_ears, sample_rate, car_params, ihc_params, agc_params);
+}
+
+void CARFAC::Reset(const int num_ears, const FPType sample_rate,
+                   const CARParams& car_params, const IHCParams& ihc_params,
+                   const AGCParams& agc_params) {
   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) {
@@ -62,8 +63,10 @@
   // This code initializes the coefficients for each of the AGC stages.
   DesignAGCCoeffs(agc_params_, sample_rate_, &agc_coeffs);
   // Once we have the coefficient structure we can design the ears.
-  for (auto& ear : ears_) {
-    ear.Init(num_channels_, car_coeffs, ihc_coeffs, agc_coeffs);
+  ears_.clear();
+  ears_.reserve(num_ears_);
+  for (int i = 0; i < num_ears_; ++i) {
+    ears_.push_back(new Ear(num_channels_, car_coeffs, ihc_coeffs, agc_coeffs));
   }
 }
 
@@ -76,15 +79,15 @@
   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_[audio_channel];
+      Ear* ear = ears_[audio_channel];
       // This stores the audio sample currently being processed.
       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());
+      ear->CARStep(input);
+      ear->IHCStep(ear->car_out());
+      updated = ear->AGCStep(ear->ihc_out());
     }
     seg_output->AppendOutput(ears_);
     if (updated) {
@@ -99,23 +102,23 @@
 }
 
 void CARFAC::CrossCouple() {
-  for (int stage = 0; stage < ears_[0].agc_num_stages(); ++stage) {
-    if (ears_[0].agc_decim_phase(stage) > 0) {
+  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);
+      FPType mix_coeff = ears_[0]->agc_mix_coeff(stage);
       if (mix_coeff > 0) {
         ArrayX stage_state;
         ArrayX this_stage_values = ArrayX::Zero(num_channels_);
-        for (auto& ear : ears_) {
-          stage_state = ear.agc_memory(stage);
+        for (const auto& ear : ears_) {
+          stage_state = ear->agc_memory(stage);
           this_stage_values += stage_state;
         }
         this_stage_values /= num_ears_;
-        for (auto& ear : ears_) {
-          stage_state = ear.agc_memory(stage);
-          ear.set_agc_memory(stage, stage_state + mix_coeff *
-                             (this_stage_values - stage_state));
+        for (const auto& ear : ears_) {
+          stage_state = ear->agc_memory(stage);
+          ear->set_agc_memory(stage, stage_state + mix_coeff *
+                              (this_stage_values - stage_state));
         }
       }
     }
@@ -123,13 +126,13 @@
 }
 
 void CARFAC::CloseAGCLoop() {
-  for (auto& ear: ears_) {
-    ArrayX undamping = 1 - ear.agc_memory(0);
+  for (auto& ear : ears_) {
+    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));
-    ear.set_dg_memory((ear.StageGValue(undamping) - ear.g_memory()) /
-                      ear.agc_decimation(0));
+    ear->set_dzb_memory((ear->zr_coeffs() * undamping - ear->zb_memory()) /
+                        ear->agc_decimation(0));
+    ear->set_dg_memory((ear->StageGValue(undamping) - ear->g_memory()) /
+                       ear->agc_decimation(0));
   }
 }
 
--- a/carfac/carfac.h	Tue Jun 11 15:04:55 2013 +0000
+++ b/carfac/carfac.h	Tue Jun 11 17:59:08 2013 +0000
@@ -48,19 +48,20 @@
   // rate. This initializes a vector of 'Ear' objects -- one for mono, two for
   // stereo, or more.
   CARFAC(const int num_ears, const FPType sample_rate,
-              const CARParams& car_params, const IHCParams& ihc_params,
-              const AGCParams& agc_params);
-  
+         const CARParams& car_params, const IHCParams& ihc_params,
+         const AGCParams& agc_params);
+
+  void Reset(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:
-  // 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,
@@ -69,7 +70,7 @@
                        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
@@ -85,10 +86,12 @@
   FPType sample_rate_;
   int num_channels_;
   FPType max_channels_per_octave_;
-  
+
   // We store a vector of Ear objects for mono/stereo/multichannel processing:
-  std::vector<Ear> ears_;
+  std::vector<Ear*> ears_;
   ArrayX pole_freqs_;
+
+  DISALLOW_COPY_AND_ASSIGN(CARFAC);
 };
 
-#endif  // CARFAC_CARFAC_H
\ No newline at end of file
+#endif  // CARFAC_CARFAC_H
--- a/carfac/carfac_output.cc	Tue Jun 11 15:04:55 2013 +0000
+++ b/carfac/carfac_output.cc	Tue Jun 11 17:59:08 2013 +0000
@@ -25,8 +25,8 @@
 using std::vector;
 
 CARFACOutput::CARFACOutput(const bool store_nap, const bool store_nap_decim,
-                        const bool store_bm, const bool store_ohc,
-                        const bool store_agc) {
+                           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;
@@ -35,29 +35,29 @@
 
 }
 
-void CARFACOutput::AppendOutput(const vector<Ear>& ears) {
+void CARFACOutput::AppendOutput(const vector<Ear*>& ears) {
   if (store_nap_) {
     nap_.push_back(vector<ArrayX>());
-    for (auto ear : ears) {
-      nap_.back().push_back(ear.ihc_out());
+    for (const auto& ear : ears) {
+      nap_.back().push_back(ear->ihc_out());
     }
   }
   if (store_ohc_) {
     ohc_.push_back(vector<ArrayX>());
-    for (auto ear : ears) {
-      ohc_.back().push_back(ear.za_memory());
+    for (const auto& ear : ears) {
+      ohc_.back().push_back(ear->za_memory());
     }
   }
   if (store_agc_) {
     agc_.push_back(vector<ArrayX>());
-    for (auto ear : ears) {
-      agc_.back().push_back(ear.zb_memory());
+    for (const auto& ear : ears) {
+      agc_.back().push_back(ear->zb_memory());
     }
   }
   if (store_bm_) {
     bm_.push_back(vector<ArrayX>());
-    for (auto ear : ears) {
-      bm_.back().push_back(ear.zy_memory());
+    for (const auto& ear : ears) {
+      bm_.back().push_back(ear->zy_memory());
     }
   }
-}
\ No newline at end of file
+}
--- a/carfac/carfac_output.h	Tue Jun 11 15:04:55 2013 +0000
+++ b/carfac/carfac_output.h	Tue Jun 11 17:59:08 2013 +0000
@@ -37,28 +37,28 @@
   // 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);
-  
+               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);
+  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_; }
+    return nap_decim_;
+  }
   const std::deque<std::vector<ArrayX>>& ohc() const { return ohc_; }
   const std::deque<std::vector<ArrayX>>& agc() const { return agc_; }
 
  private:
-  // 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_;
-  
+
   // CARFAC outputs are stored in nested containers with dimensions:
   // n_frames x n_ears x n_channels.
   std::deque<std::vector<ArrayX>> nap_;
@@ -66,6 +66,8 @@
   std::deque<std::vector<ArrayX>> bm_;
   std::deque<std::vector<ArrayX>> ohc_;
   std::deque<std::vector<ArrayX>> agc_;
+
+  DISALLOW_COPY_AND_ASSIGN(CARFACOutput);
 };
 
-#endif  // CARFAC_CARFAC_OUTPUT_H
\ No newline at end of file
+#endif  // CARFAC_CARFAC_OUTPUT_H
--- a/carfac/common.h	Tue Jun 11 15:04:55 2013 +0000
+++ b/carfac/common.h	Tue Jun 11 17:59:08 2013 +0000
@@ -45,4 +45,4 @@
 // 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
+#endif  // CARFAC_COMMON_H
--- a/carfac/ear.cc	Tue Jun 11 15:04:55 2013 +0000
+++ b/carfac/ear.cc	Tue Jun 11 17:59:08 2013 +0000
@@ -23,19 +23,25 @@
 #include <assert.h>
 #include "ear.h"
 
-void Ear::Init(const int num_channels, const CARCoeffs& car_coeffs,
-               const IHCCoeffs& ihc_coeffs,
-               const std::vector<AGCCoeffs>& agc_coeffs) {
+Ear::Ear(const int num_channels, const CARCoeffs& car_coeffs,
+         const IHCCoeffs& ihc_coeffs,
+         const std::vector<AGCCoeffs>& agc_coeffs) {
+  Reset(num_channels, car_coeffs, ihc_coeffs, agc_coeffs);
+}
+
+void Ear::Reset(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;
-  InitCARState();
-  InitIHCState();
-  InitAGCState();
+  ResetCARState();
+  ResetIHCState();
+  ResetAGCState();
 }
 
-void Ear::InitCARState() {
+void Ear::ResetCARState() {
   car_state_.z1_memory.setZero(num_channels_);
   car_state_.z2_memory.setZero(num_channels_);
   car_state_.za_memory.setZero(num_channels_);
@@ -46,7 +52,7 @@
   car_state_.dg_memory.setZero(num_channels_);
 }
 
-void Ear::InitIHCState() {
+void Ear::ResetIHCState() {
   ihc_state_.ihc_accum = ArrayX::Zero(num_channels_);
   if (! ihc_coeffs_.just_half_wave_rectify) {
     ihc_state_.ac_coupler.setZero(num_channels_);
@@ -61,7 +67,7 @@
   }
 }
 
-void Ear::InitAGCState() {
+void Ear::ResetAGCState() {
   int n_agc_stages = agc_coeffs_.size();
   agc_state_.resize(n_agc_stages);
   for (auto& stage_state : agc_state_) {
@@ -283,4 +289,4 @@
   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));
-}
\ No newline at end of file
+}
--- a/carfac/ear.h	Tue Jun 11 15:04:55 2013 +0000
+++ b/carfac/ear.h	Tue Jun 11 17:59:08 2013 +0000
@@ -33,27 +33,33 @@
 
 // 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. 
+// coefficients and states.
 class Ear {
  public:
-  
-  // This is the primary initialization function that is called for each
-  // 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);
-  
+  Ear(const int num_channels, const CARCoeffs& car_coeffs,
+      const IHCCoeffs& ihc_coeffs,
+      const std::vector<AGCCoeffs>& agc_coeffs);
+
+  void Reset(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);
+  // TODO(ronw): Consider changing the interface for the following two
+  // methods to access the internal state members directly instead of
+  // requiring callers to confusingly have to call an accessor method
+  // just to pass internal data back into the same object as in:
+  //   ear.IHCStep(ear.car_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 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 ArrayX& zy_memory() const { return car_state_.zy_memory; }
@@ -62,7 +68,7 @@
   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_num_stages() const { return agc_coeffs_.size(); }
@@ -74,14 +80,14 @@
     return agc_state_[stage].agc_memory; }
   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.
   ArrayX StageGValue(const ArrayX& undamping);
-  
+
   // This function sets the AGC memory during the cross coupling stage.
   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 ArrayX& new_values) {
     car_state_.dzb_memory = new_values; }
@@ -89,14 +95,11 @@
     car_state_.dg_memory = new_values; }
 
  private:
-  // 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();
-  
+  void ResetIHCState();
+  void ResetAGCState();
+  void ResetCARState();
+
   // These are the helper sub-functions called during the model runtime.
   void OHCNonlinearFunction(const ArrayX& velocities,
                             ArrayX* nonlinear_fun);
@@ -109,12 +112,14 @@
   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). 
+  // containing one element for each stage (default = 4).
   std::vector<AGCCoeffs> agc_coeffs_;
   std::vector<AGCState> agc_state_;
   int num_channels_;
+
+  DISALLOW_COPY_AND_ASSIGN(Ear);
 };
 
-#endif  // CARFAC_EAR_H
\ No newline at end of file
+#endif  // CARFAC_EAR_H