Mercurial > hg > aimc
changeset 609:aefe2ca0674f
First version of a C++ implementation by Alex Brandmeyer
author | alexbrandmeyer |
---|---|
date | Mon, 13 May 2013 22:51:15 +0000 |
parents | fc353426eaad |
children | 01986636257a |
files | carfac/agc_coeffs.cc carfac/agc_coeffs.h carfac/agc_params.cc carfac/agc_params.h carfac/agc_state.cc carfac/agc_state.h carfac/car_coeffs.cc carfac/car_coeffs.h carfac/car_params.cc carfac/car_params.h carfac/car_state.cc carfac/car_state.h carfac/carfac.cc carfac/carfac.h carfac/carfac_common.cc carfac/carfac_common.h carfac/carfac_output.cc carfac/carfac_output.h carfac/ear.cc carfac/ear.h carfac/ear_output.cc carfac/ear_output.h carfac/ihc_coeffs.cc carfac/ihc_coeffs.h carfac/ihc_params.cc carfac/ihc_params.h carfac/ihc_state.cc carfac/ihc_state.h carfac/main.cc carfac/test_signal.wav |
diffstat | 30 files changed, 1980 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/agc_coeffs.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,167 @@ +// +// agc_coeffs.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 "agc_coeffs.h" + +//This method has been created for debugging purposes and depends on <iostream>. +//Could possibly be removed in the final version to reduce dependencies. +void AGCCoeffs::OutputCoeffs(){ + std::cout << "AGCCoeffs Values" << std::endl; + std::cout << "****************" << std::endl; + std::cout << "n_ch_ = " << n_ch_ << std::endl; + std::cout << "n_agc_stages_ = " << n_agc_stages_ << std::endl; + std::cout << "agc_stage_gain_ = " << agc_stage_gain_ << std::endl; + std::cout << "agc_epsilon_ = " << agc_epsilon_ << std::endl; + std::cout << "decimation_ = " << decimation_ << std::endl; + std::cout << "agc_pole_z1_ = " << agc_pole_z1_ << std::endl; + std::cout << "agc_pole_z2_ = " << agc_pole_z2_ << std::endl; + std::cout << "agc_spatial_iterations_ = " << agc_spatial_iterations_ + << std::endl; + std::cout << "agc_spatial_fir_ = " << agc_spatial_fir_ << std::endl; + std::cout << "agc_spatial_n_taps_ = " << agc_spatial_n_taps_ << std::endl; + std::cout << "agc_mix_coeffs_ = " << agc_mix_coeffs_ << std::endl; + std::cout << "agc1_scales_ = " << agc1_scales_ << std::endl; + std::cout << "agc2_scales_ = " << agc2_scales_ << std::endl; + std::cout << "time_constants_ = " << time_constants_ + << std::endl << std::endl; +} + +void AGCCoeffs::DesignAGC(AGCParams agc_params, long fs, int n_ch){ + n_ch_ = n_ch; + n_agc_stages_ = agc_params.n_stages_; + agc_stage_gain_ = agc_params.agc_stage_gain_; + agc1_scales_ = agc_params.agc1_scales_; + agc2_scales_ = agc_params.agc2_scales_; + time_constants_ = agc_params.time_constants_; + agc_epsilon_.resize(n_agc_stages_); + agc_pole_z1_.resize(n_agc_stages_); + agc_pole_z2_.resize(n_agc_stages_); + agc_spatial_iterations_.resize(n_agc_stages_); + agc_spatial_n_taps_.resize(n_agc_stages_); + agc_spatial_fir_.resize(3,n_agc_stages_); + agc_mix_coeffs_.resize(n_agc_stages_); + mix_coeff_ = agc_params.agc_mix_coeff_; + fir_.resize(3); + decim_ = 1; + decimation_ = agc_params.decimation_; + total_dc_gain_ = 0; + + for (int stage=0; stage < n_agc_stages_; stage++){ + tau_ = time_constants_(stage); + decim_ = decim_ * decimation_(stage); + agc_epsilon_(stage) = 1 - exp((-1 * decim_) / (tau_ * fs)); + n_times_ = tau_ * (fs / decim_); + delay_ = (agc2_scales_(stage) - agc1_scales_(stage)) / n_times_; + spread_sq_ = (pow(agc1_scales_(stage),2) + pow(agc2_scales_(stage),2)) / + n_times_; + u_ = 1 + (1 / spread_sq_); + p_ = u_ - sqrt(pow(u_,2) - 1); + dp_ = delay_ * (1 - (2 * p_) + pow(p_,2)) / 2; + pole_z1_ = p_ - dp_; + pole_z2_ = p_ + dp_; + agc_pole_z1_(stage) = pole_z1_; + agc_pole_z2_(stage) = pole_z2_; + n_taps_ = 0; + fir_ok_ = 0; + n_iterations_ = 1; + //initialize FIR coeffs settings + try { + 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){ + throw 10; //too many iterations + } + break; + default: + throw 20; //bad n_taps + } + //Design FIR Coeffs + FPType var = spread_sq_ / n_iterations_; + FPType mn = delay_ / n_iterations_; + switch (n_taps_){ + case 3: + a = (var + pow(mn,2) - mn) / 2; + b = (var + pow(mn,2) + mn) / 2; + fir_ << a, 1 - a - b, b; + if (fir_(2) >= 0.2) { + fir_ok_ = true; + } else { + fir_ok_ = false; + } + break; + case 5: + a = (((var + pow(mn,2)) * 2/5) - (mn * 2/3)) / 2; + b = (((var + pow(mn,2)) * 2/5) + (mn * 2/3)) / 2; + fir_ << a/2, 1 - a - b, b/2; + if (fir_(2) >= 0.1) { + fir_ok_ = true; + } else { + fir_ok_ = false; + } + break; + default: + throw 30; //bad n_taps in FIR design + } + } + } + catch (int e) { + switch (e) { + case 10: + std::cout << "ERROR: Too many n_iterations in agc_coeffs.DesignAGC" + << std::endl; + break; + case 20: + std::cout << "ERROR: Bad n_taps in agc_coeffs.DesignAGC" << std::endl; + break; + case 30: + std::cout << "ERROR: Bad n_taps in agc_coeffs.DesignAGC/FIR" + << std::endl; + break; + default: + std::cout << "ERROR: unknown error in agc_coeffs.DesignAGC" + << std::endl; + } + } + //assign output of filter design + agc_spatial_iterations_(stage) = n_iterations_; + agc_spatial_n_taps_(stage) = n_taps_; + agc_spatial_fir_(0,stage) = fir_(0); + agc_spatial_fir_(1,stage) = fir_(1); + agc_spatial_fir_(2,stage) = fir_(2); + total_dc_gain_ = total_dc_gain_ + pow(agc_stage_gain_,(stage)); + if (stage == 0) { + agc_mix_coeffs_(stage) = 0; + } else { + agc_mix_coeffs_(stage) = mix_coeff_ / (tau_ * (fs /decim_)); + } + } + agc_gain_ = total_dc_gain_; + detect_scale_ = 1 / total_dc_gain_; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/agc_coeffs.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,71 @@ +// +// 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_Open_Source_C__Library_AGCCoeffs_h +#define CARFAC_Open_Source_C__Library_AGCCoeffs_h + +#include "agc_params.h" + +class AGCCoeffs { +public: + int n_ch_; + int n_agc_stages_; + int agc_stage_gain_; + FloatArray agc_epsilon_; //FloatArray + FloatArray decimation_; //FloatArray + FloatArray agc_pole_z1_; //FloatArray + FloatArray agc_pole_z2_; //FloatArray + FloatArray agc_spatial_iterations_; //FloatArray + FloatArray2d agc_spatial_fir_; //2-d FloatArray + FloatArray agc_spatial_n_taps_; //FloatArray + FloatArray agc_mix_coeffs_; //FloatArray + FPType agc_gain_; + FPType detect_scale_; + + FloatArray agc1_scales_; + FloatArray agc2_scales_; + FloatArray time_constants_; + FPType tau_; + FPType decim_; + FPType n_times_; + FPType delay_; + FPType spread_sq_; + FPType u_; + FPType p_; + FPType dp_; + FPType pole_z1_; + FPType pole_z2_; + int n_taps_; + bool fir_ok_; + int n_iterations_; + FPType total_dc_gain_; + FPType a, b; + FPType mix_coeff_; + FloatArray fir_; + + + void OutputCoeffs(); //Method to view coeffs, could go in final version + void DesignAGC(AGCParams agc_params, long fs, int n_ch); +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/agc_params.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,62 @@ +// +// agc_params.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 "agc_params.h" + +AGCParams::AGCParams(){ + n_stages_ = 4; + agc_stage_gain_ = 2; + FPType agc1f = 1.0; + FPType agc2f = 1.65; + time_constants_.resize(n_stages_); + time_constants_ << 1*0.002, 4*0.002, 16*0.002, 64*0.002; + decimation_.resize(n_stages_); + decimation_ << 8, 2, 2, 2; + agc1_scales_.resize(n_stages_); + agc1_scales_ << 1.0 * agc1f, 1.4 * agc1f, 2.0 * agc1f, 2.8 * agc1f; + agc2_scales_.resize(n_stages_); + agc2_scales_ << 1.0 * agc2f, 1.4 * agc2f, 2.0 * agc2f, 2.8 * agc2f; + agc_mix_coeff_ = 0.5; +} + +void AGCParams::SetParams(int ns, FPType agcsg, FPType agcmc, FloatArray tc, + FloatArray dec, FloatArray agc1sc, FloatArray agc2sc){ + n_stages_ = ns; + agc_stage_gain_ = agcsg; + agc_mix_coeff_ = agcmc; + time_constants_ = tc; + decimation_ = dec; + agc1_scales_ = agc1sc; + agc2_scales_ = agc2sc; +} + +void AGCParams::OutputParams(){ + std::cout << "AGCParams Values" << std::endl; + std::cout << "****************" << std::endl; + std::cout << "n_stages_ = " << n_stages_ << std::endl; + std::cout << "agc_stage_gain_ = " << agc_stage_gain_ << std::endl; + std::cout << "agc_mix_coeff_ = " << agc_mix_coeff_ << std::endl; + std::cout << "time_constants_ = " << time_constants_ << std::endl; + std::cout << "decimation_ = " << decimation_ << std::endl; + std::cout << "agc1_scales_ = " << agc1_scales_ << std::endl; + std::cout << "agc2_scales_ = " << agc2_scales_ << std::endl << std::endl; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/agc_params.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,45 @@ +// +// 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_Open_Source_C__Library_AGCParams_h +#define CARFAC_Open_Source_C__Library_AGCParams_h + +#include "carfac_common.h" + +class AGCParams { +public: + int n_stages_; + FPType agc_stage_gain_; + FPType agc_mix_coeff_; + FloatArray time_constants_; + FloatArray decimation_; + FloatArray agc1_scales_; + FloatArray agc2_scales_; + + + void OutputParams(); + void SetParams(int ns, FPType agcsg,FPType agcmc, FloatArray tc, + FloatArray dec, FloatArray agc1sc, FloatArray agc2sc); + AGCParams(); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/agc_state.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,31 @@ +// +// agc_state.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 "agc_state.h" + +void AGCState::InitAGCState(AGCCoeffs agc_coeffs){ + n_ch_ = agc_coeffs.n_ch_; + n_agc_stages_ = agc_coeffs.n_agc_stages_; + agc_memory_ = FloatArray2d::Zero(n_ch_, n_agc_stages_); + input_accum_ = FloatArray2d::Zero(n_ch_, n_agc_stages_); + decim_phase_ = FloatArray::Zero(n_agc_stages_); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/agc_state.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,38 @@ +// +// 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_Open_Source_C__Library_AGCState_h +#define CARFAC_Open_Source_C__Library_AGCState_h + +#include "agc_coeffs.h" + +class AGCState { +public: + int n_ch_; + int n_agc_stages_; + FloatArray2d agc_memory_; + FloatArray2d input_accum_; + FloatArray decim_phase_; + void InitAGCState(AGCCoeffs agc_coeffs); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/car_coeffs.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,77 @@ +// +// car_coeffs.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 "car_coeffs.h" + +//This method has been created for debugging purposes and depends on <iostream>. +//Could possibly be removed in the final version to reduce dependencies. +void CARCoeffs::OutputCoeffs(){ + std::cout << "CARCoeffs Values" << std::endl; + std::cout << "****************" << std::endl; + std::cout << "n_ch_ = " << n_ch_ << std::endl; + std::cout << "velocity_scale_ = " << velocity_scale_ << std::endl; + std::cout << "v_offset_ = " << v_offset_ << std::endl; + std::cout << "r1_coeffs_ = " << r1_coeffs_ << std::endl; + std::cout << "a0_coeffs_ = " << a0_coeffs_ << std::endl; + std::cout << "c0_coeffs_ = " << c0_coeffs_ << std::endl; + std::cout << "h_coeffs_ = " << h_coeffs_ << std::endl; + std::cout << "g0_coeffs_ = " << g0_coeffs_ << std::endl; + std::cout << "zr_coeffs_ = " << zr_coeffs_ << std::endl << std::endl; +} + +void CARCoeffs::DesignFilters(CARParams car_params, long fs, + FloatArray pole_freqs[]){ + + n_ch_ = int(pole_freqs->size()); + velocity_scale_ = car_params.velocity_scale_; + v_offset_ = car_params.v_offset_; + FloatArray p_freqs = *pole_freqs; + r1_coeffs_.resize(n_ch_); + a0_coeffs_.resize(n_ch_); + c0_coeffs_.resize(n_ch_); + h_coeffs_.resize(n_ch_); + g0_coeffs_.resize(n_ch_); + FPType f = car_params.zero_ratio_ * car_params.zero_ratio_ - 1; + FloatArray theta = p_freqs * ((2 * PI) / fs); + c0_coeffs_ = sin(theta); + a0_coeffs_ = cos(theta); + FPType ff = car_params.high_f_damping_compression_; + FloatArray x = theta / PI; + zr_coeffs_ = PI * (x - (ff * (x * x * x)));//change to exponet + FPType max_zeta = car_params.max_zeta_; + FPType min_zeta = car_params.min_zeta_; + r1_coeffs_ = (1 - (zr_coeffs_ * max_zeta)); + FPType curfreq; + FloatArray erb_freqs(n_ch_); + for (int ch=0; ch < n_ch_; ch++){ + curfreq = p_freqs(ch); + erb_freqs(ch) = ERBHz(curfreq, car_params.erb_break_freq_, + car_params.erb_q_); + } + FloatArray min_zetas = min_zeta + (0.25 * ((erb_freqs / p_freqs) - min_zeta)); + zr_coeffs_ = zr_coeffs_ * (max_zeta - min_zetas); + h_coeffs_ = c0_coeffs_ * f; + FloatArray relative_undamping = FloatArray::Ones(n_ch_); + FloatArray r = r1_coeffs_ + (zr_coeffs_ * relative_undamping); + g0_coeffs_ = (1 - (2 * r * a0_coeffs_) + (r * r)) / + (1 - (2 * r * a0_coeffs_) + (h_coeffs_ * r * c0_coeffs_) + (r * r)); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/car_coeffs.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,46 @@ +// +// 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_Open_Source_C__Library_CARCoeffs_h +#define CARFAC_Open_Source_C__Library_CARCoeffs_h + +#include "car_params.h" + +class CARCoeffs { +public: + 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_; + + void OutputCoeffs(); //Method to view coeffs, could go in final version + void DesignFilters(CARParams car_params, long fs, + FloatArray pole_freqs[]); +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/car_params.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,72 @@ +// +// car_params.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 "car_params.h" + +CARParams::CARParams(){ + velocity_scale_ = 0.1; //for the velocity nonlinearity + v_offset_ = 0.04; //offset gives quadratic part + min_zeta_ = 0.1; //minimum damping factor in mid-freq channels + max_zeta_ = 0.35; //maximum damping factor in mid-freq channels + first_pole_theta_ = 0.85 * PI; + zero_ratio_ = 1.4142; //how far zero is above pole + high_f_damping_compression_ = 0.5; //0 to 1 to compress theta + erb_per_step_ = 0.5; //assume G&M's ERB formula + min_pole_hz_ = 30; + erb_break_freq_ = 165.3; //Greenwood map's break frequency + erb_q_ = 1000/(24.7*4.37); +}; + +//This method has been created for debugging purposes and depends on <iostream>. +//Could possibly be removed in the final version to reduce dependencies. +void CARParams::OutputParams(){ + std::cout << "CARParams Values" << std::endl; + std::cout << "****************" << std::endl; + std::cout << "velocity_scale_ = " << velocity_scale_ << std::endl; + std::cout << "v_offset_ = " << v_offset_ << std::endl; + std::cout << "min_zeta_ = " << min_zeta_ << std::endl; + std::cout << "max_zeta_ = " << max_zeta_ << std::endl; + std::cout << "first_pole_theta_ = " << first_pole_theta_ << std::endl; + std::cout << "zero_ratio_ = " << zero_ratio_ << std::endl; + std::cout << "high_f_damping_compression_ = " << high_f_damping_compression_ + << std::endl; + std::cout << "erb_per_step_ = " << erb_per_step_ << std::endl; + std::cout << "min_pole_hz_ = " << min_pole_hz_ << std::endl; + std::cout << "erb_break_freq_ = " << erb_break_freq_ << std::endl; + std::cout << "erb_q_ = " << erb_q_ << std::endl << std::endl; +} + +void CARParams::SetParams(FPType vs, FPType voff, FPType min_z, FPType max_z, + FPType fpt, FPType zr, FPType hfdc, FPType erbps, + FPType mph, FPType erbbf, FPType erbq) { + velocity_scale_ = vs; + v_offset_ = voff; + min_zeta_ = min_z; + max_zeta_ = max_z; + first_pole_theta_ = fpt; + zero_ratio_ = zr; + high_f_damping_compression_ = hfdc; + erb_per_step_ = erbps; + min_pole_hz_ = mph; + erb_break_freq_ = erbbf; + erb_q_ = erbq; +}; \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/car_params.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,50 @@ +// +// 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_Open_Source_C__Library_CARParams_h +#define CARFAC_Open_Source_C__Library_CARParams_h + +#include "carfac_common.h" + +class CARParams { +public: + FPType velocity_scale_; //for the velocity nonlinearity + FPType v_offset_; //offset gives quadratic part + FPType min_zeta_; //minimum damping factor in mid-freq channels + FPType max_zeta_; //maximum damping factor in mid-freq channels + FPType first_pole_theta_; + FPType zero_ratio_; //how far zero is above pole + FPType high_f_damping_compression_; //0 to 1 to compress theta + FPType erb_per_step_; //assume G&M's ERB formula + FPType min_pole_hz_; + FPType erb_break_freq_; //Greenwood map's break frequency + FPType erb_q_; //G&M's high-cf ratio + + CARParams(); //Constructor initializes default parameter values + void OutputParams(); //Output current parameter values using std::cout + void SetParams(FPType vs, FPType voff, FPType min_z, FPType max_z, FPType fpt, + FPType zr, FPType hfdc, FPType erbps, FPType mph, FPType erbbf, + FPType erbq); //Method to set non-default params +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/car_state.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,37 @@ +// +// car_state.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 "car_state.h" + +void CARState::InitCARState(CARCoeffs car_coeffs){ + n_ch_ = car_coeffs.n_ch_; + z1_memory_ = FloatArray::Zero(n_ch_); + z2_memory_ = FloatArray::Zero(n_ch_); + za_memory_ = FloatArray::Zero(n_ch_); + zb_memory_ = car_coeffs.zr_coeffs_; + dzb_memory_ = FloatArray::Zero(n_ch_); + zy_memory_ = FloatArray::Zero(n_ch_); + g_memory_ = car_coeffs.g0_coeffs_; + dg_memory_ = FloatArray::Zero(n_ch_); + + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/car_state.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,45 @@ +// +// 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_Open_Source_C__Library_CARState_h +#define CARFAC_Open_Source_C__Library_CARState_h + +#include "car_coeffs.h" + +class CARState { +public: + int n_ch_; + FloatArray z1_memory_; + FloatArray z2_memory_; + FloatArray za_memory_; + FloatArray zb_memory_; + FloatArray dzb_memory_; + FloatArray zy_memory_; + FloatArray g_memory_; + FloatArray dg_memory_; + + void InitCARState(CARCoeffs car_coeffs); + +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/carfac.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,82 @@ +// +// carfac.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.h" +void CARFAC::Design(int n_ears, long fs, CARParams car_params, + IHCParams ihc_params, AGCParams agc_params){ + n_ears_ = n_ears; + fs_ = fs; + ears_ = new Ear[n_ears_]; + for (int i = 0; i < n_ears_; i++){ + ears_[i].InitEar(fs_, car_params,ihc_params,agc_params); + } + n_ch_ = ears_[0].car_coeffs_.n_ch_; +} + +CARFACOutput CARFAC::Run(FloatArray2d sound_data){ + //to store the final output + CARFACOutput *output = new CARFACOutput(); + //to store the output of the individual segments + CARFACOutput *seg_output = new CARFACOutput(); + + int n_audio_channels = int(sound_data.cols()); + long seg_len = 441; //Fixed segment length for now + long n_timepoints = sound_data.rows(); + double n_segs = ceil(double(n_timepoints)/double(seg_len)); + output->InitOutput(n_audio_channels, n_ch_, n_timepoints); + seg_output->InitOutput(n_audio_channels, n_ch_, seg_len); + //loop over individual audio segments + long start, length; //to store the start and endpoints for each segment + for (long i = 0; i < long(n_segs); i++){ + //determine start and end points + start = (i * seg_len); + if (i < n_segs - 1){ + length = seg_len; + } else { + length = n_timepoints - start; //the last segment can be shorter than the rest + } + RunSegment(sound_data.block(start,0,length,n_audio_channels),seg_output); + output->MergeOutput(*seg_output, start, length); + } + + return *output; +} + +void CARFAC::RunSegment(FloatArray2d sound_data, CARFACOutput *seg_output){ + long n_timepoints = sound_data.rows(); + int n_ears = int(sound_data.cols()); + for (long i = 0; i < n_timepoints; i++){ + for (int j = 0; j < n_ears; j++){ + FPType input = sound_data(i,j); + FloatArray car_out = ears_[j].CARStep(input); + FloatArray ihc_out = ears_[j].IHCStep(car_out); + bool updated = ears_[j].AGCStep(ihc_out); + seg_output->ears_[j].nap_.block(0,i,n_ch_,1) = ihc_out; + seg_output->ears_[j].bm_.block(0,i,n_ch_,1) = car_out; + seg_output->ears_[j].ohc_.block(0,1,n_ch_,1) = + ears_[j].car_state_.za_memory_; + seg_output->ears_[j].agc_.block(0,i,n_ch_,1) = + ears_[j].car_state_.zb_memory_; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/carfac.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,71 @@ +// +// carfac.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. +// +// ***************************************************************************** +// 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_Open_Source_C__Library_CARFAC_h +#define CARFAC_Open_Source_C__Library_CARFAC_h + +#include "ear.h" +#include "carfac_output.h" + +class CARFAC { +public: + int n_ears_; //number of ears + long fs_; //sample rate + int n_ch_; //number of channels in the CARFAC model + Ear *ears_; //array of Ear objects for mono/stereo/multichannel processing + + // 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(int n_ears, long fs, CARParams car_params, IHCParams ihc_params, + AGCParams agc_params); + + //The 'Run' method processes an entire file with the current model, using + //subsequent calls to the 'RunSegment' method + CARFACOutput Run(FloatArray2d sound_data); + + //The 'RunSegment' method processes individual sound segments + void RunSegment(FloatArray2d sound_data, CARFACOutput *seg_output); +}; + + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/carfac_common.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,60 @@ +// +// 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" + +//Auditory filter nominal Equivalent Rectangular Bandwidth +//Ref: Glasberg and Moore: Hearing Research, 47 (1990), 103-138 +FPType ERBHz (FPType cf_hz, FPType erb_break_freq, FPType erb_q) { + + FPType erb; + erb = (erb_break_freq + cf_hz) / erb_q; + return erb; +} + +//An IHC-like sigmoidal detection nonlinearity for the CARFAC. +//Resulting conductance is in about [0...1.3405] +FPType CARFACDetect (FPType x) { + + FPType conductance, z; + FPType a = 0.175; + //offset of low-end tail into neg x territory + //this parameter is adjusted for the book, to make the 20% DC response + //threshold at 0.1 + z = x + a; + conductance = pow(z,3) / (pow(z,3) + pow(z,2) + 0.1); + //zero is the final answer for many points: + return conductance; +} + +FloatArray CARFACDetect (FloatArray x) { + + FloatArray conductance, z; + FPType a = 0.175; + //offset of low-end tail into neg x territory + //this parameter is adjusted for the book, to make the 20% DC response + //threshold at 0.1 + z = x + a; + conductance = (z * z * z) / ((z * z * z) + (z * z) + 0.1); + //zero is the final answer for many points: + return conductance; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/carfac_common.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,71 @@ +// +// 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. +// +// Two additional typedefs are defined for one and two dimensional arrays: +// FloatArray and FloatArray2d. 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_Open_Source_C__Library_CARFACCommon_h +#define CARFAC_Open_Source_C__Library_CARFACCommon_h + +#include <iostream> //Used for debugging output, could go in final version +#include <math.h> //Used during coefficient calculations +#include <Eigen/Dense> //Used for 1d and 2d floating point arrays +using namespace Eigen; + +#define PI 3.141592 +typedef float FPType; //Used to enable easy switching in precision level + +//typedefs for Eigen floating point arrays +typedef Eigen::Array<FPType,Dynamic,1> FloatArray; //1d floating point array +typedef Eigen::Array<FPType,Dynamic,Dynamic> FloatArray2d; //2d fpoint array + +// Function: ERBHz +// Auditory filter nominal Equivalent Rectangular Bandwidth +// Ref: Glasberg and Moore: Hearing Research, 47 (1990), 103-138 +FPType ERBHz(FPType cf_hz, FPType erb_break_freq, FPType erb_q); + +// Function CARFACDetect +// TODO explain a bit more +FPType CARFACDetect (FPType x); +FloatArray CARFACDetect (FloatArray x); +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/carfac_output.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,37 @@ +// +// carfac_output.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_output.h" + +void CARFACOutput::InitOutput(int n_ears, int n_ch, long n_tp){ + n_ears_ = n_ears; + ears_ = new EarOutput[n_ears_]; + for (int i = 0; i < n_ears_; i++){ + ears_[i].InitOutput(n_ch,n_tp); + } +} + +void CARFACOutput::MergeOutput(CARFACOutput output, long start, long length){ + for (int i = 0; i < n_ears_; i++){ + ears_[i].MergeOutput(output.ears_[i], start, length); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/carfac_output.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,54 @@ +// +// carfac_output.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. +// +// ***************************************************************************** +// 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. +// +// The 'MergeOutput' method is for integrating a smaller CARFACOutput into a +// larger CARFACOutput object. This is intended to be used in the context of +// the CARFAC class's 'Run' and 'RunSegments' methods. + +#ifndef CARFAC_Open_Source_C__Library_carfac_output_h +#define CARFAC_Open_Source_C__Library_carfac_output_h + +#include "ear_output.h" + +class CARFACOutput { +public: + int n_ears_; + EarOutput *ears_; + void InitOutput(int n_ears, int n_ch, long n_tp); + void MergeOutput(CARFACOutput output, long start, long length); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/ear.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,268 @@ +// +// ear.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 "ear.h" + +void Ear::InitEar(long fs, CARParams car_p, IHCParams ihc_p, AGCParams agc_p){ + car_params_ = car_p; + ihc_params_ = ihc_p; + agc_params_ = agc_p; + n_ch_ = 0; + FPType pole_hz = car_params_.first_pole_theta_ * fs / (2 * PI); + 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_); + } + FloatArray pole_freqs(n_ch_); + pole_hz = car_params_.first_pole_theta_ * fs / (2 * PI); + 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_); + } + max_channels_per_octave_ = log(2) / log(pole_freqs(0) / pole_freqs(1)); + car_coeffs_.DesignFilters(car_params_, fs, &pole_freqs); + agc_coeffs_.DesignAGC(agc_params_, fs, n_ch_); + ihc_coeffs_.DesignIHC(ihc_params_, fs, n_ch_); + car_state_.InitCARState(car_coeffs_); + agc_state_.InitAGCState(agc_coeffs_); + ihc_state_.InitIHCState(ihc_coeffs_); + +} + +FloatArray Ear::CARStep(FPType input){ + FloatArray g(n_ch_); + FloatArray zb(n_ch_); + FloatArray za(n_ch_); + FloatArray v(n_ch_); + FloatArray nlf(n_ch_); + FloatArray r(n_ch_); + FloatArray z1(n_ch_); + FloatArray z2(n_ch_); + FloatArray zy(n_ch_); + FPType in_out; + + // do the DOHC stuff: + g = car_state_.g_memory_ + car_state_.dg_memory_; //interp g + zb = car_state_.zb_memory_ + car_state_.dzb_memory_; //AGC interpolation state + // update the nonlinear function of "velocity", and zA (delay of z2): + za = car_state_.za_memory_; + v = car_state_.z2_memory_ - za; + nlf = OHC_NLF(v); + r = car_coeffs_.r1_coeffs_ + (zb * nlf); // zB * nfl is "undamping" delta r + za = car_state_.z2_memory_; + // now reduce state by r and rotate with the fixed cos/sin coeffs: + z1 = r * ((car_coeffs_.a0_coeffs_ * car_state_.z1_memory_) - + (car_coeffs_.c0_coeffs_ * car_state_.z2_memory_)); + z2 = r * ((car_coeffs_.c0_coeffs_ * car_state_.z1_memory_) + + (car_coeffs_.a0_coeffs_ * car_state_.z2_memory_)); + zy = car_coeffs_.h_coeffs_ * z2; + // Ripple input-output path, instead of parallel, to avoid delay... + // this is the only part that doesn't get computed "in parallel": + in_out = input; + for (int ch = 0; ch < n_ch_; ch++){ + z1(ch) = z1(ch) + in_out; + // ripple, saving final channel outputs in zY + in_out = g(ch) * (in_out + zy(ch)); + zy(ch) = in_out; + } + car_state_.z1_memory_ = z1; + car_state_.z2_memory_ = z2; + car_state_.za_memory_ = za; + car_state_.zb_memory_ = zb; + car_state_.zy_memory_ = zy; + car_state_.g_memory_ = g; + // car_out is equal to zy state; + return zy; +} + +// start with a quadratic nonlinear function, and limit it via a +// rational function; make the result go to zero at high +// absolute velocities, so it will do nothing there. +FloatArray Ear::OHC_NLF(FloatArray velocities){ + FloatArray nlf(n_ch_); + nlf = 1 / ((velocities * car_coeffs_.velocity_scale_) + + (car_coeffs_.v_offset_ * car_coeffs_.v_offset_)); + return nlf; +} + +// One sample-time update of inner-hair-cell (IHC) model, including the +// detection nonlinearity and one or two capacitor state variables. +FloatArray Ear::IHCStep(FloatArray car_out){ + FloatArray ihc_out(n_ch_); + FloatArray ac_diff(n_ch_); + FloatArray conductance(n_ch_); + 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_hwr_) { + //TODO Figure out best implementation with Eigen max/min methods + for (int ch = 0; ch < n_ch_; ch++){ + FPType a; + if (ac_diff(ch) > 0){ + a = ac_diff(ch); + } else { + a = 0; + } + if (a < 2){ + ihc_out(ch) = a; + } else { + ihc_out(ch) = 2; + } + } + + } else { + conductance = CARFACDetect(ac_diff); + if (ihc_coeffs_.one_cap_) { + ihc_out = conductance * ihc_state_.cap1_voltage_; + ihc_state_.cap1_voltage_ = ihc_state_.cap1_voltage_ - + (ihc_out * ihc_coeffs_.out1_rate_) + + ((1 - ihc_state_.cap1_voltage_) + * ihc_coeffs_.in1_rate_); + } else { + ihc_out = conductance * ihc_state_.cap2_voltage_; + ihc_state_.cap1_voltage_ = ihc_state_.cap1_voltage_ - + ((ihc_state_.cap1_voltage_ - ihc_state_.cap2_voltage_) + * ihc_coeffs_.out1_rate_) + + ((1 - ihc_state_.cap1_voltage_) * ihc_coeffs_.in1_rate_); + ihc_state_.cap2_voltage_ = ihc_state_.cap2_voltage_ - + (ihc_out * ihc_coeffs_.out2_rate_) + + ((ihc_state_.cap1_voltage_ - ihc_state_.cap2_voltage_) + * ihc_coeffs_.in2_rate_); + } + // smooth it twice with LPF: + ihc_out = ihc_out * ihc_coeffs_.output_gain_; + ihc_state_.lpf1_state_ = ihc_state_.lpf1_state_ + + (ihc_coeffs_.lpf_coeff_ * (ihc_out - ihc_state_.lpf1_state_)); + ihc_state_.lpf2_state_ = ihc_state_.lpf2_state_ + + (ihc_coeffs_.lpf_coeff_ * + (ihc_state_.lpf1_state_ - ihc_state_.lpf2_state_)); + ihc_out = ihc_state_.lpf2_state_ - ihc_coeffs_.rest_output_; + } + ihc_state_.ihc_accum_ += ihc_out; + return ihc_out; +} + +bool Ear::AGCStep(FloatArray ihc_out){ + int stage = 0; + FloatArray agc_in(n_ch_); + agc_in = agc_coeffs_.detect_scale_ * ihc_out; + bool updated = AGCRecurse(stage, agc_in); + return updated; +} + +bool Ear::AGCRecurse(int stage, FloatArray agc_in){ + bool updated = true; + // decim factor for this stage, relative to input or prev. stage: + int decim = agc_coeffs_.decimation_(stage); + // decim phase of this stage (do work on phase 0 only): + //TODO FIX MODULO + + int decim_phase = agc_state_.decim_phase_(stage); + decim_phase = decim_phase % decim; + agc_state_.decim_phase_(stage) = decim_phase; + // accumulate input for this stage from detect or previous stage: + agc_state_.input_accum_.block(0,stage,n_ch_,1) = + agc_state_.input_accum_.block(0,stage,n_ch_,1) + agc_in; + + // nothing else to do if it's not the right decim_phase + if (decim_phase == 0){ + // do lots of work, at decimated rate. + // decimated inputs for this stage, and to be decimated more for next: + agc_in = agc_state_.input_accum_.block(0,stage,n_ch_,1) / decim; + // reset accumulator: + agc_state_.input_accum_.block(0,stage,n_ch_,1) = FloatArray::Zero(n_ch_); + + if (stage < (agc_coeffs_.decimation_.size() - 1)){ + // recurse to evaluate next stage(s) + updated = AGCRecurse(stage+1, agc_in); + // and add its output to this stage input, whether it updated or not: + agc_in = agc_in + (agc_coeffs_.agc_stage_gain_ * + agc_state_.agc_memory_.block(0,stage+1,n_ch_,1)); + } + FloatArray agc_stage_state = agc_state_.agc_memory_.block(0,stage,n_ch_,1); + // first-order recursive smoothing filter update, in time: + agc_stage_state = agc_stage_state + (agc_coeffs_.agc_epsilon_(stage) * + (agc_in - agc_stage_state)); + agc_stage_state = AGCSpatialSmooth(stage, agc_stage_state); + agc_state_.agc_memory_.block(0,stage,n_ch_,1) = agc_stage_state; + } else { + updated = false; + } + return updated; +} + +FloatArray Ear::AGCSpatialSmooth(int stage, FloatArray stage_state){ + int n_iterations = agc_coeffs_.agc_spatial_iterations_(stage); + bool use_fir; + if (n_iterations < 4){ + use_fir = true; + } else { + use_fir = false; + } + + if (use_fir) { + FloatArray fir_coeffs = agc_coeffs_.agc_spatial_fir_.block(0,stage,3,1); + FloatArray ss_tap1(n_ch_); + FloatArray ss_tap2(n_ch_); + FloatArray ss_tap3(n_ch_); + FloatArray ss_tap4(n_ch_); + int n_taps = agc_coeffs_.agc_spatial_n_taps_(stage); + //Initialize first two taps of stage state, used for both 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); + switch (n_taps) { + case 3: + stage_state = (fir_coeffs(0) * ss_tap1) + + (fir_coeffs(1) * stage_state) + + (fir_coeffs(2) * ss_tap2); + break; + case 5: + //Initialize last two taps of stage state, used for 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); + + stage_state = (fir_coeffs(0) * (ss_tap3 + ss_tap1)) + + (fir_coeffs(1) * stage_state) + + (fir_coeffs(2) * (ss_tap2 + ss_tap4)); + break; + default: + //TODO Throw Error + std::cout << "Error: bad n-taps in AGCSpatialSmooth" << std::endl; + } + + } else { + stage_state = AGCSmoothDoubleExponential(stage_state); + } + return stage_state; +} + +FloatArray Ear::AGCSmoothDoubleExponential(FloatArray stage_state){ + return stage_state; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/ear.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,55 @@ +// +// ear.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_Open_Source_C__Library_Ear_h +#define CARFAC_Open_Source_C__Library_Ear_h + +#include "car_state.h" +#include "ihc_state.h" +#include "agc_state.h" + + +class Ear { +public: + int n_ch_; + FPType max_channels_per_octave_; + CARParams car_params_; + IHCParams ihc_params_; + AGCParams agc_params_; + CARCoeffs car_coeffs_; + IHCCoeffs ihc_coeffs_; + AGCCoeffs agc_coeffs_; + CARState car_state_; + IHCState ihc_state_; + AGCState agc_state_; + + void InitEar(long fs, CARParams car_p, IHCParams ihc_p, AGCParams agc_p); + FloatArray CARStep(FPType input); + FloatArray OHC_NLF(FloatArray velocities); + FloatArray IHCStep(FloatArray car_out); + bool AGCStep(FloatArray ihc_out); + bool AGCRecurse(int stage, FloatArray agc_in); + FloatArray AGCSpatialSmooth(int stage, FloatArray stage_state); + FloatArray AGCSmoothDoubleExponential(FloatArray stage_state); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/ear_output.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,43 @@ +// +// ear_output.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 "ear_output.h" + +void EarOutput::InitOutput(int n_ch, long n_tp){ + n_ch_ = n_ch; + n_timepoints_ = n_tp; + nap_.resize(n_ch_,n_timepoints_); + bm_.resize(n_ch_,n_timepoints_); + ohc_.resize(n_ch_,n_timepoints_); + agc_.resize(n_ch_,n_timepoints_); +} + +void EarOutput::MergeOutput(EarOutput ear_output, long start, long length){ + nap_.block(0, start, n_ch_, length) = ear_output.nap_.block(0, 0, n_ch_, + length); + bm_.block(0, start, n_ch_, length) = ear_output.bm_.block(0, 0, n_ch_, + length); + ohc_.block(0, start, n_ch_, length) = ear_output.ohc_.block(0, 0, n_ch_, + length); + agc_.block(0, start, n_ch_, length) = ear_output.agc_.block(0, 0, n_ch_, + length); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/ear_output.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,41 @@ +// +// ear_output.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_Open_Source_C___Library_ear_output_h +#define CARFAC_Open_Source_C___Library_ear_output_h + +#include "carfac_common.h" + +class EarOutput { +public: + int n_ch_; + long n_timepoints_; + FloatArray2d nap_; + FloatArray2d nap_decim_; + FloatArray2d ohc_; + FloatArray2d agc_; + FloatArray2d bm_; + void InitOutput(int n_ch, long n_tp); + void MergeOutput(EarOutput output, long start, long length); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/ihc_coeffs.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,97 @@ +// +// ihc_coeffs.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 "ihc_coeffs.h" + +//This method has been created for debugging purposes and depends on <iostream>. +//Could possibly be removed in the final version to reduce dependencies. +void IHCCoeffs::OutputCoeffs(){ + std::cout << "IHCCoeffs Values" << std::endl; + std::cout << "****************" << std::endl; + std::cout << "n_ch_ = " << n_ch_ << std::endl; + std::cout << "just_hwr_ = " << just_hwr_ << std::endl; + std::cout << "one_cap_ = " << one_cap_ << std::endl; + std::cout << "lpf_coeff_ = " << lpf_coeff_ << std::endl; + std::cout << "out1_rate_ = " << out1_rate_ << std::endl; + std::cout << "in1_rate_ = " << in1_rate_ << std::endl; + std::cout << "out2_rate_ = " << out2_rate_ << std::endl; + std::cout << "in2_rate_ = " << in2_rate_ << std::endl; + std::cout << "output_gain_ = " << output_gain_ << std::endl; + std::cout << "rest_output_ = " << rest_output_ << std::endl; + std::cout << "rest_cap1_ = " << rest_cap1_ << std::endl; + std::cout << "rest_cap2_ = " << rest_cap2_ << std::endl; + std::cout << "ac_coeff_ = " << ac_coeff_ << std::endl << std::endl; +} + +void IHCCoeffs::DesignIHC(IHCParams ihc_params, long fs, int n_ch){ + if (ihc_params.just_hwr_){ + n_ch_ = n_ch; + just_hwr_ = ihc_params.just_hwr_; + } else { + if (ihc_params.one_cap_){ + ro_ = 1 / CARFACDetect(10); + c_ = ihc_params.tau1_out_ / ro_; + ri_ = ihc_params.tau1_in_ / c_; + saturation_output_ = 1 / ((2 * ro_) + ri_); + r0_ = 1 / CARFACDetect(0); + current_ = 1 / (ri_ + r0_); + cap1_voltage_ = 1 - (current_ * ri_); + + n_ch_ = n_ch; + just_hwr_ = false; + lpf_coeff_ = 1 - exp( -1 / (ihc_params.tau_lpf_ * fs)); + out1_rate_ = ro_ / (ihc_params.tau1_out_ * fs); + in1_rate_ = 1 / (ihc_params.tau1_in_ * fs); + one_cap_ = ihc_params.one_cap_; + output_gain_ = 1 / (saturation_output_ - current_); + rest_output_ = current_ / (saturation_output_ - current_); + rest_cap1_ = cap1_voltage_; + + + } else { + ro_ = 1 / CARFACDetect(10); + c2_ = ihc_params.tau2_out_ / ro_; + r2_ = ihc_params.tau2_in_ / c2_; + c1_ = ihc_params.tau1_out_ / r2_; + r1_ = ihc_params.tau1_in_ / c1_; + saturation_output_ = 1 / (2 * ro_ + r2_ + r1_); + r0_ = 1 / CARFACDetect(0); + current_ = 1 / (r1_ + r2_ + r0_); + cap1_voltage_ = 1 - (current_ * r1_); + cap2_voltage_ = cap1_voltage_ - (current_ * r2_); + + n_ch_ = n_ch; + just_hwr_ = false; + lpf_coeff_ = 1 - exp(-1 / (ihc_params.tau_lpf_ * fs)); + out1_rate_ = 1 / (ihc_params.tau1_out_ * fs); + in1_rate_ = 1 / (ihc_params.tau1_in_ * fs); + out2_rate_ = ro_ / (ihc_params.tau2_out_ * fs); + in2_rate_ = 1 / (ihc_params.tau2_in_ * fs); + one_cap_ = ihc_params.one_cap_; + output_gain_ = 1 / (saturation_output_ - current_); + rest_output_ = current_ / (saturation_output_ - current_); + rest_cap1_ = cap1_voltage_; + rest_cap2_ = cap2_voltage_; + } + } + ac_coeff_ = 2 * PI * ihc_params.ac_corner_hz_ / fs; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/ihc_coeffs.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,52 @@ +// +// 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_Open_Source_C__Library_IHCCoeffs_h +#define CARFAC_Open_Source_C__Library_IHCCoeffs_h + +#include "ihc_params.h" + +class IHCCoeffs { +public: + int n_ch_; + bool just_hwr_; + bool one_cap_; + 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 ro_, c_, ri_, r0_, saturation_output_, current_, cap1_voltage_, + cap2_voltage_; + FPType c2_, r2_, c1_, r1_; + + void OutputCoeffs(); //Method to view coeffs, could go in final version + void DesignIHC(IHCParams ihc_params, long fs, int n_ch); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/ihc_params.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,65 @@ +// +// ihc_params.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 "ihc_params.h" + + +//Default constructor for IHCParams initializes with the settings from Lyon's +//book 'Human and Machine Hearing' +IHCParams::IHCParams(){ + just_hwr_ = false; //not just a simple HWR + one_cap_ = true; //uses the Allen model, as in Lyon's book + tau_lpf_ = 0.000080; //80 microseconds smoothing twice + tau1_out_ = 0.0005; //depletion tau is pretty fast + tau1_in_ = 0.010; //recovery tau is slower + tau2_out_ = 0.0025; + tau2_in_ = 0.005; + ac_corner_hz_ = 20; +} + +//OutputParams method uses <iostream> for debugging purposes, could go in the +//final version +void IHCParams::OutputParams(){ + std::cout << "IHCParams Values" << std::endl; + std::cout << "****************" << std::endl; + std::cout << "just_hwr_ = " << just_hwr_ << std::endl; + std::cout << "one_cap_ = " << one_cap_ << std::endl; + std::cout << "tau_lpf_ = " << tau_lpf_ << std::endl; + std::cout << "tau1_out_ = " << tau1_out_ << std::endl; + std::cout << "tau1_in_ = " << tau1_in_ << std::endl; + std::cout << "tau2_out_ = " << tau2_out_ << std::endl; + std::cout << "tau2_in_ = " << tau2_in_ << std::endl; + std::cout << "ac_corner_hz_ = " << ac_corner_hz_ << std::endl << std::endl; +} + +//SetParams method allows for use of different inner hair cell parameters +void IHCParams::SetParams(bool jh, bool oc, FPType tlpf, FPType t1out, + FPType t1in, FPType t2out, FPType t2in, FPType acchz){ + just_hwr_ = jh; + one_cap_ = oc; + tau_lpf_ = tlpf; + tau1_out_ = t1out; + tau1_in_ = t1in; + tau2_out_ = t2out; + tau2_in_ = t2in; + ac_corner_hz_ = acchz; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/ihc_params.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,45 @@ +// +// 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_Open_Source_C__Library_IHCParams_h +#define CARFAC_Open_Source_C__Library_IHCParams_h + +#include "carfac_common.h" + +class IHCParams { +public: + bool just_hwr_; + bool one_cap_; + FPType tau_lpf_; + FPType tau1_out_; + FPType tau1_in_; + FPType tau2_out_; + FPType tau2_in_; + FPType ac_corner_hz_; + + IHCParams(); + void OutputParams(); //Output current parameter values using std::cout + void SetParams(bool jh, bool oc, FPType tlpf, FPType t1out, FPType t1in, + FPType t2out, FPType t2in, FPType acchz);//Method to set non-default params +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/ihc_state.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,39 @@ +// +// ihc_state.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 "ihc_state.h" + +void IHCState::InitIHCState(IHCCoeffs ihc_coeffs){ + n_ch_ = ihc_coeffs.n_ch_; + ihc_accum_ = FloatArray::Zero(n_ch_); + if (! ihc_coeffs.just_hwr_){ + ac_coupler_ = FloatArray::Zero(n_ch_); + lpf1_state_ = ihc_coeffs.rest_output_ * FloatArray::Ones(n_ch_); + lpf2_state_ = ihc_coeffs.rest_output_ * FloatArray::Ones(n_ch_); + if (ihc_coeffs.one_cap_){ + cap1_voltage_ = ihc_coeffs.rest_cap1_ * FloatArray::Ones(n_ch_); + } else { + cap1_voltage_ = ihc_coeffs.rest_cap1_ * FloatArray::Ones(n_ch_); + cap2_voltage_ = ihc_coeffs.rest_cap2_ * FloatArray::Ones(n_ch_); + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/ihc_state.h Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,42 @@ +// +// 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_Open_Source_C__Library_IHCState_h +#define CARFAC_Open_Source_C__Library_IHCState_h + +#include "ihc_coeffs.h" + +class IHCState { +public: + int n_ch_; + FloatArray ihc_accum_; + FloatArray cap1_voltage_; + FloatArray cap2_voltage_; + FloatArray lpf1_state_; + FloatArray lpf2_state_; + FloatArray ac_coupler_; + + void InitIHCState(IHCCoeffs ihc_coeffs); + +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/main.cc Mon May 13 22:51:15 2013 +0000 @@ -0,0 +1,117 @@ +// +// main.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. +// +// ***************************************************************************** +// main.cc +// ***************************************************************************** +// This 'main' file is not currently intended as part of the CARFAC distribution, +// but serves as a testbed for debugging and implementing various aspects of the +// library. It currently includes the "libsndfile" API for loading soundfiles: +// +// http://www.mega-nerd.com/libsndfile/ +// +// I've currently tested the code on Mac OS X 10.8 using XCode and dynamically +// linking to the libsndfile.dylib file. Two helper functions 'ReadSound' and +// 'ReadSoundInfo' are used to obtain header information (needed for the CARFAC +// design stage) and sound data (for running the model). +#include <sndfile.h> +#include "carfac.h" + +// ReadSound takes a character array (filename string) as an argument and +// returns a two dimensional (samples x channels) FloatArray (Eigen ArrayXX) +// containing the sound data +FloatArray2d ReadSound(const char * filename){ + FloatArray2d mysnd; //output data + SNDFILE *sf; + SF_INFO info; + long num, num_items; + double *buf; + long f,sr,c; + sf = sf_open(filename,SFM_READ,&info); + if (sf == NULL) + { + std::cout << "Failed to open the file" << std::endl; + return mysnd; + } + f = info.frames; + sr = info.samplerate; + c = info.channels; + num_items = f*c; + buf = new double[num_items]; + num = sf_read_double(sf,buf,num_items); + mysnd.resize(f,c); + int j = 0; + for(int i = 0; i < num_items; i = i + 2){ + mysnd(j,0) = buf[i]; + mysnd(j,1) = buf[i+1]; + j++; + } + sf_close(sf); + return mysnd; +}; + +// ReadSoundInfo takes a character array (filename string) as an argument and +// returns an SF_INFO structure containing the sample rate and channel info +// needed during the call to CARFAC::Design +SF_INFO ReadSoundInfo(const char * filename){ + SNDFILE *sf; + SF_INFO info; + sf = sf_open(filename,SFM_READ,&info); + if (sf == NULL) + { + std::cout << "Failed to open the file" << std::endl; + return info; + } + return info; +}; + + + + +// This 'main' function serves as the primary testbed for this C++ CARFAC +// implementation. It currently uses a hardcoded filename to obtain sound file +// info and sound data, and designs a CARFAC on the basis of the header data +// using the default parameters. +int main() +{ + //Here we specify a path to a test file + const char * filename = "/Users/alexbrandmeyer/aimc/carfac/test_signal.wav"; + + //Now we load the header info and sound data + SF_INFO info = ReadSoundInfo(filename); + FloatArray2d mysnd = ReadSound(filename); + //These initialze the default parameter objects needed for the CARFAC design + CARParams *car_params = new CARParams(); + IHCParams *ihc_params = new IHCParams(); + AGCParams *agc_params = new AGCParams(); + + //This initializes the CARFAC object and runs the design method + CARFAC *mycf = new CARFAC(); + mycf->Design(info.channels,info.samplerate, *car_params, *ihc_params, + *agc_params); + std::cout << "CARFAC Object Created" << std::endl; + + //Now we run the model on the test data + CARFACOutput output = mycf->Run(mysnd); + return 0; +} +