dicklyon@473: % Copyright 2012, Google, Inc. dicklyon@473: % Author: Richard F. Lyon dicklyon@473: % dicklyon@473: % This Matlab file is part of an implementation of Lyon's cochlear model: dicklyon@473: % "Cascade of Asymmetric Resonators with Fast-Acting Compression" dicklyon@473: % to supplement Lyon's upcoming book "Human and Machine Hearing" dicklyon@473: % dicklyon@473: % Licensed under the Apache License, Version 2.0 (the "License"); dicklyon@473: % you may not use this file except in compliance with the License. dicklyon@473: % You may obtain a copy of the License at dicklyon@473: % dicklyon@473: % http://www.apache.org/licenses/LICENSE-2.0 dicklyon@473: % dicklyon@473: % Unless required by applicable law or agreed to in writing, software dicklyon@473: % distributed under the License is distributed on an "AS IS" BASIS, dicklyon@473: % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. dicklyon@473: % See the License for the specific language governing permissions and dicklyon@473: % limitations under the License. dicklyon@473: dicklyon@473: function [ihc_out, state] = CARFAC_IHC_Step(filters_out, coeffs, state); dicklyon@473: % function [ihc_out, state] = CARFAC_IHC_Step(filters_out, coeffs, state); dicklyon@473: % dicklyon@473: % One sample-time update of inner-hair-cell (IHC) model, including the dicklyon@473: % detection nonlinearity and one or two capacitor state variables. dicklyon@473: dicklyon@504: % AC couple the filters_out, with 20 Hz corner dicklyon@504: ac_diff = filters_out - state.ac_coupler; dicklyon@504: state.ac_coupler = state.ac_coupler + coeffs.ac_coeff * ac_diff; dicklyon@473: dicklyon@504: if coeffs.just_hwr dicklyon@504: ihc_out = min(2, max(0, ac_diff)); % limit it for stability dicklyon@473: else dicklyon@504: conductance = CARFAC_Detect(ac_diff); % rectifying nonlinearity dicklyon@504: dicklyon@495: if coeffs.one_cap; dicklyon@495: ihc_out = conductance .* state.cap_voltage; dicklyon@473: state.cap_voltage = state.cap_voltage - ihc_out .* coeffs.out_rate + ... dicklyon@473: (1 - state.cap_voltage) .* coeffs.in_rate; dicklyon@473: else dicklyon@473: % change to 2-cap version more like Meddis's: dicklyon@495: ihc_out = conductance .* state.cap2_voltage; dicklyon@473: state.cap1_voltage = state.cap1_voltage - ... dicklyon@473: (state.cap1_voltage - state.cap2_voltage) .* coeffs.out1_rate + ... dicklyon@473: (1 - state.cap1_voltage) .* coeffs.in1_rate; dicklyon@473: dicklyon@473: state.cap2_voltage = state.cap2_voltage - ihc_out .* coeffs.out2_rate + ... dicklyon@473: (state.cap1_voltage - state.cap2_voltage) .* coeffs.in2_rate; dicklyon@473: end dicklyon@473: dicklyon@473: % smooth it twice with LPF: dicklyon@473: dicklyon@499: ihc_out = ihc_out * coeffs.output_gain; dicklyon@473: state.lpf1_state = state.lpf1_state + coeffs.lpf_coeff * ... dicklyon@473: (ihc_out - state.lpf1_state); dicklyon@473: state.lpf2_state = state.lpf2_state + coeffs.lpf_coeff * ... dicklyon@473: (state.lpf1_state - state.lpf2_state); dicklyon@499: ihc_out = state.lpf2_state - coeffs.rest_output; dicklyon@473: end dicklyon@504: dicklyon@504: state.ihc_accum = state.ihc_accum + ihc_out; % for where decimated output is useful dicklyon@504: