dicklyon@473
|
1 % Copyright 2012, Google, Inc.
|
dicklyon@473
|
2 % Author: Richard F. Lyon
|
dicklyon@473
|
3 %
|
dicklyon@473
|
4 % This Matlab file is part of an implementation of Lyon's cochlear model:
|
dicklyon@473
|
5 % "Cascade of Asymmetric Resonators with Fast-Acting Compression"
|
dicklyon@473
|
6 % to supplement Lyon's upcoming book "Human and Machine Hearing"
|
dicklyon@473
|
7 %
|
dicklyon@473
|
8 % Licensed under the Apache License, Version 2.0 (the "License");
|
dicklyon@473
|
9 % you may not use this file except in compliance with the License.
|
dicklyon@473
|
10 % You may obtain a copy of the License at
|
dicklyon@473
|
11 %
|
dicklyon@473
|
12 % http://www.apache.org/licenses/LICENSE-2.0
|
dicklyon@473
|
13 %
|
dicklyon@473
|
14 % Unless required by applicable law or agreed to in writing, software
|
dicklyon@473
|
15 % distributed under the License is distributed on an "AS IS" BASIS,
|
dicklyon@473
|
16 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
dicklyon@473
|
17 % See the License for the specific language governing permissions and
|
dicklyon@473
|
18 % limitations under the License.
|
dicklyon@473
|
19
|
dicklyon@504
|
20 function [state, updated] = CARFAC_AGC_Step(detects, coeffs, state)
|
dicklyon@504
|
21 % function [state, updated] = CARFAC_AGC_Step(detects, coeffs, state)
|
dicklyon@473
|
22 %
|
dicklyon@498
|
23 % one time step of the AGC state update; decimates internally
|
dicklyon@473
|
24
|
dicklyon@473
|
25 stage = 1;
|
dicklyon@498
|
26 AGC_in = coeffs.detect_scale * detects;
|
dicklyon@498
|
27 [state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, stage, state);
|
dicklyon@473
|
28
|
dicklyon@473
|
29
|
dicklyon@498
|
30 function [state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, ...
|
dicklyon@498
|
31 stage, state)
|
dicklyon@498
|
32 % function [state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, ...
|
dicklyon@498
|
33 % stage, state)
|
dicklyon@473
|
34
|
dicklyon@498
|
35 % decim factor for this stage, relative to input or prev. stage:
|
dicklyon@498
|
36 decim = coeffs.decimation(stage);
|
dicklyon@498
|
37 % decim phase of this stage (do work on phase 0 only):
|
dicklyon@473
|
38 decim_phase = mod(state(1).decim_phase(stage) + 1, decim);
|
dicklyon@498
|
39 state.decim_phase(stage) = decim_phase;
|
dicklyon@473
|
40
|
dicklyon@473
|
41 % accumulate input for this stage from detect or previous stage:
|
dicklyon@498
|
42 state.input_accum(:, stage) = state.input_accum(:, stage) + AGC_in;
|
dicklyon@473
|
43
|
dicklyon@473
|
44 % nothing else to do if it's not the right decim_phase
|
dicklyon@473
|
45 if decim_phase == 0
|
dicklyon@498
|
46 % do lots of work, at decimated rate.
|
dicklyon@498
|
47 % decimated inputs for this stage, and to be decimated more for next:
|
dicklyon@498
|
48 AGC_in = state.input_accum(:, stage) / decim;
|
dicklyon@498
|
49 state.input_accum(:, stage) = 0; % reset accumulator
|
dicklyon@473
|
50
|
dicklyon@498
|
51 if stage < length(coeffs.decimation) % recurse to evaluate next stage(s)
|
dicklyon@498
|
52 state = CARFAC_AGC_Recurse(coeffs, AGC_in, stage+1, state);
|
dicklyon@498
|
53 % and add its output to this stage input, whether it updated or not:
|
dicklyon@498
|
54 AGC_in = AGC_in + coeffs.AGC_stage_gain * state.AGC_memory(:, stage+1);
|
dicklyon@473
|
55 end
|
dicklyon@473
|
56
|
dicklyon@498
|
57 AGC_stage_state = state.AGC_memory(:, stage);
|
dicklyon@498
|
58 % first-order recursive smoothing filter update, in time:
|
dicklyon@498
|
59 AGC_stage_state = AGC_stage_state + ...
|
dicklyon@498
|
60 coeffs.AGC_epsilon(stage) * (AGC_in - AGC_stage_state);
|
dicklyon@498
|
61 % spatial smooth:
|
dicklyon@498
|
62 AGC_stage_state = ...
|
dicklyon@498
|
63 CARFAC_Spatial_Smooth(coeffs, stage, AGC_stage_state);
|
dicklyon@498
|
64 % and store the state back (in C++, do it all in place?)
|
dicklyon@498
|
65 state.AGC_memory(:, stage) = AGC_stage_state;
|
dicklyon@473
|
66
|
dicklyon@473
|
67 updated = 1; % bool to say we have new state
|
dicklyon@473
|
68 else
|
dicklyon@473
|
69 updated = 0;
|
dicklyon@473
|
70 end
|