[aimc] r292 committed - Additional changes to C++ CARFAC on the basis of ronw's comments on r2...

1 view
Skip to first unread message

ai...@googlecode.com

unread,
Jun 4, 2013, 2:46:56 PM6/4/13
to aimc...@googlegroups.com
Revision: 292
Author: alexbrandmeyer
Date: Tue Jun 4 11:30:22 2013
Log: Additional changes to C++ CARFAC on the basis of ronw's comments
on r289. Moved CARFAC::Design to CARFAC::CARFAC and CARFAC::Reset(), moved
carfac_common.h to common.h, CARFACDetect to carfac_util.h/cc, FloatArray
and Float2dArray to ArrayX and ArrayXX, improved variable naming, made a
start on improved commenting documentation.
http://code.google.com/p/aimc/source/detail?r=292

Added:
/trunk/carfac/agc.h
/trunk/carfac/car.h
/trunk/carfac/carfac_util.cc
/trunk/carfac/carfac_util.h
/trunk/carfac/common.h
/trunk/carfac/ihc.h
Deleted:
/trunk/carfac/agc_coeffs.h
/trunk/carfac/agc_params.h
/trunk/carfac/agc_state.h
/trunk/carfac/car_coeffs.h
/trunk/carfac/car_params.h
/trunk/carfac/car_state.h
/trunk/carfac/carfac_common.cc
/trunk/carfac/carfac_common.h
/trunk/carfac/ihc_coeffs.h
/trunk/carfac/ihc_params.h
/trunk/carfac/ihc_state.h
Modified:
/trunk/carfac/SConstruct
/trunk/carfac/carfac.cc
/trunk/carfac/carfac.h
/trunk/carfac/carfac_output.cc
/trunk/carfac/carfac_output.h
/trunk/carfac/carfac_test.cc
/trunk/carfac/ear.cc
/trunk/carfac/ear.h
/trunk/carfac/sai.cc
/trunk/carfac/sai.h
/trunk/carfac/sai_test.cc

=======================================
--- /dev/null
+++ /trunk/carfac/agc.h Tue Jun 4 11:30:22 2013
@@ -0,0 +1,80 @@
+//
+// agc.h
+// CARFAC Open Source C++ Library
+//
+// Created by Alex Brandmeyer on 5/30/13.
+//
+// This C++ file is part of an implementation of Lyon's cochlear model:
+// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
+// to supplement Lyon's upcoming book "Human and Machine Hearing"
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CARFAC_AGC_H
+#define CARFAC_AGC_H
+
+#include <vector>
+#include "common.h"
+
+struct AGCParams {
+ AGCParams() {
+ num_stages = 4;
+ agc_stage_gain = 2.0;
+ time_constants.resize(num_stages);
+ agc1_scales.resize(num_stages);
+ agc2_scales.resize(num_stages);
+ agc1_scales[0] = 1.0;
+ agc2_scales[0] = 1.65;
+ time_constants[0] = 0.002;
+ for (int i = 1; i < num_stages; ++i) {
+ agc1_scales[i] = agc1_scales[i - 1] * sqrt(2.0);
+ agc2_scales[i] = agc2_scales[i - 1] * sqrt(2.0);
+ time_constants[i] = time_constants[i - 1] * 4.0;
+ }
+ decimation = {8, 2, 2, 2};
+ agc_mix_coeff = 0.5;
+ }
+ int num_stages;
+ FPType agc_stage_gain;
+ FPType agc_mix_coeff;
+ std::vector<FPType> time_constants;
+ std::vector<int> decimation;
+ std::vector<FPType> agc1_scales;
+ std::vector<FPType> agc2_scales;
+};
+
+struct AGCCoeffs {
+ int num_agc_stages;
+ FPType agc_stage_gain;
+ FPType agc_epsilon;
+ int decimation;
+ FPType agc_pole_z1;
+ FPType agc_pole_z2;
+ int agc_spatial_iterations;
+ FPType agc_spatial_fir_left;
+ FPType agc_spatial_fir_mid;
+ FPType agc_spatial_fir_right;
+ int agc_spatial_n_taps;
+ FPType agc_mix_coeffs;
+ FPType agc_gain;
+ FPType detect_scale;
+ FPType decim;
+};
+
+struct AGCState {
+ ArrayX agc_memory;
+ ArrayX input_accum;
+ int decim_phase;
+};
+
+#endif // CARFAC_AGC_H
=======================================
--- /dev/null
+++ /trunk/carfac/car.h Tue Jun 4 11:30:22 2013
@@ -0,0 +1,86 @@
+//
+// car.h
+// CARFAC Open Source C++ Library
+//
+// Created by Alex Brandmeyer on 5/10/13.
+//
+// This C++ file is part of an implementation of Lyon's cochlear model:
+// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
+// to supplement Lyon's upcoming book "Human and Machine Hearing"
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CARFAC_CAR_H
+#define CARFAC_CAR_H
+
+#include "common.h"
+
+// A CARParams structure stores the necessary information needed by a
CARFAC
+// object to design the set of coefficients implementing 'The Cascade of
+// Asymmetric Resonators' described in the chapter of the same name in
Lyon's
+// book "Human and Machine Hearing".
+struct CARParams {
+ // The constructor initializes using default parameter values.
+ CARParams() {
+ velocity_scale = 0.1;
+ v_offset = 0.04;
+ min_zeta = 0.1;
+ max_zeta = 0.35;
+ first_pole_theta = 0.85 * kPi;
+ zero_ratio = sqrt(2.0);
+ high_f_damping_compression = 0.5;
+ erb_per_step = 0.5;
+ min_pole_hz = 30;
+ erb_break_freq = 165.3; // This is the Greenwood map's break
frequency.
+ // This represents Glassberg and Moore's high-cf ratio.
+ erb_q = 1000/(24.7*4.37);
+ };
+ FPType velocity_scale; // This is used for the velocity nonlinearity.
+ FPType v_offset; // The offset gives us quadratic part.
+ FPType min_zeta; // This is the minimum damping factor in mid-freq
channels.
+ FPType max_zeta; // This is the maximum damping factor in mid-freq
channels.
+ FPType first_pole_theta;
+ FPType zero_ratio; // This is how far zero is above the pole.
+ FPType high_f_damping_compression; // A range from 0 to 1 to compress
theta.
+ FPType erb_per_step;
+ FPType min_pole_hz;
+ FPType erb_break_freq;
+ FPType erb_q;
+};
+
+// The CAR coefficients are designed by the CARFAC::DesignCARCoeffs method,
+// which is called during initial construction and resetting of a CARFAC
object.
+struct CARCoeffs {
+ FPType velocity_scale;
+ FPType v_offset;
+ ArrayX r1_coeffs;
+ ArrayX a0_coeffs;
+ ArrayX c0_coeffs;
+ ArrayX h_coeffs;
+ ArrayX g0_coeffs;
+ ArrayX zr_coeffs;
+};
+
+
+struct CARState {
+ ArrayX z1_memory;
+ ArrayX z2_memory;
+ ArrayX za_memory;
+ ArrayX zb_memory;
+ ArrayX dzb_memory;
+ ArrayX zy_memory;
+ ArrayX g_memory;
+ ArrayX dg_memory;
+};
+
+#endif // CARFAC_CAR_H
=======================================
--- /dev/null
+++ /trunk/carfac/carfac_util.cc Tue Jun 4 11:30:22 2013
@@ -0,0 +1,35 @@
+//
+// carfac_util.cc
+// CARFAC Open Source C++ Library
+//
+// Created by Alex Brandmeyer on 6/3/13.
+//
+// This C++ file is part of an implementation of Lyon's cochlear model:
+// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
+// to supplement Lyon's upcoming book "Human and Machine Hearing"
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "carfac_util.h"
+
+ArrayX CARFACDetect (const ArrayX& x) {
+ ArrayX conductance, z, set;
+ FPType a = 0.175;
+ // This offsets the low-end tail into negative x territory.
+ // The parameter is adjusted for the book, to make the 20% DC response
+ // threshold at 0.1.
+ z = x + a;
+ // Zero is the final answer for many points.
+ conductance = (z < 0).select(0.0, (z*z*z) / (z*z*z + z*z + 0.1));
+ return conductance;
+}
=======================================
--- /dev/null
+++ /trunk/carfac/carfac_util.h Tue Jun 4 11:30:22 2013
@@ -0,0 +1,33 @@
+//
+// carfac_util.h
+// CARFAC Open Source C++ Library
+//
+// Created by Alex Brandmeyer on 5/10/13.
+//
+// This C++ file is part of an implementation of Lyon's cochlear model:
+// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
+// to supplement Lyon's upcoming book "Human and Machine Hearing"
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CARFAC_CARFAC_UTIL_H
+#define CARFAC_CARFAC_UTIL_H
+
+#include "common.h"
+
+// Function CARFACDetect
+// This returns the IHC detection nonilnearity function of the filter
output
+// values. This is here because it is called both in design and run
phases.
+ArrayX CARFACDetect(const ArrayX& x);
+
+#endif // CARFAC_CARFAC_UTIL_H
=======================================
--- /dev/null
+++ /trunk/carfac/common.h Tue Jun 4 11:30:22 2013
@@ -0,0 +1,48 @@
+//
+// common.h
+// CARFAC Open Source C++ Library
+//
+// Created by Alex Brandmeyer on 5/10/13.
+//
+// This C++ file is part of an implementation of Lyon's cochlear model:
+// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
+// to supplement Lyon's upcoming book "Human and Machine Hearing"
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CARFAC_COMMON_H
+#define CARFAC_COMMON_H
+
+// This macro disallows the copy constructor and operator= functions.
+// This should be used in the private: declarations for a class.
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+// The Eigen library is used extensively for floating point arrays.
+// For more information, see: http://eigen.tuxfamily.org
+#include <Eigen/Dense>
+
+// The 'FPType' typedef is used to enable easy switching in precision
level.
+// It's currently set to double for during the unit testing phase of the
+// project.
+typedef float FPType;
+// A typedef is used to define a one-dimensional Eigen array with the same
+// precision level as FPType.
+typedef Eigen::Array<FPType, Eigen::Dynamic, 1> ArrayX;
+typedef Eigen::Array<FPType, Eigen::Dynamic, Eigen::Dynamic> ArrayXX;
+
+// A fixed value of PI is defined throughout the project.
+static const FPType kPi = 3.141592653589793238;
+
+#endif // CARFAC_COMMON_H
=======================================
--- /dev/null
+++ /trunk/carfac/ihc.h Tue Jun 4 11:30:22 2013
@@ -0,0 +1,76 @@
+//
+// ihc.h
+// CARFAC Open Source C++ Library
+//
+// Created by Alex Brandmeyer on 5/30/13.
+//
+// This C++ file is part of an implementation of Lyon's cochlear model:
+// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
+// to supplement Lyon's upcoming book "Human and Machine Hearing"
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CARFAC_IHC_H
+#define CARFAC_IHC_H
+
+#include "common.h"
+
+struct IHCParams {
+ IHCParams() {
+ just_half_wave_rectify = false;
+ one_capacitor = true;
+ tau_lpf = 0.000080;
+ tau1_out = 0.0005;
+ tau1_in = 0.010;
+ tau2_out = 0.0025;
+ tau2_in = 0.005;
+ ac_corner_hz = 20.0;
+ };
+ bool just_half_wave_rectify;
+ bool one_capacitor;
+ FPType tau_lpf;
+ FPType tau1_out;
+ FPType tau1_in;
+ FPType tau2_out;
+ FPType tau2_in;
+ FPType ac_corner_hz;
+};
+
+struct IHCCoeffs {
+ bool just_half_wave_rectify;
+ bool one_capacitor;
+ FPType lpf_coeff;
+ FPType out1_rate;
+ FPType in1_rate;
+ FPType out2_rate;
+ FPType in2_rate;
+ FPType output_gain;
+ FPType rest_output;
+ FPType rest_cap1;
+ FPType rest_cap2;
+ FPType ac_coeff;
+ FPType cap1_voltage;
+ FPType cap2_voltage;
+};
+
+struct IHCState {
+ ArrayX ihc_out;
+ ArrayX ihc_accum;
+ ArrayX cap1_voltage;
+ ArrayX cap2_voltage;
+ ArrayX lpf1_state;
+ ArrayX lpf2_state;
+ ArrayX ac_coupler;
+};
+
+#endif // CARFAC_IHC_H
=======================================
--- /trunk/carfac/agc_coeffs.h Wed May 29 08:37:28 2013
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// agc_coeffs.h
-// CARFAC Open Source C++ Library
-//
-// Created by Alex Brandmeyer on 5/10/13.
-//
-// This C++ file is part of an implementation of Lyon's cochlear model:
-// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
-// to supplement Lyon's upcoming book "Human and Machine Hearing"
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CARFAC_AGC_COEFFS_H
-#define CARFAC_AGC_COEFFS_H
-
-#include "carfac_common.h"
-
-struct AGCCoeffs {
- int n_agc_stages;
- FPType agc_stage_gain;
- FPType agc_epsilon;
- int decimation;
- FPType agc_pole_z1;
- FPType agc_pole_z2;
- int agc_spatial_iterations;
- FPType agc_spatial_fir_left;
- FPType agc_spatial_fir_mid;
- FPType agc_spatial_fir_right;
- int agc_spatial_n_taps;
- FPType agc_mix_coeffs;
- FPType agc_gain;
- FPType detect_scale;
- FPType decim;
-};
-
-#endif // CARFAC_AGC_COEFFS_H
=======================================
--- /trunk/carfac/agc_params.h Wed May 29 08:37:28 2013
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// agc_params.h
-// CARFAC Open Source C++ Library
-//
-// Created by Alex Brandmeyer on 5/10/13.
-//
-// This C++ file is part of an implementation of Lyon's cochlear model:
-// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
-// to supplement Lyon's upcoming book "Human and Machine Hearing"
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CARFAC_AGC_PARAMS_H
-#define CARFAC_AGC_PARAMS_H
-
-#include <vector>
-#include "carfac_common.h"
-
-struct AGCParams {
- AGCParams() {
- n_stages = 4;
- agc_stage_gain = 2.0;
- time_constants.resize(n_stages);
- agc1_scales.resize(n_stages);
- agc2_scales.resize(n_stages);
- agc1_scales[0] = 1.0;
- agc2_scales[0] = 1.65;
- time_constants[0] = 0.002;
- for (int i = 1; i < n_stages; ++i) {
- agc1_scales[i] = agc1_scales[i - 1] * sqrt(2.0);
- agc2_scales[i] = agc2_scales[i - 1] * sqrt(2.0);
- time_constants[i] = time_constants[i - 1] * 4.0;
- }
- decimation = {8, 2, 2, 2};
- agc_mix_coeff = 0.5;
- }
- int n_stages;
- FPType agc_stage_gain;
- FPType agc_mix_coeff;
- std::vector<FPType> time_constants;
- std::vector<int> decimation;
- std::vector<FPType> agc1_scales;
- std::vector<FPType> agc2_scales;
-};
-
-#endif // CARFAC_AGC_PARAMS_H
=======================================
--- /trunk/carfac/agc_state.h Wed May 29 08:37:28 2013
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// agc_state.h
-// CARFAC Open Source C++ Library
-//
-// Created by Alex Brandmeyer on 5/10/13.
-//
-// This C++ file is part of an implementation of Lyon's cochlear model:
-// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
-// to supplement Lyon's upcoming book "Human and Machine Hearing"
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CARFAC_AGC_STATE_H
-#define CARFAC_AGC_STATE_H
-
-#include "carfac_common.h"
-
-struct AGCState {
- int n_ch;
- FloatArray agc_memory;
- FloatArray input_accum;
- int decim_phase;
-};
-
-#endif // CARFAC_AGC_STATE_H
=======================================
--- /trunk/carfac/car_coeffs.h Wed May 29 08:37:28 2013
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// car_coeffs.h
-// CARFAC Open Source C++ Library
-//
-// Created by Alex Brandmeyer on 5/10/13.
-//
-// This C++ file is part of an implementation of Lyon's cochlear model:
-// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
-// to supplement Lyon's upcoming book "Human and Machine Hearing"
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CARFAC_CAR_COEFFS_H
-#define CARFAC_CAR_COEFFS_H
-
-#include "carfac_common.h"
-
-struct CARCoeffs {
- int n_ch;
- FPType velocity_scale;
- FPType v_offset;
- FloatArray r1_coeffs;
- FloatArray a0_coeffs;
- FloatArray c0_coeffs;
- FloatArray h_coeffs;
- FloatArray g0_coeffs;
- FloatArray zr_coeffs;
-};
-
-#endif // CARFAC_CAR_COEFFS_H
=======================================
--- /trunk/carfac/car_params.h Wed May 29 08:37:28 2013
+++ /dev/null
@@ -1,57 +0,0 @@
-//
-// car_params.h
-// CARFAC Open Source C++ Library
-//
-// Created by Alex Brandmeyer on 5/10/13.
-//
-// This C++ file is part of an implementation of Lyon's cochlear model:
-// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
-// to supplement Lyon's upcoming book "Human and Machine Hearing"
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CARFAC_CAR_PARAMS_H
-#define CARFAC_CAR_PARAMS_H
-
-#include "carfac_common.h"
-
-struct CARParams {
- // The constructor initializes using default parameter values.
- CARParams() {
- velocity_scale = 0.1;
- v_offset = 0.04;
- min_zeta = 0.1;
- max_zeta = 0.35;
- first_pole_theta = 0.85 * kPi;
- zero_ratio = sqrt(2.0);
- high_f_damping_compression = 0.5;
- erb_per_step = 0.5;
- min_pole_hz = 30;
- erb_break_freq = 165.3; // This is the Greenwood map's break
frequency.
- // This represents Glassberg and Moore's high-cf ratio.
- erb_q = 1000/(24.7*4.37);
- };
- FPType velocity_scale; // This is used for the velocity nonlinearity.
- FPType v_offset; // The offset gives us quadratic part.
- FPType min_zeta; // This is the minimum damping factor in mid-freq
channels.
- FPType max_zeta; // This is the maximum damping factor in mid-freq
channels.
- FPType first_pole_theta;
- FPType zero_ratio; // This is how far zero is above the pole.
- FPType high_f_damping_compression; // A range from 0 to 1 to compress
theta.
- FPType erb_per_step;
- FPType min_pole_hz;
- FPType erb_break_freq;
- FPType erb_q;
-};
-
-#endif // CARFAC_CAR_PARAMS_H
=======================================
--- /trunk/carfac/car_state.h Wed May 29 08:37:28 2013
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// car_state.h
-// CARFAC Open Source C++ Library
-//
-// Created by Alex Brandmeyer on 5/10/13.
-//
-// This C++ file is part of an implementation of Lyon's cochlear model:
-// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
-// to supplement Lyon's upcoming book "Human and Machine Hearing"
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CARFAC_CAR_STATE_H
-#define CARFAC_CAR_STATE_H
-
-#include "carfac_common.h"
-
-struct CARState {
- FloatArray z1_memory;
- FloatArray z2_memory;
- FloatArray za_memory;
- FloatArray zb_memory;
- FloatArray dzb_memory;
- FloatArray zy_memory;
- FloatArray g_memory;
- FloatArray dg_memory;
-};
-
-#endif // CARFAC_CAR_STATE_H
=======================================
--- /trunk/carfac/carfac_common.cc Mon May 27 09:36:54 2013
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// carfac_common.cc
-// CARFAC Open Source C++ Library
-//
-// Created by Alex Brandmeyer on 5/10/13.
-//
-// This C++ file is part of an implementation of Lyon's cochlear model:
-// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
-// to supplement Lyon's upcoming book "Human and Machine Hearing"
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "carfac_common.h"
-
-FPType ERBHz (const FPType cf_hz, const FPType erb_break_freq,
- const FPType erb_q) {
- return (erb_break_freq + cf_hz) / erb_q;
-}
-
-FloatArray CARFACDetect (const FloatArray& x) {
- FloatArray conductance, z, set;
- FPType a = 0.175;
- // This offsets the low-end tail into negative x territory.
- // The parameter is adjusted for the book, to make the 20% DC response
- // threshold at 0.1.
- z = x + a;
- // Zero is the final answer for many points.
- conductance = (z < 0).select(0.0, (z*z*z) / (z*z*z + z*z + 0.1));
- return conductance;
-}
=======================================
--- /trunk/carfac/carfac_common.h Fri May 31 14:46:48 2013
+++ /dev/null
@@ -1,81 +0,0 @@
-//
-// carfac_common.h
-// CARFAC Open Source C++ Library
-//
-// Created by Alex Brandmeyer on 5/10/13.
-//
-// This C++ file is part of an implementation of Lyon's cochlear model:
-// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
-// to supplement Lyon's upcoming book "Human and Machine Hearing"
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//
*****************************************************************************
-// carfac_common.h
-//
*****************************************************************************
-// This file contains the base level definitions and includes used within
the
-// CARFAC C++ library. It also defines some low level functions which are
used
-// during the calculation of the various coefficient sets required by the
model.
-//
-// The current implementation of the library is dependent on the use of the
-// Eigen C++ library for linear algebra. Specifically, Eigen Arrays are
used
-// extensively for coefficient wise operations during both the design and
run
-// stages of the model.
-//
-// The 'FPType' typedef is specified in this file in order to enable quick
-// switching between precision levels (i.e. float vs. double) throughout
the
-// library. The remainder of the code uses this type for specifying
floating
-// point scalars.
-//
-// An additional typedefs are defined for one dimensional arrays:
FloatArray.
-// These in turn make use of FPType so that the precision level across
floating
-// point data is consistent.
-//
-// The functions 'ERBHz' and 'CARFACDetect' are defined here, and are used
-// during the design stage of a CARFAC model.
-
-#ifndef CARFAC_CARFAC_COMMON_H
-#define CARFAC_CARFAC_COMMON_H
-
-// The Eigen library is used extensively for floating point arrays.
-// For more information, see: http://eigen.tuxfamily.org
-#include <Eigen/Dense>
-
-using namespace Eigen;
-
-// The 'FPType' typedef is used to enable easy switching in precision
level.
-// It's currently set to double for during the unit testing phase of the
-// project.
-typedef double FPType;
-// A typedef is used to define a one-dimensional Eigen array with the same
-// precision level as FPType.
-typedef Eigen::Array<FPType, Dynamic, 1> FloatArray;
-typedef Eigen::Array<FPType, Dynamic, Dynamic> Float2dArray;
-
-// A fixed value of PI is defined throughout the project.
-static const FPType kPi = 3.141592653589793238;
-
-// Two helper functions are defined here for use by the different model
stages
-// in calculating coeffecients and during model runtime.
-// Function: ERBHz
-// Auditory filter nominal Equivalent Rectangular Bandwidth
-// Ref: Glasberg and Moore: Hearing Research, 47 (1990), 103-138
-FPType ERBHz(const FPType cf_hz, const FPType erb_break_freq,
- const FPType erb_q);
-
-// Function CARFACDetect
-// This returns the IHC detection nonilnearity function of the filter
output
-// values. This is here because it is called both in design and run
phases.
-FloatArray CARFACDetect(const FloatArray& x);
-
-#endif // CARFAC_CARFAC_COMMON_H
=======================================
--- /trunk/carfac/ihc_coeffs.h Wed May 29 08:37:28 2013
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// ihc_coeffs.h
-// CARFAC Open Source C++ Library
-//
-// Created by Alex Brandmeyer on 5/10/13.
-//
-// This C++ file is part of an implementation of Lyon's cochlear model:
-// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
-// to supplement Lyon's upcoming book "Human and Machine Hearing"
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CARFAC_IHC_COEFFS_H
-#define CARFAC_IHC_COEFFS_H
-
-#include "carfac_common.h"
-
-struct IHCCoeffs {
- bool just_half_wave_rectify;
- bool one_capacitor;
- FPType lpf_coeff;
- FPType out1_rate;
- FPType in1_rate;
- FPType out2_rate;
- FPType in2_rate;
- FPType output_gain;
- FPType rest_output;
- FPType rest_cap1;
- FPType rest_cap2;
- FPType ac_coeff;
- FPType cap1_voltage;
- FPType cap2_voltage;
-};
-
-#endif // CARFAC_IHC_COEFFS_H
=======================================
--- /trunk/carfac/ihc_params.h Wed May 29 08:37:28 2013
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// ihc_params.h
-// CARFAC Open Source C++ Library
-//
-// Created by Alex Brandmeyer on 5/10/13.
-//
-// This C++ file is part of an implementation of Lyon's cochlear model:
-// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
-// to supplement Lyon's upcoming book "Human and Machine Hearing"
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CARFAC_IHC_PARAMS_H
-#define CARFAC_IHC_PARAMS_H
-
-#include "carfac_common.h"
-
-struct IHCParams {
- IHCParams() {
- just_half_wave_rectify = false;
- one_capacitor = true;
- tau_lpf = 0.000080;
- tau1_out = 0.0005;
- tau1_in = 0.010;
- tau2_out = 0.0025;
- tau2_in = 0.005;
- ac_corner_hz = 20.0;
- };
- bool just_half_wave_rectify;
- bool one_capacitor;
- FPType tau_lpf;
- FPType tau1_out;
- FPType tau1_in;
- FPType tau2_out;
- FPType tau2_in;
- FPType ac_corner_hz;
-};
-
-#endif // CARFAC_IHC_PARAMS_H
=======================================
--- /trunk/carfac/ihc_state.h Wed May 29 08:37:28 2013
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// ihc_state.h
-// CARFAC Open Source C++ Library
-//
-// Created by Alex Brandmeyer on 5/10/13.
-//
-// This C++ file is part of an implementation of Lyon's cochlear model:
-// "Cascade of Asymmetric Resonators with Fast-Acting Compression"
-// to supplement Lyon's upcoming book "Human and Machine Hearing"
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef CARFAC_IHC_STATE_H
-#define CARFAC_IHC_STATE_H
-
-#include "carfac_common.h"
-
-struct IHCState {
- FloatArray ihc_out;
- FloatArray ihc_accum;
- FloatArray cap1_voltage;
- FloatArray cap2_voltage;
- FloatArray lpf1_state;
- FloatArray lpf2_state;
- FloatArray ac_coupler;
-};
-
-#endif // CARFAC_IHC_STATE_H
=======================================
--- /trunk/carfac/SConstruct Fri May 31 14:46:48 2013
+++ /trunk/carfac/SConstruct Tue Jun 4 11:30:22 2013
@@ -51,20 +51,15 @@
env.MergeFlags(['-std=c++11'])

carfac_sources = [
- 'agc_coeffs.h',
- 'agc_params.h',
- 'agc_state.h',
- 'car_coeffs.h',
+ 'agc.h',
+ 'car.h',
+ 'ihc.h',
'carfac.cc',
- 'carfac_common.cc',
+ 'common.h',
+ 'carfac_util.h',
'carfac_output.cc',
- 'car_params.h',
- 'car_state.h',
'ear.cc',
- 'ihc_coeffs.h',
- 'ihc_params.h',
- 'ihc_state.h',
- 'sai.cc',
+ 'sai.cc'
]
env.Library(target = 'carfac', source = carfac_sources)

=======================================
--- /trunk/carfac/carfac.cc Wed May 29 13:33:06 2013
+++ /trunk/carfac/carfac.cc Tue Jun 4 11:30:22 2013
@@ -21,41 +21,49 @@
// limitations under the License.

#include <assert.h>
+
#include "carfac.h"
+
using std::vector;

-void CARFAC::Design(const int n_ears, const FPType fs,
+CARFAC::CARFAC(const int num_ears, const FPType sample_rate,
const CARParams& car_params, const IHCParams&
ihc_params,
const AGCParams& agc_params) {
- n_ears_ = n_ears;
- fs_ = fs;
- ears_.resize(n_ears_);
- n_ch_ = 0;
- FPType pole_hz = car_params.first_pole_theta * fs / (2 * kPi);
- while (pole_hz > car_params.min_pole_hz) {
- ++n_ch_;
- pole_hz = pole_hz - car_params.erb_per_step *
- ERBHz(pole_hz, car_params.erb_break_freq, car_params.erb_q);
+ num_ears_ = num_ears;
+ sample_rate_ = sample_rate;
+ ears_.resize(num_ears_);
+ car_params_ = car_params;
+ ihc_params_ = ihc_params;
+ agc_params_ = agc_params;
+ Reset();
+}
+
+void CARFAC::Reset() {
+ num_channels_ = 0;
+ FPType pole_hz = car_params_.first_pole_theta * sample_rate_ / (2 * kPi);
+ while (pole_hz > car_params_.min_pole_hz) {
+ ++num_channels_;
+ pole_hz = pole_hz - car_params_.erb_per_step *
+ ERBHz(pole_hz, car_params_.erb_break_freq, car_params_.erb_q);
}
- pole_freqs_.resize(n_ch_);
- pole_hz = car_params.first_pole_theta * fs / (2 * kPi);
- for (int ch = 0; ch < n_ch_; ++ch) {
- pole_freqs_(ch) = pole_hz;
- pole_hz = pole_hz - car_params.erb_per_step *
- ERBHz(pole_hz, car_params.erb_break_freq, car_params.erb_q);
+ pole_freqs_.resize(num_channels_);
+ pole_hz = car_params_.first_pole_theta * sample_rate_ / (2 * kPi);
+ for (int channel = 0; channel < num_channels_; ++channel) {
+ pole_freqs_(channel) = pole_hz;
+ pole_hz = pole_hz - car_params_.erb_per_step *
+ ERBHz(pole_hz, car_params_.erb_break_freq, car_params_.erb_q);
}
max_channels_per_octave_ = log(2) / log(pole_freqs_(0) / pole_freqs_(1));
CARCoeffs car_coeffs;
IHCCoeffs ihc_coeffs;
std::vector<AGCCoeffs> agc_coeffs;
- DesignCARCoeffs(car_params, fs, pole_freqs_, &car_coeffs);
- DesignIHCCoeffs(ihc_params, fs, &ihc_coeffs);
+ DesignCARCoeffs(car_params_, sample_rate_, pole_freqs_, &car_coeffs);
+ DesignIHCCoeffs(ihc_params_, sample_rate_, &ihc_coeffs);
// This code initializes the coefficients for each of the AGC stages.
- DesignAGCCoeffs(agc_params, fs, &agc_coeffs);
+ DesignAGCCoeffs(agc_params_, sample_rate_, &agc_coeffs);
// Once we have the coefficient structure we can design the ears.
for (auto& ear : ears_) {
- ear.InitEar(n_ch_, fs_, car_coeffs, ihc_coeffs,
- agc_coeffs);
+ ear.Init(num_channels_, car_coeffs, ihc_coeffs, agc_coeffs);
}
}

@@ -65,21 +73,22 @@
// A nested loop structure is used to iterate through the individual
samples
// for each ear (audio channel).
bool updated; // This variable is used by the AGC stage.
- for (int32_t i = 0; i < length; ++i) {
- for (int j = 0; j < n_ears_; ++j) {
+ for (int32_t timepoint = 0; timepoint < length; ++timepoint) {
+ for (int audio_channel = 0; audio_channel < num_ears_;
++audio_channel) {
// First we create a reference to the current Ear object.
- Ear& ear = ears_[j];
+ Ear& ear = ears_[audio_channel];
// This stores the audio sample currently being processed.
- FPType input = sound_data[j][start+i];
+ FPType input = sound_data[audio_channel][start + timepoint];
+
// Now we apply the three stages of the model in sequence to the
current
// audio sample.
ear.CARStep(input);
ear.IHCStep(ear.car_out());
updated = ear.AGCStep(ear.ihc_out());
}
- seg_output->StoreOutput(ears_);
+ seg_output->AppendOutput(ears_);
if (updated) {
- if (n_ears_ > 1) {
+ if (num_ears_ > 1) {
CrossCouple();
}
if (! open_loop) {
@@ -90,19 +99,19 @@
}

void CARFAC::CrossCouple() {
- for (int stage = 0; stage < ears_[0].agc_nstages(); ++stage) {
+ for (int stage = 0; stage < ears_[0].agc_num_stages(); ++stage) {
if (ears_[0].agc_decim_phase(stage) > 0) {
break;
} else {
FPType mix_coeff = ears_[0].agc_mix_coeff(stage);
if (mix_coeff > 0) {
- FloatArray stage_state;
- FloatArray this_stage_values = FloatArray::Zero(n_ch_);
+ ArrayX stage_state;
+ ArrayX this_stage_values = ArrayX::Zero(num_channels_);
for (auto& ear : ears_) {
stage_state = ear.agc_memory(stage);
this_stage_values += stage_state;
}
- this_stage_values /= n_ears_;
+ this_stage_values /= num_ears_;
for (auto& ear : ears_) {
stage_state = ear.agc_memory(stage);
ear.set_agc_memory(stage, stage_state + mix_coeff *
@@ -115,7 +124,7 @@

void CARFAC::CloseAGCLoop() {
for (auto& ear: ears_) {
- FloatArray undamping = 1 - ear.agc_memory(0);
+ ArrayX undamping = 1 - ear.agc_memory(0);
// This updates the target stage gain for the new damping.
ear.set_dzb_memory((ear.zr_coeffs() * undamping - ear.zb_memory()) /
ear.agc_decimation(0));
@@ -124,51 +133,52 @@
}
}

-void CARFAC::DesignCARCoeffs(const CARParams& car_params, const FPType fs,
- const FloatArray& pole_freqs,
+void CARFAC::DesignCARCoeffs(const CARParams& car_params,
+ const FPType sample_rate,
+ const ArrayX& pole_freqs,
CARCoeffs* car_coeffs) {
- n_ch_ = pole_freqs.size();
+ num_channels_ = pole_freqs.size();
car_coeffs->velocity_scale = car_params.velocity_scale;
car_coeffs->v_offset = car_params.v_offset;
- car_coeffs->r1_coeffs.resize(n_ch_);
- car_coeffs->a0_coeffs.resize(n_ch_);
- car_coeffs->c0_coeffs.resize(n_ch_);
- car_coeffs->h_coeffs.resize(n_ch_);
- car_coeffs->g0_coeffs.resize(n_ch_);
+ car_coeffs->r1_coeffs.resize(num_channels_);
+ car_coeffs->a0_coeffs.resize(num_channels_);
+ car_coeffs->c0_coeffs.resize(num_channels_);
+ car_coeffs->h_coeffs.resize(num_channels_);
+ car_coeffs->g0_coeffs.resize(num_channels_);
FPType f = car_params.zero_ratio * car_params.zero_ratio - 1.0;
- FloatArray theta = pole_freqs * ((2.0 * kPi) / fs);
+ ArrayX theta = pole_freqs * ((2.0 * kPi) / sample_rate);
car_coeffs->c0_coeffs = theta.sin();
car_coeffs->a0_coeffs = theta.cos();
FPType ff = car_params.high_f_damping_compression;
- FloatArray x = theta / kPi;
+ ArrayX x = theta / kPi;
car_coeffs->zr_coeffs = kPi * (x - (ff * (x*x*x)));
FPType max_zeta = car_params.max_zeta;
FPType min_zeta = car_params.min_zeta;
car_coeffs->r1_coeffs = (1.0 - (car_coeffs->zr_coeffs * max_zeta));
- FloatArray erb_freqs(n_ch_);
- for (int ch=0; ch < n_ch_; ++ch) {
- erb_freqs(ch) = ERBHz(pole_freqs(ch), car_params.erb_break_freq,
+ ArrayX erb_freqs(num_channels_);
+ for (int channel = 0; channel < num_channels_; ++channel) {
+ erb_freqs(channel) = ERBHz(pole_freqs(channel),
car_params.erb_break_freq,
car_params.erb_q);
}
- FloatArray min_zetas = min_zeta + (0.25 * ((erb_freqs / pole_freqs) -
+ ArrayX min_zetas = min_zeta + (0.25 * ((erb_freqs / pole_freqs) -
min_zeta));
car_coeffs->zr_coeffs *= max_zeta - min_zetas;
car_coeffs->h_coeffs = car_coeffs->c0_coeffs * f;
- FloatArray relative_undamping = FloatArray::Ones(n_ch_);
- FloatArray r = car_coeffs->r1_coeffs + (car_coeffs->zr_coeffs *
+ ArrayX relative_undamping = ArrayX::Ones(num_channels_);
+ ArrayX r = car_coeffs->r1_coeffs + (car_coeffs->zr_coeffs *
relative_undamping);
car_coeffs->g0_coeffs = (1.0 - (2.0 * r * car_coeffs->a0_coeffs) +
(r*r)) /
(1 - (2 * r * car_coeffs->a0_coeffs) +
(car_coeffs->h_coeffs * r * car_coeffs->c0_coeffs) + (r*r));
}

-void CARFAC::DesignIHCCoeffs(const IHCParams& ihc_params, const FPType fs,
- IHCCoeffs* ihc_coeffs) {
+void CARFAC::DesignIHCCoeffs(const IHCParams& ihc_params,
+ const FPType sample_rate, IHCCoeffs*
ihc_coeffs) {
if (ihc_params.just_half_wave_rectify) {
ihc_coeffs->just_half_wave_rectify = ihc_params.just_half_wave_rectify;
} else {
// This section calculates conductance values using two pre-defined
scalars.
- FloatArray x(1);
+ ArrayX x(1);
FPType conduct_at_10, conduct_at_0;
x(0) = 10.0;
x = CARFACDetect(x);
@@ -185,9 +195,9 @@
FPType current = 1 / (ri + r0);
ihc_coeffs->cap1_voltage = 1 - (current * ri);
ihc_coeffs->just_half_wave_rectify = false;
- ihc_coeffs->lpf_coeff = 1 - exp( -1 / (ihc_params.tau_lpf * fs));
- ihc_coeffs->out1_rate = ro / (ihc_params.tau1_out * fs);
- ihc_coeffs->in1_rate = 1 / (ihc_params.tau1_in * fs);
+ ihc_coeffs->lpf_coeff = 1 - exp( -1 / (ihc_params.tau_lpf *
sample_rate));
+ ihc_coeffs->out1_rate = ro / (ihc_params.tau1_out * sample_rate);
+ ihc_coeffs->in1_rate = 1 / (ihc_params.tau1_in * sample_rate);
ihc_coeffs->one_capacitor = ihc_params.one_capacitor;
ihc_coeffs->output_gain = 1 / (saturation_output - current);
ihc_coeffs->rest_output = current / (saturation_output - current);
@@ -204,11 +214,11 @@
ihc_coeffs->cap1_voltage = 1 - (current * r1);
ihc_coeffs->cap2_voltage = ihc_coeffs->cap1_voltage - (current * r2);
ihc_coeffs->just_half_wave_rectify = false;
- ihc_coeffs->lpf_coeff = 1 - exp(-1 / (ihc_params.tau_lpf * fs));
- ihc_coeffs->out1_rate = 1 / (ihc_params.tau1_out * fs);
- ihc_coeffs->in1_rate = 1 / (ihc_params.tau1_in * fs);
- ihc_coeffs->out2_rate = ro / (ihc_params.tau2_out * fs);
- ihc_coeffs->in2_rate = 1 / (ihc_params.tau2_in * fs);
+ ihc_coeffs->lpf_coeff = 1 - exp(-1 / (ihc_params.tau_lpf *
sample_rate));
+ ihc_coeffs->out1_rate = 1 / (ihc_params.tau1_out * sample_rate);
+ ihc_coeffs->in1_rate = 1 / (ihc_params.tau1_in * sample_rate);
+ ihc_coeffs->out2_rate = ro / (ihc_params.tau2_out * sample_rate);
+ ihc_coeffs->in2_rate = 1 / (ihc_params.tau2_in * sample_rate);
ihc_coeffs->one_capacitor = ihc_params.one_capacitor;
ihc_coeffs->output_gain = 1 / (saturation_output - current);
ihc_coeffs->rest_output = current / (saturation_output - current);
@@ -216,17 +226,18 @@
ihc_coeffs->rest_cap2 = ihc_coeffs->cap2_voltage;
}
}
- ihc_coeffs->ac_coeff = 2 * kPi * ihc_params.ac_corner_hz / fs;
+ ihc_coeffs->ac_coeff = 2 * kPi * ihc_params.ac_corner_hz / sample_rate;
}

-void CARFAC::DesignAGCCoeffs(const AGCParams& agc_params, const FPType fs,
+void CARFAC::DesignAGCCoeffs(const AGCParams& agc_params,
+ const FPType sample_rate,
vector<AGCCoeffs>* agc_coeffs) {
- agc_coeffs->resize(agc_params.n_stages);
+ agc_coeffs->resize(agc_params.num_stages);
FPType previous_stage_gain = 0.0;
FPType decim = 1.0;
- for (int stage = 0; stage < agc_params.n_stages; ++stage) {
+ for (int stage = 0; stage < agc_params.num_stages; ++stage) {
AGCCoeffs& agc_coeff = agc_coeffs->at(stage);
- agc_coeff.n_agc_stages = agc_params.n_stages;
+ agc_coeff.num_agc_stages = agc_params.num_stages;
agc_coeff.agc_stage_gain = agc_params.agc_stage_gain;
vector<FPType> agc1_scales = agc_params.agc1_scales;
vector<FPType> agc2_scales = agc_params.agc2_scales;
@@ -238,8 +249,9 @@
FPType tau = time_constants[stage];
agc_coeff.decim = decim;
agc_coeff.decim *= agc_coeff.decimation;
- agc_coeff.agc_epsilon = 1 - exp((-1 * agc_coeff.decim) / (tau * fs));
- FPType n_times = tau * (fs / agc_coeff.decim);
+ agc_coeff.agc_epsilon = 1 - exp((-1 * agc_coeff.decim) /
+ (tau * sample_rate));
+ FPType n_times = tau * (sample_rate / agc_coeff.decim);
FPType delay = (agc2_scales[stage] - agc1_scales[stage]) / n_times;
FPType spread_sq = (pow(agc1_scales[stage], 2) +
pow(agc2_scales[stage], 2)) / n_times;
@@ -317,10 +329,15 @@
agc_coeff.agc_spatial_fir_right = fir_right;
total_dc_gain += pow(agc_coeff.agc_stage_gain, stage);
agc_coeff.agc_mix_coeffs = stage == 0 ? 0 : mix_coeff /
- (tau * (fs / agc_coeff.decim));
+ (tau * (sample_rate / agc_coeff.decim));
agc_coeff.agc_gain = total_dc_gain;
agc_coeff.detect_scale = 1 / total_dc_gain;
previous_stage_gain = agc_coeff.agc_gain;
decim = agc_coeff.decim;
}
}
+
+FPType CARFAC::ERBHz (const FPType center_frequency_hz,
+ const FPType erb_break_freq, const FPType erb_q) {
+ return (erb_break_freq + center_frequency_hz) / erb_q;
+}
=======================================
--- /trunk/carfac/carfac.h Wed May 29 13:33:06 2013
+++ /trunk/carfac/carfac.h Tue Jun 4 11:30:22 2013
@@ -19,69 +19,76 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
-//
*****************************************************************************
-// Class: CARFAC
-//
*****************************************************************************
-// The CARFAC class is the top-level class implementing the CAR-FAC C++
model.
-// A CARFAC object knows how to design its details from a modest set of
-// parameters, and knows how to process sound signals to produce "neural
-// activity patterns" (NAPs) which are contained in a CARFACOutput object.
-//
-// The 'Design' method is used to intialize the CARFAC model, and is passed
-// a set of CAR, IHC and AGC parameters along with sound file information
-// (channels and sample rate).
-//
-// The two methods 'Run' and 'RunSegment' are responsible for
-// processing sound signals. These both take two dimensional Eigen float
arrays
-// (samples x channels) as arguments and return CARFACOutput objects.

#ifndef CARFAC_CARFAC_H
#define CARFAC_CARFAC_H

#include <vector>
-#include "carfac_common.h"
-#include "car_params.h"
-#include "car_coeffs.h"
-#include "ihc_params.h"
-#include "ihc_coeffs.h"
-#include "agc_params.h"
-#include "agc_coeffs.h"
+
+#include "common.h"
+#include "carfac_util.h"
+#include "car.h"
+#include "ihc.h"
+#include "agc.h"
#include "ear.h"
#include "carfac_output.h"

+// This is the top-level class implementing the CAR-FAC C++ model. See the
+// chapter entitled 'The CAR-FAC Digital Cochlear Model' in Lyon's
book "Human
+// and Machine Hearing" for an overview.
+//
+// A CARFAC object knows how to design its details from a modest set of
+// parameters, and knows how to process sound signals to produce "neural
+// activity patterns" (NAPs) which are stored in a CARFACOutput object
during
+// the call to CARFAC::RunSegment.
class CARFAC {
public:
// The 'Design' method takes a set of CAR, IHC and AGC parameters along
with
// arguments specifying the number of 'ears' (audio file channels) and
sample
// rate. This initializes a vector of 'Ear' objects -- one for mono, two
for
- // stereo, or more. Each 'Ear' includes various sub-objects
representing the
- // parameters, designs (coeffs) ,and states of different parts of the
CAR-FAC
- // model.
- void Design(const int n_ears, const FPType fs, const CARParams&
car_params,
- const IHCParams& ihc_params, const AGCParams& agc_params);
- // The 'RunSegment' method processes individual sound segments
+ // stereo, or more.
+ CARFAC(const int num_ears, const FPType sample_rate,
+ const CARParams& car_params, const IHCParams& ihc_params,
+ const AGCParams& agc_params);
+
+ // The 'RunSegment' method processes individual sound segments and
stores the
+ // output of the model in a CARFACOutput object.
void RunSegment(const std::vector<std::vector<float>>& sound_data,
const int32_t start, const int32_t length,
const bool open_loop, CARFACOutput* seg_output);
+ void Reset();

private:
- void DesignCARCoeffs(const CARParams& car_params, const FPType fs,
- const FloatArray& pole_freqs, CARCoeffs*
car_coeffs);
- void DesignIHCCoeffs(const IHCParams& ihc_params, const FPType fs,
+ // TODO (alexbrandmeyer): figure out why this breaks object
initialization.
+ //DISALLOW_COPY_AND_ASSIGN(CARFAC);
+ void DesignCARCoeffs(const CARParams& car_params, const FPType
sample_rate,
+ const ArrayX& pole_freqs, CARCoeffs* car_coeffs);
+ void DesignIHCCoeffs(const IHCParams& ihc_params, const FPType
sample_rate,
IHCCoeffs* ihc_coeffs);
- void DesignAGCCoeffs(const AGCParams& agc_params, const FPType fs,
+ void DesignAGCCoeffs(const AGCParams& agc_params, const FPType
sample_rate,
std::vector<AGCCoeffs>* agc_coeffs);
void CrossCouple();
void CloseAGCLoop();
+
+ // Function: ERBHz
+ // Auditory filter nominal Equivalent Rectangular Bandwidth
+ // Ref: Glasberg and Moore: Hearing Research, 47 (1990), 103-138
+ // See also the section 'Auditory Frequency Scales' of the
chapter 'Acoustic
+ // Approaches and Auditory Influence' in "Human and Machine Hearing".
+ FPType ERBHz(const FPType center_frequency_hz, const FPType
erb_break_freq,
+ const FPType erb_q);

- int n_ears_; // This is the number of ears.
- FPType fs_; // This is our current sample rate.
- int n_ch_; // This is the number of channels in the CARFAC model.
+ CARParams car_params_;
+ IHCParams ihc_params_;
+ AGCParams agc_params_;
+ int num_ears_;
+ FPType sample_rate_;
+ int num_channels_;
FPType max_channels_per_octave_;
- // We store an array of Ear objects for mono/stereo/multichannel
processing:
+
+ // We store a vector of Ear objects for mono/stereo/multichannel
processing:
std::vector<Ear> ears_;
- FloatArray pole_freqs_;
+ ArrayX pole_freqs_;
};

#endif // CARFAC_CARFAC_H
=======================================
--- /trunk/carfac/carfac_output.cc Tue May 28 08:54:54 2013
+++ /trunk/carfac/carfac_output.cc Tue Jun 4 11:30:22 2013
@@ -24,10 +24,9 @@

using std::vector;

-void CARFACOutput::Init(const int n_ears, const bool store_nap,
- const bool store_nap_decim, const bool store_bm,
- const bool store_ohc, const bool store_agc) {
- n_ears_ = n_ears;
+CARFACOutput::CARFACOutput(const bool store_nap, const bool
store_nap_decim,
+ const bool store_bm, const bool store_ohc,
+ const bool store_agc) {
store_nap_ = store_nap;
store_nap_decim_ = store_nap_decim;
store_bm_ = store_bm;
@@ -36,27 +35,27 @@

}

-void CARFACOutput::StoreOutput(const vector<Ear>& ears) {
+void CARFACOutput::AppendOutput(const vector<Ear>& ears) {
if (store_nap_) {
- nap_.push_back(vector<FloatArray>());
+ nap_.push_back(vector<ArrayX>());
for (auto ear : ears) {
nap_.back().push_back(ear.ihc_out());
}
}
if (store_ohc_) {
- ohc_.push_back(vector<FloatArray>());
+ ohc_.push_back(vector<ArrayX>());
for (auto ear : ears) {
ohc_.back().push_back(ear.za_memory());
}
}
if (store_agc_) {
- agc_.push_back(vector<FloatArray>());
+ agc_.push_back(vector<ArrayX>());
for (auto ear : ears) {
agc_.back().push_back(ear.zb_memory());
}
}
if (store_bm_) {
- bm_.push_back(vector<FloatArray>());
+ bm_.push_back(vector<ArrayX>());
for (auto ear : ears) {
bm_.back().push_back(ear.zy_memory());
}
=======================================
--- /trunk/carfac/carfac_output.h Wed May 29 08:37:28 2013
+++ /trunk/carfac/carfac_output.h Tue Jun 4 11:30:22 2013
@@ -19,53 +19,53 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
-//
*****************************************************************************
-// Class: CARFACOutput
-//
*****************************************************************************
-// The CARFACOutput object stores an array of EarOuput objects. It is
meant as a
-// container for the output generated by the CARFAC object's 'Run' and
-// 'RunSegment' methods. Depending on the number of audio channels in the
input
-// data, the CARFACOutput will have 1 or more EarOutput obects, each of
which
-// contains a set of two dimensional float arrays (FloatArray2d)
representing
-// the neural activation patterns (NAPs) generated by the CARFAC model.
-//
-// The 'InitOutput' method is used to initialize the arrays in each of the
-// EarOutput sub-objects once the target data dimensions ears (n_ears),
channels
-// (n_ch) and timepoints (n_tp) are known.

#ifndef CARFAC_CARFAC_OUTPUT_H
#define CARFAC_CARFAC_OUTPUT_H

#include <deque>
#include <vector>
-#include "carfac_common.h"
+
+#include "common.h"
#include "ear.h"

+// A CARFACOutput object can store up to 5 different types of output from a
+// CARFAC model, and is provided as an argument to the CARFAC::RunSegment
+// method.
class CARFACOutput {
public:
- void Init(const int n_ears, const bool store_nap, const bool
store_nap_decim,
- const bool store_bm, const bool store_ohc, const bool
store_agc);
- void StoreOutput(const std::vector<Ear>& ears);
- // Here we define several acessors for the data members.
- const std::deque<std::vector<FloatArray>>& nap() { return nap_; }
- const std::deque<std::vector<FloatArray>>& bm() { return bm_; }
- const std::deque<std::vector<FloatArray>>& nap_decim() { return
nap_decim_; }
- const std::deque<std::vector<FloatArray>>& ohc() { return ohc_; }
- const std::deque<std::vector<FloatArray>>& agc() { return agc_; }
+ // The constructor takes five boolean values as arguments which indicate
+ // the portions of the CARFAC model's output to be stored.
+ CARFACOutput(const bool store_nap, const bool store_nap_decim,
+ const bool store_bm, const bool store_ohc, const bool
store_agc);
+
+ // The AppendOutput method is called on a sample by sample basis by the
+ // CARFAC::RunSegemtn method, appending a single frame of n_ears x
n_channels
+ // data to the end of the individual data members selected for storage.
+ void AppendOutput(const std::vector<Ear>& ears);
+ const std::deque<std::vector<ArrayX>>& nap() const { return nap_; }
+ const std::deque<std::vector<ArrayX>>& bm() const { return bm_; }
+ const std::deque<std::vector<ArrayX>>& nap_decim() const {
+ return nap_decim_; }
+ const std::deque<std::vector<ArrayX>>& ohc() const { return ohc_; }
+ const std::deque<std::vector<ArrayX>>& agc() const { return agc_; }

private:
- int n_ears_;
+ // TODO (alexbrandmeyer): figure out why this breaks object
initialization.
+ //DISALLOW_COPY_AND_ASSIGN(CARFACOutput);
bool store_nap_;
bool store_nap_decim_;
bool store_bm_;
bool store_ohc_;
bool store_agc_;
- std::deque<std::vector<FloatArray>> nap_;
- std::deque<std::vector<FloatArray>> nap_decim_;
- std::deque<std::vector<FloatArray>> bm_;
- std::deque<std::vector<FloatArray>> ohc_;
- std::deque<std::vector<FloatArray>> agc_;
+
+ // CARFAC outputs are stored in nested containers with dimensions:
+ // n_frames x n_ears x n_channels.
+ std::deque<std::vector<ArrayX>> nap_;
+ std::deque<std::vector<ArrayX>> nap_decim_;
+ std::deque<std::vector<ArrayX>> bm_;
+ std::deque<std::vector<ArrayX>> ohc_;
+ std::deque<std::vector<ArrayX>> agc_;
};

#endif // CARFAC_CARFAC_OUTPUT_H
=======================================
--- /trunk/carfac/carfac_test.cc Fri May 31 14:46:48 2013
+++ /trunk/carfac/carfac_test.cc Tue Jun 4 11:30:22 2013
@@ -25,10 +25,12 @@
#include <vector>

#include "gtest/gtest.h"
-#include "car_params.h"
-#include "ihc_params.h"
-#include "agc_params.h"
+
+#include "car.h"
+#include "ihc.h"
+#include "agc.h"
#include "carfac.h"
+#include "common.h"

using std::vector;
using std::string;
@@ -39,19 +41,19 @@
// locate the text files produced by 'CARFAC_GenerateTestData.m' for
comparing
// the ouput of the Matlab version of CARFAC with this C++ version.
static const char* kTestSourceDir= "./test_data/";
-// Here we specify the level to which the output should match (7 decimals).
-static const float kPrecisionLevel = 1.0e-7;
+// Here we specify the level to which the output should match (2 decimals).
+static const float kPrecisionLevel = 1.0e-2;

// Three helper functions are defined here for loading the test data
generated
// by the Matlab version of CARFAC.
-// This loads one-dimensional FloatArrays from single-column text files.
-void WriteNAPOutput(CARFACOutput output, const string filename, int ear) {
+// This loads one-dimensional ArrayXs from single-column text files.
+void WriteNAPOutput(CARFACOutput& output, const string filename, int ear) {
string fullfile = kTestSourceDir + filename;
ofstream ofile(fullfile.c_str());
- int32_t n_timepoints = output.nap().size();
+ int32_t num_timepoints = output.nap().size();
int channels = output.nap()[0][0].size();
if (ofile.is_open()) {
- for (int32_t i = 0; i < n_timepoints; ++i) {
+ for (int32_t i = 0; i < num_timepoints; ++i) {
for (int j = 0; j < channels; ++j) {
ofile << output.nap()[i][ear](j);
if ( j < channels - 1) {
@@ -64,11 +66,11 @@
ofile.close();
}

-FloatArray LoadTestData(const string filename, const int number_points) {
+ArrayX LoadTestData(const string filename, const int number_points) {
string fullfile = kTestSourceDir + filename;
ifstream file(fullfile.c_str());
FPType myarray[number_points];
- FloatArray output(number_points);
+ ArrayX output(number_points);
if (file.is_open()) {
for (int i = 0; i < number_points; ++i) {
file >> myarray[i];
@@ -79,13 +81,13 @@
return output;
}

-// This loads a vector of FloatArrays from multi-column text files.
-vector<FloatArray> Load2dTestData(const string filename, const int rows,
+// This loads a vector of ArrayXs from multi-column text files.
+vector<ArrayX> Load2dTestData(const string filename, const int rows,
const int columns) {
string fullfile = kTestSourceDir + filename;
ifstream file(fullfile.c_str());
FPType myarray[rows][columns];
- vector<FloatArray> output;
+ vector<ArrayX> output;
output.resize(rows);
for (auto& timepoint : output) {
timepoint.resize(columns);
@@ -125,28 +127,25 @@
}

TEST(CARFACTest, Binaural_Output_test) {
- int n_timepoints = 882;
- int n_channels = 71;
- int n_ears = 2;
+ int num_timepoints = 882;
+ int num_channels = 71;
+ int num_ears = 2;
string filename = "binaural_test_nap1.txt";
- vector<FloatArray> nap1 = Load2dTestData(filename, n_timepoints,
n_channels);
+ vector<ArrayX> nap1 = Load2dTestData(filename, num_timepoints,
num_channels);
filename = "binaural_test_bm1.txt";
- vector<FloatArray> bm1 = Load2dTestData(filename, n_timepoints,
n_channels);
+ vector<ArrayX> bm1 = Load2dTestData(filename, num_timepoints,
num_channels);
filename = "binaural_test_nap2.txt";
- vector<FloatArray> nap2 = Load2dTestData(filename, n_timepoints,
n_channels);
+ vector<ArrayX> nap2 = Load2dTestData(filename, num_timepoints,
num_channels);
filename = "binaural_test_bm2.txt";
- vector<FloatArray> bm2 = Load2dTestData(filename, n_timepoints,
n_channels);
+ vector<ArrayX> bm2 = Load2dTestData(filename, num_timepoints,
num_channels);
filename = "file_signal_binaural_test.txt";
- vector<vector<float>> sound_data = Load2dAudioVector(filename,
n_timepoints,
- n_ears);
+ vector<vector<float>> sound_data = Load2dAudioVector(filename,
num_timepoints,
+ num_ears);
CARParams car_params;
IHCParams ihc_params;
AGCParams agc_params;
- CARFAC mycf;
- mycf.Design(n_ears, 22050, car_params, ihc_params,
- agc_params);
- CARFACOutput my_output;
- my_output.Init(n_ears, true, false, true, false, false);
+ CARFAC mycf(num_ears, 22050, car_params, ihc_params, agc_params);
+ CARFACOutput my_output(true, false, true, false, false);
const bool kOpenLoop = false;
const int length = sound_data[0].size();
mycf.RunSegment(sound_data, 0, length, kOpenLoop, &my_output);
@@ -156,7 +155,7 @@
WriteNAPOutput(my_output, filename, 1);
int ear = 0;
int n_ch = 71;
- for (int timepoint = 0; timepoint < n_timepoints; ++timepoint) {
+ for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
for (int channel = 0; channel < n_ch; ++channel) {
FPType cplusplus = my_output.nap()[timepoint][ear](channel);
FPType matlab = nap1[timepoint](channel);
@@ -167,7 +166,7 @@
}
}
ear = 1;
- for (int timepoint = 0; timepoint < n_timepoints; ++timepoint) {
+ for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
for (int channel = 0; channel < n_ch; ++channel) {
FPType cplusplus = my_output.nap()[timepoint][ear](channel);
FPType matlab = nap2[timepoint](channel);
@@ -180,28 +179,25 @@
}

TEST(CARFACTest, Long_Output_test) {
- int n_timepoints = 2000;
- int n_channels = 83;
- int n_ears = 2;
+ int num_timepoints = 2000;
+ int num_channels = 83;
+ int num_ears = 2;
string filename = "long_test_nap1.txt";
- vector<FloatArray> nap1 = Load2dTestData(filename, n_timepoints,
n_channels);
+ vector<ArrayX> nap1 = Load2dTestData(filename, num_timepoints,
num_channels);
filename = "long_test_bm1.txt";
- vector<FloatArray> bm1 = Load2dTestData(filename, n_timepoints,
n_channels);
+ vector<ArrayX> bm1 = Load2dTestData(filename, num_timepoints,
num_channels);
filename = "long_test_nap2.txt";
- vector<FloatArray> nap2 = Load2dTestData(filename, n_timepoints,
n_channels);
+ vector<ArrayX> nap2 = Load2dTestData(filename, num_timepoints,
num_channels);
filename = "long_test_bm2.txt";
- vector<FloatArray> bm2 = Load2dTestData(filename, n_timepoints,
n_channels);
+ vector<ArrayX> bm2 = Load2dTestData(filename, num_timepoints,
num_channels);
filename = "file_signal_long_test.txt";
- vector<vector<float>> sound_data = Load2dAudioVector(filename,
n_timepoints,
- n_ears);
+ vector<vector<float>> sound_data = Load2dAudioVector(filename,
num_timepoints,
+ num_ears);
CARParams car_params;
IHCParams ihc_params;
AGCParams agc_params;
- CARFAC mycf;
- mycf.Design(n_ears, 44100, car_params, ihc_params,
- agc_params);
- CARFACOutput my_output;
- my_output.Init(n_ears, true, false, true, false, false);
+ CARFAC mycf(num_ears, 44100, car_params, ihc_params, agc_params);
+ CARFACOutput my_output(true, false, true, false, false);
const bool kOpenLoop = false;
const int length = sound_data[0].size();
mycf.RunSegment(sound_data, 0, length, kOpenLoop, &my_output);
@@ -210,8 +206,8 @@
filename = "cpp_nap_output_2_long_test.txt";
WriteNAPOutput(my_output, filename, 1);
int ear = 0;
- for (int timepoint = 0; timepoint < n_timepoints; ++timepoint) {
- for (int channel = 0; channel < n_channels; ++channel) {
+ for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
+ for (int channel = 0; channel < num_channels; ++channel) {
FPType cplusplus = my_output.nap()[timepoint][ear](channel);
FPType matlab = nap1[timepoint](channel);
ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
@@ -221,8 +217,8 @@
}
}
ear = 1;
- for (int timepoint = 0; timepoint < n_timepoints; ++timepoint) {
- for (int channel = 0; channel < n_channels; ++channel) {
+ for (int timepoint = 0; timepoint < num_timepoints; ++timepoint) {
+ for (int channel = 0; channel < num_channels; ++channel) {
FPType cplusplus = my_output.nap()[timepoint][ear](channel);
FPType matlab = nap2[timepoint](channel);
ASSERT_NEAR(cplusplus, matlab, kPrecisionLevel);
=======================================
--- /trunk/carfac/ear.cc Wed May 29 08:37:28 2013
+++ /trunk/carfac/ear.cc Tue Jun 4 11:30:22 2013
@@ -23,48 +23,40 @@
#include <assert.h>
#include "ear.h"

-// The 'InitEar' function takes a set of model parameters and initializes
the
-// design coefficients and model state variables needed for running the
model
-// on a single audio channel.
-void Ear::InitEar(const int n_ch, const FPType fs, const CARCoeffs&
car_coeffs,
- const IHCCoeffs& ihc_coeffs,
- const std::vector<AGCCoeffs>& agc_coeffs) {
- // The first section of code determines the number of channels that will
be
- // used in the model on the basis of the sample rate and the CAR
parameters
- // that have been passed to this function.
- n_ch_ = n_ch;
+void Ear::Init(const int num_channels, const CARCoeffs& car_coeffs,
+ const IHCCoeffs& ihc_coeffs,
+ const std::vector<AGCCoeffs>& agc_coeffs) {
+ num_channels_ = num_channels;
car_coeffs_ = car_coeffs;
ihc_coeffs_ = ihc_coeffs;
agc_coeffs_ = agc_coeffs;
- // Once the coefficients have been determined, we can initialize the
state
- // variables that will be used during runtime.
InitCARState();
InitIHCState();
InitAGCState();
}

void Ear::InitCARState() {
- car_state_.z1_memory.setZero(n_ch_);
- car_state_.z2_memory.setZero(n_ch_);
- car_state_.za_memory.setZero(n_ch_);
+ car_state_.z1_memory.setZero(num_channels_);
+ car_state_.z2_memory.setZero(num_channels_);
+ car_state_.za_memory.setZero(num_channels_);
car_state_.zb_memory = car_coeffs_.zr_coeffs;
- car_state_.dzb_memory.setZero(n_ch_);
- car_state_.zy_memory.setZero(n_ch_);
+ car_state_.dzb_memory.setZero(num_channels_);
+ car_state_.zy_memory.setZero(num_channels_);
car_state_.g_memory = car_coeffs_.g0_coeffs;
- car_state_.dg_memory.setZero(n_ch_);
+ car_state_.dg_memory.setZero(num_channels_);
}

void Ear::InitIHCState() {
- ihc_state_.ihc_accum = FloatArray::Zero(n_ch_);
+ ihc_state_.ihc_accum = ArrayX::Zero(num_channels_);
if (! ihc_coeffs_.just_half_wave_rectify) {
- ihc_state_.ac_coupler.setZero(n_ch_);
- ihc_state_.lpf1_state.setConstant(n_ch_, ihc_coeffs_.rest_output);
- ihc_state_.lpf2_state.setConstant(n_ch_, ihc_coeffs_.rest_output);
+ ihc_state_.ac_coupler.setZero(num_channels_);
+ ihc_state_.lpf1_state.setConstant(num_channels_,
ihc_coeffs_.rest_output);
+ ihc_state_.lpf2_state.setConstant(num_channels_,
ihc_coeffs_.rest_output);
if (ihc_coeffs_.one_capacitor) {
- ihc_state_.cap1_voltage.setConstant(n_ch_, ihc_coeffs_.rest_cap1);
+ ihc_state_.cap1_voltage.setConstant(num_channels_,
ihc_coeffs_.rest_cap1);
} else {
- ihc_state_.cap1_voltage.setConstant(n_ch_, ihc_coeffs_.rest_cap1);
- ihc_state_.cap2_voltage.setConstant(n_ch_, ihc_coeffs_.rest_cap2);
+ ihc_state_.cap1_voltage.setConstant(num_channels_,
ihc_coeffs_.rest_cap1);
+ ihc_state_.cap2_voltage.setConstant(num_channels_,
ihc_coeffs_.rest_cap2);
}
}
}
@@ -74,8 +66,8 @@
agc_state_.resize(n_agc_stages);
for (auto& stage_state : agc_state_) {
stage_state.decim_phase = 0;
- stage_state.agc_memory.setZero(n_ch_);
- stage_state.input_accum.setZero(n_ch_);
+ stage_state.agc_memory.setZero(num_channels_);
+ stage_state.input_accum.setZero(num_channels_);
}
}

@@ -86,16 +78,15 @@
car_state_.zb_memory = car_state_.zb_memory + car_state_.dzb_memory;
// This updates the nonlinear function of 'velocity' along with zA,
which is
// a delay of z2.
- FloatArray nonlinear_fun(n_ch_);
- FloatArray velocities = car_state_.z2_memory - car_state_.za_memory;
+ ArrayX nonlinear_fun(num_channels_);
+ ArrayX velocities = car_state_.z2_memory - car_state_.za_memory;
OHCNonlinearFunction(velocities, &nonlinear_fun);
// Here, zb_memory_ * nonlinear_fun is "undamping" delta r.
- FloatArray r = car_coeffs_.r1_coeffs + (car_state_.zb_memory *
- nonlinear_fun);
+ ArrayX r = car_coeffs_.r1_coeffs + (car_state_.zb_memory *
nonlinear_fun);
car_state_.za_memory = car_state_.z2_memory;
// Here we reduce the CAR state by r and rotate with the fixed cos/sin
coeffs.
- FloatArray z1 = r * ((car_coeffs_.a0_coeffs * car_state_.z1_memory) -
- (car_coeffs_.c0_coeffs * car_state_.z2_memory));
+ ArrayX z1 = r * ((car_coeffs_.a0_coeffs * car_state_.z1_memory) -
+ (car_coeffs_.c0_coeffs * car_state_.z2_memory));
car_state_.z2_memory = r *
((car_coeffs_.c0_coeffs * car_state_.z1_memory) +
(car_coeffs_.a0_coeffs * car_state_.z2_memory));
@@ -103,11 +94,12 @@
// This section ripples the input-output path, to avoid delay...
// It's the only part that doesn't get computed "in parallel":
FPType in_out = input;
- for (int ch = 0; ch < n_ch_; ch++) {
- z1(ch) = z1(ch) + in_out;
+ for (int channel = 0; channel < num_channels_; channel++) {
+ z1(channel) = z1(channel) + in_out;
// This performs the ripple, and saves the final channel outputs in zy.
- in_out = car_state_.g_memory(ch) * (in_out + car_state_.zy_memory(ch));
- car_state_.zy_memory(ch) = in_out;
+ in_out = car_state_.g_memory(channel) *
+ (in_out + car_state_.zy_memory(channel));
+ car_state_.zy_memory(channel) = in_out;
}
car_state_.z1_memory = z1;
}
@@ -115,8 +107,8 @@
// We start with a quadratic nonlinear function, and limit it via a
// rational function. This makes the result go to zero at high
// absolute velocities, so it will do nothing there.
-void Ear::OHCNonlinearFunction(const FloatArray& velocities,
- FloatArray* nonlinear_fun) {
+void Ear::OHCNonlinearFunction(const ArrayX& velocities,
+ ArrayX* nonlinear_fun) {
*nonlinear_fun = (1 + ((velocities * car_coeffs_.velocity_scale) +
car_coeffs_.v_offset).square()).inverse();
}
@@ -124,19 +116,19 @@
// This step is a one sample-time update of the inner-hair-cell (IHC)
model,
// including the detection nonlinearity and either one or two capacitor
state
// variables.
-void Ear::IHCStep(const FloatArray& car_out) {
- FloatArray ac_diff = car_out - ihc_state_.ac_coupler;
+void Ear::IHCStep(const ArrayX& car_out) {
+ ArrayX ac_diff = car_out - ihc_state_.ac_coupler;
ihc_state_.ac_coupler = ihc_state_.ac_coupler +
(ihc_coeffs_.ac_coeff * ac_diff);
if (ihc_coeffs_.just_half_wave_rectify) {
- FloatArray output(n_ch_);
- for (int ch = 0; ch < n_ch_; ++ch) {
- FPType a = (ac_diff(ch) > 0.0) ? ac_diff(ch) : 0.0;
- output(ch) = (a < 2) ? a : 2;
+ ArrayX output(num_channels_);
+ for (int channel = 0; channel < num_channels_; ++channel) {
+ FPType a = (ac_diff(channel) > 0.0) ? ac_diff(channel) : 0.0;
+ output(channel) = (a < 2) ? a : 2;
}
ihc_state_.ihc_out = output;
} else {
- FloatArray conductance = CARFACDetect(ac_diff);
+ ArrayX conductance = CARFACDetect(ac_diff);
if (ihc_coeffs_.one_capacitor) {
ihc_state_.ihc_out = conductance * ihc_state_.cap1_voltage;
ihc_state_.cap1_voltage = ihc_state_.cap1_voltage -
@@ -164,15 +156,15 @@
ihc_state_.ihc_accum += ihc_state_.ihc_out;
}

-bool Ear::AGCStep(const FloatArray& ihc_out) {
+bool Ear::AGCStep(const ArrayX& ihc_out) {
int stage = 0;
- int n_stages = agc_coeffs_[0].n_agc_stages;
- FPType detect_scale = agc_coeffs_[n_stages - 1].detect_scale;
+ int num_stages = agc_coeffs_[0].num_agc_stages;
+ FPType detect_scale = agc_coeffs_[num_stages - 1].detect_scale;
bool updated = AGCRecurse(stage, detect_scale * ihc_out);
return updated;
}

-bool Ear::AGCRecurse(const int stage, FloatArray agc_in) {
+bool Ear::AGCRecurse(const int stage, ArrayX agc_in) {
bool updated = true;
const auto& agc_coeffs = agc_coeffs_[stage];
auto& agc_state = agc_state_[stage];
@@ -191,7 +183,7 @@
// decimated at the next stage.
agc_in = agc_state.input_accum / decim;
// This resets the accumulator.
- agc_state.input_accum = FloatArray::Zero(n_ch_);
+ agc_state.input_accum = ArrayX::Zero(num_channels_);
if (stage < (agc_coeffs_.size() - 1)) {
// Now we recurse to evaluate the next stage(s).
updated = AGCRecurse(stage + 1, agc_in);
@@ -212,25 +204,27 @@
}

void Ear::AGCSpatialSmooth(const AGCCoeffs& agc_coeffs,
- FloatArray* stage_state) {
- int n_iterations = agc_coeffs.agc_spatial_iterations;
+ ArrayX* stage_state) {
+ int num_iterations = agc_coeffs.agc_spatial_iterations;
bool use_fir;
- use_fir = (n_iterations < 4) ? true : false;
+ use_fir = (num_iterations < 4) ? true : false;
if (use_fir) {
FPType fir_coeffs_left = agc_coeffs.agc_spatial_fir_left;
FPType fir_coeffs_mid = agc_coeffs.agc_spatial_fir_mid;
FPType fir_coeffs_right = agc_coeffs.agc_spatial_fir_right;
- FloatArray ss_tap1(n_ch_);
- FloatArray ss_tap2(n_ch_);
- FloatArray ss_tap3(n_ch_);
- FloatArray ss_tap4(n_ch_);
+ ArrayX ss_tap1(num_channels_);
+ ArrayX ss_tap2(num_channels_);
+ ArrayX ss_tap3(num_channels_);
+ ArrayX ss_tap4(num_channels_);
int n_taps = agc_coeffs.agc_spatial_n_taps;
// This initializes the first two taps of stage state, which are used
for
// both possible cases.
ss_tap1(0) = (*stage_state)(0);
- ss_tap1.block(1, 0, n_ch_ - 1, 1) = stage_state->block(0, 0, n_ch_ -
1, 1);
- ss_tap2(n_ch_ - 1) = (*stage_state)(n_ch_ - 1);
- ss_tap2.block(0, 0, n_ch_ - 1, 1) = stage_state->block(1, 0, n_ch_ -
1, 1);
+ ss_tap1.block(1, 0, num_channels_ - 1, 1) =
+ stage_state->block(0, 0, num_channels_ - 1, 1);
+ ss_tap2(num_channels_ - 1) = (*stage_state)(num_channels_ - 1);
+ ss_tap2.block(0, 0, num_channels_ - 1, 1) =
+ stage_state->block(1, 0, num_channels_ - 1, 1);
switch (n_taps) {
case 3:
*stage_state = (fir_coeffs_left * ss_tap1) +
@@ -241,12 +235,12 @@
// for the 5-tap case.
ss_tap3(0) = (*stage_state)(0);
ss_tap3(1) = (*stage_state)(1);
- ss_tap3.block(2, 0, n_ch_ - 2, 1) =
- stage_state->block(0, 0, n_ch_ - 2, 1);
- ss_tap4(n_ch_ - 2) = (*stage_state)(n_ch_ - 1);
- ss_tap4(n_ch_ - 1) = (*stage_state)(n_ch_ - 2);
- ss_tap4.block(0, 0, n_ch_ - 2, 1) =
- stage_state->block(2, 0, n_ch_ - 2, 1);
+ ss_tap3.block(2, 0, num_channels_ - 2, 1) =
+ stage_state->block(0, 0, num_channels_ - 2, 1);
+ ss_tap4(num_channels_ - 2) = (*stage_state)(num_channels_ - 1);
+ ss_tap4(num_channels_ - 1) = (*stage_state)(num_channels_ - 2);
+ ss_tap4.block(0, 0, num_channels_ - 2, 1) =
+ stage_state->block(2, 0, num_channels_ - 2, 1);
*stage_state = (fir_coeffs_left * (ss_tap3 + ss_tap1)) +
(fir_coeffs_mid * *stage_state) +
(fir_coeffs_right * (ss_tap2 + ss_tap4));
@@ -261,30 +255,31 @@
}
}

-void Ear::AGCSmoothDoubleExponential(const FPType pole_z1, const FPType
pole_z2,
- FloatArray* stage_state) {
- int32_t n_pts = stage_state->size();
+void Ear::AGCSmoothDoubleExponential(const FPType pole_z1,
+ const FPType pole_z2,
+ ArrayX* stage_state) {
+ int32_t num_points = stage_state->size();
FPType input;
FPType state = 0.0;
// TODO (alexbrandmeyer): I'm assuming one dimensional input for now,
but this
// should be verified with Dick for the final version
- for (int i = n_pts - 11; i < n_pts; ++i) {
+ for (int i = num_points - 11; i < num_points; ++i) {
input = (*stage_state)(i);
state = state + (1 - pole_z1) * (input - state);
}
- for (int i = n_pts - 1; i > -1; --i) {
+ for (int i = num_points - 1; i > -1; --i) {
input = (*stage_state)(i);
state = state + (1 - pole_z2) * (input - state);
}
- for (int i = 0; i < n_pts; ++i) {
+ for (int i = 0; i < num_points; ++i) {
input = (*stage_state)(i);
state = state + (1 - pole_z1) * (input - state);
(*stage_state)(i) = state;
}
}

-FloatArray Ear::StageGValue(const FloatArray& undamping) {
- FloatArray r = car_coeffs_.r1_coeffs + car_coeffs_.zr_coeffs * undamping;
+ArrayX Ear::StageGValue(const ArrayX& undamping) {
+ ArrayX r = car_coeffs_.r1_coeffs + car_coeffs_.zr_coeffs * undamping;
return (1 - 2 * r * car_coeffs_.a0_coeffs + (r * r)) /
(1 - 2 * r * car_coeffs_.a0_coeffs + car_coeffs_.h_coeffs * r *
car_coeffs_.c0_coeffs + (r * r));
=======================================
--- /trunk/carfac/ear.h Wed May 29 08:37:28 2013
+++ /trunk/carfac/ear.h Tue Jun 4 11:30:22 2013
@@ -24,84 +24,97 @@
#define CARFAC_EAR_H

#include <vector>
-#include "carfac_common.h"
-#include "car_coeffs.h"
-#include "ihc_coeffs.h"
-#include "agc_coeffs.h"
-#include "car_state.h"
-#include "ihc_state.h"
-#include "agc_state.h"

+#include "common.h"
+#include "carfac_util.h"
+#include "car.h"
+#include "agc.h"
+#include "ihc.h"
+
+// The Ear object carries out the three steps of the CARFAC model on a
single
+// channel of audio data, and stores information about the CAR, IHC and AGC
+// coefficients and states.
class Ear {
public:
+
// This is the primary initialization function that is called for each
- // Ear object in the CARFAC 'Design' method.
- void InitEar(const int n_ch, const FPType fs,
- const CARCoeffs& car_coeffs, const IHCCoeffs& ihc_coeffs,
- const std::vector<AGCCoeffs>& agc_coeffs);
- // These three methods apply the different stages of the model in
sequence
- // to individual audio samples.
+ // Ear object by the CARFAC::Design method.
+ void Init(const int num_channels, const CARCoeffs& car_coeffs,
+ const IHCCoeffs& ihc_coeffs,
+ const std::vector<AGCCoeffs>& agc_coeffs);
+
+ // These three methods apply the different steps of the model in sequence
+ // to individual audio samples during the call to CARFAC::RunSegment.
void CARStep(const FPType input);
- void IHCStep(const FloatArray& car_out);
- bool AGCStep(const FloatArray& ihc_out);
+ void IHCStep(const ArrayX& car_out);
+ bool AGCStep(const ArrayX& ihc_out);
+
// These accessor functions return portions of the CAR state for storage
in
// the CAROutput structures.
- const FloatArray& za_memory() { return car_state_.za_memory; }
- const FloatArray& zb_memory() { return car_state_.zb_memory; }
+ const ArrayX& za_memory() const { return car_state_.za_memory; }
+ const ArrayX& zb_memory() const { return car_state_.zb_memory; }
+
// The zy_memory_ of the CARState is equivalent to the CAR output. A
second
// accessor function is included for documentation purposes.
- const FloatArray& zy_memory() { return car_state_.zy_memory; }
- const FloatArray& car_out() { return car_state_.zy_memory; }
- const FloatArray& g_memory() { return car_state_.g_memory; }
- // This returns the IHC output for storage.
- const FloatArray& ihc_out() { return ihc_state_.ihc_out; }
- const FloatArray& dzb_memory() { return car_state_.dzb_memory; }
- // These accessor functions return CAR coefficients.
- const FloatArray& zr_coeffs() { return car_coeffs_.zr_coeffs; }
+ const ArrayX& zy_memory() const { return car_state_.zy_memory; }
+ const ArrayX& car_out() const { return car_state_.zy_memory; }
+ const ArrayX& g_memory() const { return car_state_.g_memory; }
+ const ArrayX& ihc_out() const { return ihc_state_.ihc_out; }
+ const ArrayX& dzb_memory() const { return car_state_.dzb_memory; }
+ const ArrayX& zr_coeffs() const { return car_coeffs_.zr_coeffs; }
+
// These accessor functions return portions of the AGC state during the
cross
// coupling of the ears.
- const int agc_nstages() { return agc_coeffs_.size(); }
- const int agc_decim_phase(const int stage) {
+ const int agc_num_stages() const { return agc_coeffs_.size(); }
+ const int agc_decim_phase(const int stage) const {
return agc_state_[stage].decim_phase; }
- const FPType agc_mix_coeff(const int stage) {
+ const FPType agc_mix_coeff(const int stage) const {
return agc_coeffs_[stage].agc_mix_coeffs; }
- const FloatArray& agc_memory(const int stage) {
+ const ArrayX& agc_memory(const int stage) const {
return agc_state_[stage].agc_memory; }
- const int agc_decimation(const int stage) {
+ const int agc_decimation(const int stage) const {
return agc_coeffs_[stage].decimation; }
+
// This returns the stage G value during the closing of the AGC loop.
- FloatArray StageGValue(const FloatArray& undamping);
+ ArrayX StageGValue(const ArrayX& undamping);
+
// This function sets the AGC memory during the cross coupling stage.
- void set_agc_memory(const int stage, const FloatArray& new_values) {
+ void set_agc_memory(const int stage, const ArrayX& new_values) {
agc_state_[stage].agc_memory = new_values; }
+
// These are the setter functions for the CAR memory states.
- void set_dzb_memory(const FloatArray& new_values) {
+ void set_dzb_memory(const ArrayX& new_values) {
car_state_.dzb_memory = new_values; }
- void set_dg_memory(const FloatArray& new_values) {
+ void set_dg_memory(const ArrayX& new_values) {
car_state_.dg_memory = new_values; }

private:
- // These are the corresponding methods that initialize the model state
- // variables before runtime using the model coefficients.
+ // TODO (alexbrandmeyer): figure out why this breaks object
initialization.
+ //DISALLOW_COPY_AND_ASSIGN(Ear);
+
+ // These methodsinitialize the model state variables prior to runtime.
void InitIHCState();
void InitAGCState();
void InitCARState();
- // These are the various helper functions called during the model
runtime.
- void OHCNonlinearFunction(const FloatArray& velocities,
- FloatArray* nonlinear_fun);
- bool AGCRecurse(const int stage, FloatArray agc_in);
- void AGCSpatialSmooth(const AGCCoeffs& agc_coeffs , FloatArray*
stage_state);
+
+ // These are the helper sub-functions called during the model runtime.
+ void OHCNonlinearFunction(const ArrayX& velocities,
+ ArrayX* nonlinear_fun);
+ bool AGCRecurse(const int stage, ArrayX agc_in);
+ void AGCSpatialSmooth(const AGCCoeffs& agc_coeffs , ArrayX* stage_state);
void AGCSmoothDoubleExponential(const FPType pole_z1, const FPType
pole_z2,
- FloatArray* stage_state);
- // These are the private data members that store the state and
coefficient
- // information.
+ ArrayX* stage_state);
+
CARCoeffs car_coeffs_;
- IHCCoeffs ihc_coeffs_;
- std::vector<AGCCoeffs> agc_coeffs_;
CARState car_state_;
+ IHCCoeffs ihc_coeffs_;
IHCState ihc_state_;
+
+ // The AGC coefficient and state variables are both stored in vectors
+ // containing one element for each stage (default = 4).
+ std::vector<AGCCoeffs> agc_coeffs_;
std::vector<AGCState> agc_state_;
- int n_ch_;
+ int num_channels_;
};

#endif // CARFAC_EAR_H
=======================================
--- /trunk/carfac/sai.cc Fri May 31 14:46:48 2013
+++ /trunk/carfac/sai.cc Tue Jun 4 11:30:22 2013
@@ -35,8 +35,8 @@
.sin();
}

-void SAI::RunSegment(const std::vector<FloatArray>& input,
- Float2dArray* output_frame) {
+void SAI::RunSegment(const std::vector<ArrayX>& input,
+ ArrayXX* output_frame) {
assert(!input.empty() || input.size() <= params_.window_width &&
"Unexpected input size.");
assert(input[0].size() == params_.n_ch &&
@@ -60,8 +60,8 @@
*output_frame = output_buffer_;
}

-void SAI::StabilizeSegment(const Float2dArray& input_buffer,
- Float2dArray* output_buffer) const {
+void SAI::StabilizeSegment(const ArrayXX& input_buffer,
+ ArrayXX* output_buffer) const {
// Windows are always approximately 50% overlapped.
float window_hop = params_.window_width / 2;
int window_start = (input_buffer.cols() - params_.window_width) -
@@ -72,14 +72,14 @@
for (int i = 0; i < params_.n_ch; ++i) {
// TODO(ronw): Rename this here and in the Matlab code since the
// input doesn't have to contain naps.
- const FloatArray& nap_wave = input_buffer.row(i);
+ const ArrayX& nap_wave = input_buffer.row(i);
// TODO(ronw): Smooth row.

for (int w = 0; w < params_.n_window_pos; ++w) {
int current_window_offset = w * window_hop;
// Choose a trigger point.
int trigger_time;
- const FloatArray& trigger_window =
+ const ArrayX& trigger_window =
nap_wave.segment(window_range_start + current_window_offset,
params_.window_width);
FPType peak_val = (trigger_window * window_).maxCoeff(&trigger_time);
=======================================
--- /trunk/carfac/sai.h Fri May 31 14:46:48 2013
+++ /trunk/carfac/sai.h Tue Jun 4 11:30:22 2013
@@ -22,8 +22,7 @@

#include <vector>

-// TODO(ronw): Rename this file to common.h
-#include "carfac_common.h"
+#include "common.h"

// Design parameters for a single SAI.
struct SAIParams {
@@ -57,25 +56,25 @@
//
// The input should have dimensionality of params_.window_width by
// params_.n_ch. Inputs containing too few frames are zero-padded.
- // FIXME: Float2DArray input type would be less awkward.
- void RunSegment(const std::vector<FloatArray>& input,
- Float2dArray* output_output_frame);
+ // FIXME: ArrayXX input type would be less awkward.
+ void RunSegment(const std::vector<ArrayX>& input,
+ ArrayXX* output_output_frame);

private:
// Process successive windows within input_buffer, choose trigger
// points, and blend each window into output_buffer.
- void StabilizeSegment(const Float2dArray& input_buffer,
- Float2dArray* output_buffer) const;
+ void StabilizeSegment(const ArrayXX& input_buffer,
+ ArrayXX* output_buffer) const;

SAIParams params_;
// Window function to apply before selecting a trigger point.
// Size: params_.window_width.
- FloatArray window_;
+ ArrayX window_;
// Buffer to store a large enough window of input frames to compute
// a full SAI frame. Size: params_.n_ch by params_.buffer_width.
- Float2dArray input_buffer_;
+ ArrayXX input_buffer_;
// Output frame buffer. Size: params_.n_ch by params_.width.
- Float2dArray output_buffer_;
+ ArrayXX output_buffer_;
};

#endif // CARFAC_SAI_H_
=======================================
--- /trunk/carfac/sai_test.cc Fri May 31 14:46:48 2013
+++ /trunk/carfac/sai_test.cc Tue Jun 4 11:30:22 2013
@@ -27,15 +27,15 @@
using testing::Values;
using std::vector;

-vector<FloatArray> CreateZeroSegment(int n_ch, int length) {
- vector<FloatArray> segment;
+vector<ArrayX> CreateZeroSegment(int n_ch, int length) {
+ vector<ArrayX> segment;
for (int i = 0; i < length; ++i) {
- segment.push_back(FloatArray::Zero(n_ch));
+ segment.push_back(ArrayX::Zero(n_ch));
}
return segment;
}

-bool HasPeakAt(const Float2dArray& frame, int index) {
+bool HasPeakAt(const ArrayXX& frame, int index) {
if (index == 0) {
return frame(index) > frame(index + 1);
} else if (index == frame.size() - 1) {
@@ -57,7 +57,7 @@
};

TEST_P(SAIPeriodicInputTest, SingleChannelPulseTrain) {
- vector<FloatArray> segment = CreateZeroSegment(1, 38);
+ vector<ArrayX> segment = CreateZeroSegment(1, 38);
for (int i = phase_; i < segment.size(); i += period_) {
segment[i](0) = 1;
}
@@ -72,7 +72,7 @@
sai_params.n_window_pos = 2;

SAI sai(sai_params);
- Float2dArray sai_frame;
+ ArrayXX sai_frame;
sai.RunSegment(segment, &sai_frame);

// The output should have peaks at the same positions, regardless of
Reply all
Reply to author
Forward
0 new messages