dicklyon@534
|
1 % Copyright 2012, Google, Inc.
|
dicklyon@534
|
2 % Author: Richard F. Lyon
|
dicklyon@534
|
3 %
|
dicklyon@534
|
4 % This Matlab file is part of an implementation of Lyon's cochlear model:
|
dicklyon@534
|
5 % "Cascade of Asymmetric Resonators with Fast-Acting Compression"
|
dicklyon@534
|
6 % to supplement Lyon's upcoming book "Human and Machine Hearing"
|
dicklyon@534
|
7 %
|
dicklyon@534
|
8 % Licensed under the Apache License, Version 2.0 (the "License");
|
dicklyon@534
|
9 % you may not use this file except in compliance with the License.
|
dicklyon@534
|
10 % You may obtain a copy of the License at
|
dicklyon@534
|
11 %
|
dicklyon@534
|
12 % http://www.apache.org/licenses/LICENSE-2.0
|
dicklyon@534
|
13 %
|
dicklyon@534
|
14 % Unless required by applicable law or agreed to in writing, software
|
dicklyon@534
|
15 % distributed under the License is distributed on an "AS IS" BASIS,
|
dicklyon@534
|
16 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
dicklyon@534
|
17 % See the License for the specific language governing permissions and
|
dicklyon@534
|
18 % limitations under the License.
|
dicklyon@534
|
19
|
dicklyon@534
|
20 function [ihc_out, state] = CARFAC_IHC_Step(filters_out, coeffs, state);
|
dicklyon@534
|
21 % function [ihc_out, state] = CARFAC_IHC_Step(filters_out, coeffs, state);
|
dicklyon@534
|
22 %
|
dicklyon@534
|
23 % One sample-time update of inner-hair-cell (IHC) model, including the
|
dicklyon@534
|
24 % detection nonlinearity and one or two capacitor state variables.
|
dicklyon@534
|
25
|
dicklyon@565
|
26 % AC couple the filters_out, with 20 Hz corner
|
dicklyon@565
|
27 ac_diff = filters_out - state.ac_coupler;
|
dicklyon@565
|
28 state.ac_coupler = state.ac_coupler + coeffs.ac_coeff * ac_diff;
|
dicklyon@534
|
29
|
dicklyon@565
|
30 if coeffs.just_hwr
|
dicklyon@565
|
31 ihc_out = min(2, max(0, ac_diff)); % limit it for stability
|
dicklyon@534
|
32 else
|
dicklyon@565
|
33 conductance = CARFAC_Detect(ac_diff); % rectifying nonlinearity
|
dicklyon@565
|
34
|
dicklyon@556
|
35 if coeffs.one_cap;
|
dicklyon@556
|
36 ihc_out = conductance .* state.cap_voltage;
|
dicklyon@534
|
37 state.cap_voltage = state.cap_voltage - ihc_out .* coeffs.out_rate + ...
|
dicklyon@534
|
38 (1 - state.cap_voltage) .* coeffs.in_rate;
|
dicklyon@534
|
39 else
|
dicklyon@534
|
40 % change to 2-cap version more like Meddis's:
|
dicklyon@556
|
41 ihc_out = conductance .* state.cap2_voltage;
|
dicklyon@534
|
42 state.cap1_voltage = state.cap1_voltage - ...
|
dicklyon@534
|
43 (state.cap1_voltage - state.cap2_voltage) .* coeffs.out1_rate + ...
|
dicklyon@534
|
44 (1 - state.cap1_voltage) .* coeffs.in1_rate;
|
dicklyon@534
|
45
|
dicklyon@534
|
46 state.cap2_voltage = state.cap2_voltage - ihc_out .* coeffs.out2_rate + ...
|
dicklyon@534
|
47 (state.cap1_voltage - state.cap2_voltage) .* coeffs.in2_rate;
|
dicklyon@534
|
48 end
|
dicklyon@534
|
49
|
dicklyon@534
|
50 % smooth it twice with LPF:
|
dicklyon@534
|
51
|
dicklyon@560
|
52 ihc_out = ihc_out * coeffs.output_gain;
|
dicklyon@534
|
53 state.lpf1_state = state.lpf1_state + coeffs.lpf_coeff * ...
|
dicklyon@534
|
54 (ihc_out - state.lpf1_state);
|
dicklyon@534
|
55 state.lpf2_state = state.lpf2_state + coeffs.lpf_coeff * ...
|
dicklyon@534
|
56 (state.lpf1_state - state.lpf2_state);
|
dicklyon@560
|
57 ihc_out = state.lpf2_state - coeffs.rest_output;
|
dicklyon@534
|
58 end
|
dicklyon@565
|
59
|
dicklyon@565
|
60 state.ihc_accum = state.ihc_accum + ihc_out; % for where decimated output is useful
|
dicklyon@565
|
61
|