Mercurial > hg > aimc
changeset 646:e76951e4da20
Style fixes.
- Fix most lint errors found by
http://google-styleguide.googlecode.com/svn/trunk/cpplint/cpplint.py
- Clean up commenting style.
- Alphabetize #includes and using statements.
author | ronw@google.com |
---|---|
date | Tue, 11 Jun 2013 20:41:15 +0000 |
parents | 3f01a136c537 |
children | 749b5aed61f6 |
files | carfac/agc.h carfac/car.h carfac/carfac.cc carfac/carfac.h carfac/carfac_output.cc carfac/carfac_output.h carfac/carfac_test.cc carfac/carfac_util.h carfac/ear.cc carfac/ear.h carfac/ihc.h carfac/sai.h |
diffstat | 12 files changed, 132 insertions(+), 110 deletions(-) [+] |
line wrap: on
line diff
--- a/carfac/agc.h Tue Jun 11 17:59:08 2013 +0000 +++ b/carfac/agc.h Tue Jun 11 20:41:15 2013 +0000 @@ -24,8 +24,11 @@ #define CARFAC_AGC_H #include <vector> + #include "common.h" +// Automatic gain control (AGC) parameters, which are used to design the AGC +// filters. struct AGCParams { AGCParams() { num_stages = 4; @@ -53,6 +56,8 @@ std::vector<FPType> agc2_scales; }; +// Automatic gain control filter coefficients, which are derived from a set of +// AGCParams. struct AGCCoeffs { int num_agc_stages; FPType agc_stage_gain; @@ -71,10 +76,11 @@ FPType decim; }; +// Automatic gain control filter state. struct AGCState { ArrayX agc_memory; ArrayX input_accum; int decim_phase; }; -#endif // CARFAC_AGC_H \ No newline at end of file +#endif // CARFAC_AGC_H
--- a/carfac/car.h Tue Jun 11 17:59:08 2013 +0000 +++ b/carfac/car.h Tue Jun 11 20:41:15 2013 +0000 @@ -26,11 +26,10 @@ #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 +// object to design the set of CARCoeffs implementing 'The Cascade of // Asymmetric Resonators' described in the chapter of the same name in Lyon's -// book "Human and Machine Hearing". +// book "Human and Machine Hearing". struct CARParams { - // The constructor initializes using default parameter values. CARParams() { velocity_scale = 0.1; v_offset = 0.04; @@ -41,14 +40,15 @@ 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. + erb_break_freq = 165.3; // The Greenwood map's break frequency in Hertz. + // Glassberg and Moore's high-cf ratio. + erb_q = 1000 / (24.7 * 4.37); + } + + FPType velocity_scale; // 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 min_zeta; // The minimum damping factor in mid-freq channels. + FPType max_zeta; // 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. @@ -58,8 +58,7 @@ 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. +// CAR filter coefficients, which are derived from a set of CARParams. struct CARCoeffs { FPType velocity_scale; FPType v_offset; @@ -72,6 +71,7 @@ }; +// CAR filter state. struct CARState { ArrayX z1_memory; ArrayX z2_memory; @@ -83,4 +83,4 @@ ArrayX dg_memory; }; -#endif // CARFAC_CAR_H \ No newline at end of file +#endif // CARFAC_CAR_H
--- a/carfac/carfac.cc Tue Jun 11 17:59:08 2013 +0000 +++ b/carfac/carfac.cc Tue Jun 11 20:41:15 2013 +0000 @@ -60,25 +60,29 @@ std::vector<AGCCoeffs> agc_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_, sample_rate_, &agc_coeffs); // Once we have the coefficient structure we can design the ears. - 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)); + if (ears_.size() > i && ears_[i] != NULL) { + // Reset any existing ears. + ears_[i]->Reset(num_channels_, car_coeffs, ihc_coeffs, agc_coeffs); + } else { + ears_.push_back( + new Ear(num_channels_, car_coeffs, ihc_coeffs, agc_coeffs)); + } } } void CARFAC::RunSegment(const vector<vector<float>>& sound_data, const int32_t start, const int32_t length, const bool open_loop, CARFACOutput* seg_output) { + assert(sound_data.size() == num_ears_); // 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 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]; // This stores the audio sample currently being processed. FPType input = sound_data[audio_channel][start + timepoint]; @@ -94,7 +98,7 @@ if (num_ears_ > 1) { CrossCouple(); } - if (! open_loop) { + if (!open_loop) { CloseAGCLoop(); } } @@ -190,7 +194,7 @@ x = CARFACDetect(x); conduct_at_0 = x(0); if (ihc_params.one_capacitor) { - FPType ro = 1 / conduct_at_10 ; + FPType ro = 1 / conduct_at_10; FPType c = ihc_params.tau1_out / ro; FPType ri = ihc_params.tau1_in / c; FPType saturation_output = 1 / ((2 * ro) + ri); @@ -198,7 +202,7 @@ 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 * sample_rate)); + 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; @@ -248,7 +252,7 @@ FPType mix_coeff = agc_params.agc_mix_coeff; agc_coeff.decimation = agc_params.decimation[stage]; FPType total_dc_gain = previous_stage_gain; - // Here we calculate the parameters for the current stage. + // Calculate the parameters for the current stage. FPType tau = time_constants[stage]; agc_coeff.decim = decim; agc_coeff.decim *= agc_coeff.decimation; @@ -266,9 +270,9 @@ int n_taps = 0; bool fir_ok = false; int n_iterations = 1; - // This section initializes the FIR coeffs settings at each stage. + // Initialize the FIR coefficient settings at each stage. FPType fir_left, fir_mid, fir_right; - while (! fir_ok) { + while (!fir_ok) { switch (n_taps) { case 0: n_taps = 3; @@ -341,6 +345,6 @@ } FPType CARFAC::ERBHz(const FPType center_frequency_hz, - const FPType erb_break_freq, const FPType erb_q) { + const FPType erb_break_freq, const FPType erb_q) const { return (erb_break_freq + center_frequency_hz) / erb_q; }
--- a/carfac/carfac.h Tue Jun 11 17:59:08 2013 +0000 +++ b/carfac/carfac.h Tue Jun 11 20:41:15 2013 +0000 @@ -25,28 +25,25 @@ #include <vector> +#include "agc.h" +#include "car.h" +#include "carfac_output.h" +#include "carfac_util.h" #include "common.h" -#include "carfac_util.h" -#include "car.h" +#include "ear.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. +// 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. +// activity patterns" (NAPs) using 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. + // Constructs a vector of Ear objects, one for each input audio channel, + // using the given CAR, IHC and AGC parameters. CARFAC(const int num_ears, const FPType sample_rate, const CARParams& car_params, const IHCParams& ihc_params, const AGCParams& agc_params); @@ -55,8 +52,11 @@ 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. + // Processes an individual sound segment and copies the model output to + // seg_output. + // + // The input sound_data should contain a vector of audio samples for each + // ear. 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); @@ -71,13 +71,13 @@ void CrossCouple(); void CloseAGCLoop(); - // Function: ERBHz - // Auditory filter nominal Equivalent Rectangular Bandwidth + // Computes the nominal Equivalent Rectangular Bandwidth (ERB) of an auditory + // filter at the given center frequency. // 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); + const FPType erb_q) const; CARParams car_params_; IHCParams ihc_params_; @@ -87,7 +87,7 @@ int num_channels_; FPType max_channels_per_octave_; - // We store a vector of Ear objects for mono/stereo/multichannel processing: + // One Ear per input audio channel. std::vector<Ear*> ears_; ArrayX pole_freqs_;
--- a/carfac/carfac_output.cc Tue Jun 11 17:59:08 2013 +0000 +++ b/carfac/carfac_output.cc Tue Jun 11 20:41:15 2013 +0000 @@ -24,15 +24,12 @@ 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) { +CARFACOutput::CARFACOutput(const bool store_nap, 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; store_ohc_ = store_ohc; store_agc_ = store_agc; - } void CARFACOutput::AppendOutput(const vector<Ear*>& ears) {
--- a/carfac/carfac_output.h Tue Jun 11 17:59:08 2013 +0000 +++ b/carfac/carfac_output.h Tue Jun 11 20:41:15 2013 +0000 @@ -29,42 +29,44 @@ #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. +// Container for the different types of output from a CARFAC model. See the +// private members below for details. class CARFACOutput { public: - // 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 boolean argument indicate which portions of the CARFAC model's output + // should be stored by subsequent calls to AppendOutput. + // + // TODO(ronw): Consider removing store_nap, unless there is a reasonable use + // case for setting it to false? + CARFACOutput(const bool store_nap, 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. + // Appends a single frame of n_ears x n_channels data to the end of the + // individual data members selected for storage. This is called on a sample + // by sample basis by CARFAC::RunSegment. 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: 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. + + // Neural activity pattern rates. std::deque<std::vector<ArrayX>> nap_; - std::deque<std::vector<ArrayX>> nap_decim_; + // Basilar membrane displacement. std::deque<std::vector<ArrayX>> bm_; + // Outer hair cell state. std::deque<std::vector<ArrayX>> ohc_; + // Automatic gain control state. std::deque<std::vector<ArrayX>> agc_; DISALLOW_COPY_AND_ASSIGN(CARFACOutput);
--- a/carfac/carfac_test.cc Tue Jun 11 17:59:08 2013 +0000 +++ b/carfac/carfac_test.cc Tue Jun 11 20:41:15 2013 +0000 @@ -20,22 +20,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include <fstream> #include <string> -#include <fstream> #include <vector> #include "gtest/gtest.h" +#include "agc.h" #include "car.h" -#include "ihc.h" -#include "agc.h" #include "carfac.h" #include "common.h" +#include "ihc.h" -using std::vector; -using std::string; using std::ifstream; using std::ofstream; +using std::string; +using std::vector; // This is the 'test_data' subdirectory of aimc/carfac that specifies where to // locate the text files produced by 'CARFAC_GenerateTestData.m' for comparing @@ -47,7 +47,8 @@ // Three helper functions are defined here for loading the test data generated // by the Matlab version of CARFAC. // This loads one-dimensional ArrayXs from single-column text files. -void WriteNAPOutput(CARFACOutput& output, const string filename, int ear) { +void WriteNAPOutput(const CARFACOutput& output, const string filename, + int ear) { string fullfile = kTestSourceDir + filename; ofstream ofile(fullfile.c_str()); int32_t num_timepoints = output.nap().size(); @@ -56,7 +57,7 @@ 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) { + if (j < channels - 1) { ofile << " "; } } @@ -145,7 +146,7 @@ IHCParams ihc_params; AGCParams agc_params; CARFAC mycf(num_ears, 22050, car_params, ihc_params, agc_params); - CARFACOutput my_output(true, false, true, false, false); + CARFACOutput my_output(true, true, false, false); const bool kOpenLoop = false; const int length = sound_data[0].size(); mycf.RunSegment(sound_data, 0, length, kOpenLoop, &my_output); @@ -197,7 +198,7 @@ IHCParams ihc_params; AGCParams agc_params; CARFAC mycf(num_ears, 44100, car_params, ihc_params, agc_params); - CARFACOutput my_output(true, false, true, false, false); + CARFACOutput my_output(true, true, false, false); const bool kOpenLoop = false; const int length = sound_data[0].size(); mycf.RunSegment(sound_data, 0, length, kOpenLoop, &my_output); @@ -227,4 +228,4 @@ ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel); } } -} \ No newline at end of file +}
--- a/carfac/carfac_util.h Tue Jun 11 17:59:08 2013 +0000 +++ b/carfac/carfac_util.h Tue Jun 11 20:41:15 2013 +0000 @@ -25,9 +25,8 @@ #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. +// 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 +#endif // CARFAC_CARFAC_UTIL_H
--- a/carfac/ear.cc Tue Jun 11 17:59:08 2013 +0000 +++ b/carfac/ear.cc Tue Jun 11 20:41:15 2013 +0000 @@ -21,6 +21,7 @@ // limitations under the License. #include <assert.h> + #include "ear.h" Ear::Ear(const int num_channels, const CARCoeffs& car_coeffs, @@ -54,7 +55,7 @@ void Ear::ResetIHCState() { ihc_state_.ihc_accum = ArrayX::Zero(num_channels_); - if (! ihc_coeffs_.just_half_wave_rectify) { + if (!ihc_coeffs_.just_half_wave_rectify) { 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); @@ -78,9 +79,9 @@ } void Ear::CARStep(const FPType input) { - // This interpolates g. + // Interpolates g. car_state_.g_memory = car_state_.g_memory + car_state_.dg_memory; - // This calculates the AGC interpolation state. + // Calculates the AGC interpolation state. 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. @@ -114,7 +115,7 @@ // rational function. This makes the result go to zero at high // absolute velocities, so it will do nothing there. void Ear::OHCNonlinearFunction(const ArrayX& velocities, - ArrayX* nonlinear_fun) { + ArrayX* nonlinear_fun) const { *nonlinear_fun = (1 + ((velocities * car_coeffs_.velocity_scale) + car_coeffs_.v_offset).square()).inverse(); } @@ -210,7 +211,7 @@ } void Ear::AGCSpatialSmooth(const AGCCoeffs& agc_coeffs, - ArrayX* stage_state) { + ArrayX* stage_state) const { int num_iterations = agc_coeffs.agc_spatial_iterations; bool use_fir; use_fir = (num_iterations < 4) ? true : false; @@ -263,11 +264,11 @@ void Ear::AGCSmoothDoubleExponential(const FPType pole_z1, const FPType pole_z2, - ArrayX* stage_state) { + ArrayX* stage_state) const { 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 + // TODO(alexbrandmeyer): I'm assuming one dimensional input for now, but this // should be verified with Dick for the final version for (int i = num_points - 11; i < num_points; ++i) { input = (*stage_state)(i); @@ -284,7 +285,7 @@ } } -ArrayX Ear::StageGValue(const ArrayX& undamping) { +ArrayX Ear::StageGValue(const ArrayX& undamping) const { 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 *
--- a/carfac/ear.h Tue Jun 11 17:59:08 2013 +0000 +++ b/carfac/ear.h Tue Jun 11 20:41:15 2013 +0000 @@ -25,15 +25,15 @@ #include <vector> +#include "agc.h" +#include "car.h" +#include "carfac_util.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. +// filter coefficients and states. class Ear { public: Ear(const int num_channels, const CARCoeffs& car_coeffs, @@ -73,40 +73,47 @@ // coupling of the ears. 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; } + return agc_state_[stage].decim_phase; + } const FPType agc_mix_coeff(const int stage) const { - return agc_coeffs_[stage].agc_mix_coeffs; } + return agc_coeffs_[stage].agc_mix_coeffs; + } const ArrayX& agc_memory(const int stage) const { - return agc_state_[stage].agc_memory; } + return agc_state_[stage].agc_memory; + } const int agc_decimation(const int stage) const { - return agc_coeffs_[stage].decimation; } + return agc_coeffs_[stage].decimation; + } - // This returns the stage G value during the closing of the AGC loop. - ArrayX StageGValue(const ArrayX& undamping); + // Returns the stage G value during the closing of the AGC loop. + ArrayX StageGValue(const ArrayX& undamping) const; - // This function sets the AGC memory during the cross coupling stage. + // 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; } + agc_state_[stage].agc_memory = new_values; + } - // These are the setter functions for the CAR memory states. + // Setter functions for the CAR memory states. void set_dzb_memory(const ArrayX& new_values) { - car_state_.dzb_memory = new_values; } + car_state_.dzb_memory = new_values; + } void set_dg_memory(const ArrayX& new_values) { - car_state_.dg_memory = new_values; } + car_state_.dg_memory = new_values; + } private: - // These methodsinitialize the model state variables prior to runtime. + // Initializes the model state variables prior to runtime. void ResetIHCState(); void ResetAGCState(); void ResetCARState(); - // These are the helper sub-functions called during the model runtime. + // Helper sub-functions called during the model runtime. void OHCNonlinearFunction(const ArrayX& velocities, - ArrayX* nonlinear_fun); + ArrayX* nonlinear_fun) const; bool AGCRecurse(const int stage, ArrayX agc_in); - void AGCSpatialSmooth(const AGCCoeffs& agc_coeffs , ArrayX* stage_state); + void AGCSpatialSmooth(const AGCCoeffs& agc_coeffs, ArrayX* stage_state) const; void AGCSmoothDoubleExponential(const FPType pole_z1, const FPType pole_z2, - ArrayX* stage_state); + ArrayX* stage_state) const; CARCoeffs car_coeffs_; CARState car_state_;
--- a/carfac/ihc.h Tue Jun 11 17:59:08 2013 +0000 +++ b/carfac/ihc.h Tue Jun 11 20:41:15 2013 +0000 @@ -25,6 +25,7 @@ #include "common.h" +// Inner hair cell (IHC) parameters, which are used to design the IHC filters. struct IHCParams { IHCParams() { just_half_wave_rectify = false; @@ -35,7 +36,8 @@ tau2_out = 0.0025; tau2_in = 0.005; ac_corner_hz = 20.0; - }; + } + bool just_half_wave_rectify; bool one_capacitor; FPType tau_lpf; @@ -46,6 +48,8 @@ FPType ac_corner_hz; }; +// Inner hair cell filter coefficients, which are derived from a set of +// IHCParams. struct IHCCoeffs { bool just_half_wave_rectify; bool one_capacitor; @@ -63,6 +67,7 @@ FPType cap2_voltage; }; +// Inner hair cell filter state. struct IHCState { ArrayX ihc_out; ArrayX ihc_accum; @@ -73,4 +78,4 @@ ArrayX ac_coupler; }; -#endif // CARFAC_IHC_H \ No newline at end of file +#endif // CARFAC_IHC_H