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@565
|
20 function [state, updated] = CARFAC_AGC_Step(detects, coeffs, state)
|
dicklyon@565
|
21 % function [state, updated] = CARFAC_AGC_Step(detects, coeffs, state)
|
dicklyon@534
|
22 %
|
dicklyon@559
|
23 % one time step of the AGC state update; decimates internally
|
dicklyon@534
|
24
|
dicklyon@534
|
25 stage = 1;
|
dicklyon@665
|
26 AGC_in = coeffs(1).detect_scale * detects;
|
dicklyon@559
|
27 [state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, stage, state);
|
dicklyon@534
|
28
|
dicklyon@534
|
29
|
dicklyon@559
|
30 function [state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, ...
|
dicklyon@559
|
31 stage, state)
|
dicklyon@559
|
32 % function [state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, ...
|
dicklyon@559
|
33 % stage, state)
|
dicklyon@534
|
34
|
dicklyon@559
|
35 % decim factor for this stage, relative to input or prev. stage:
|
dicklyon@665
|
36 decim = coeffs(stage).decimation;
|
dicklyon@559
|
37 % decim phase of this stage (do work on phase 0 only):
|
dicklyon@665
|
38 decim_phase = mod(state(stage).decim_phase + 1, decim);
|
dicklyon@665
|
39 state(stage).decim_phase = decim_phase;
|
dicklyon@534
|
40
|
dicklyon@534
|
41 % accumulate input for this stage from detect or previous stage:
|
dicklyon@665
|
42 state(stage).input_accum = state(stage).input_accum + AGC_in;
|
dicklyon@534
|
43
|
dicklyon@534
|
44 % nothing else to do if it's not the right decim_phase
|
dicklyon@534
|
45 if decim_phase == 0
|
dicklyon@559
|
46 % do lots of work, at decimated rate.
|
dicklyon@559
|
47 % decimated inputs for this stage, and to be decimated more for next:
|
dicklyon@665
|
48 AGC_in = state(stage).input_accum / decim;
|
dicklyon@665
|
49 state(stage).input_accum(:) = 0; % reset accumulator
|
dicklyon@534
|
50
|
dicklyon@665
|
51 if stage < coeffs(1).n_AGC_stages
|
dicklyon@559
|
52 state = CARFAC_AGC_Recurse(coeffs, AGC_in, stage+1, state);
|
dicklyon@559
|
53 % and add its output to this stage input, whether it updated or not:
|
dicklyon@665
|
54 AGC_in = AGC_in + ...
|
dicklyon@665
|
55 coeffs(stage).AGC_stage_gain * state(stage + 1).AGC_memory;
|
dicklyon@534
|
56 end
|
dicklyon@534
|
57
|
dicklyon@665
|
58 AGC_stage_state = state(stage).AGC_memory;
|
dicklyon@559
|
59 % first-order recursive smoothing filter update, in time:
|
dicklyon@559
|
60 AGC_stage_state = AGC_stage_state + ...
|
dicklyon@665
|
61 coeffs(stage).AGC_epsilon * (AGC_in - AGC_stage_state);
|
dicklyon@559
|
62 % spatial smooth:
|
dicklyon@559
|
63 AGC_stage_state = ...
|
dicklyon@665
|
64 CARFAC_Spatial_Smooth(coeffs(stage), AGC_stage_state);
|
dicklyon@559
|
65 % and store the state back (in C++, do it all in place?)
|
dicklyon@665
|
66 state(stage).AGC_memory = AGC_stage_state;
|
dicklyon@534
|
67
|
dicklyon@534
|
68 updated = 1; % bool to say we have new state
|
dicklyon@534
|
69 else
|
dicklyon@534
|
70 updated = 0;
|
dicklyon@534
|
71 end
|