annotate trunk/matlab/bmm/carfac/CARFAC_AGC_Step.m @ 534:95a11cca4619

Add CARFAC_Design_Doc.txt, CARFAC_Run_Segment.m, and some renames; rename various variables to be more parallel; clean up init code and such.
author dicklyon@google.com
date Fri, 16 Mar 2012 04:19:24 +0000
parents
children 2964a3b4a00a
rev   line source
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 [state, updated] = CARFAC_AGC_Step(AGC_coeffs, detects, state)
dicklyon@534 21 % function [state, updated] = CARFAC_AGC_Step(AGC_coeffs, detects, state)
dicklyon@534 22 %
dicklyon@534 23 % one time step (at decimated low AGC rate) of the AGC state update
dicklyon@534 24
dicklyon@534 25 n_ears = length(state);
dicklyon@534 26 [n_ch, n_AGC_stages] = size(state(1).AGC_memory); % number of channels
dicklyon@534 27
dicklyon@534 28 optimize_for_mono = n_ears == 1; % mono optimization
dicklyon@534 29
dicklyon@534 30 stage = 1;
dicklyon@534 31 ins = AGC_coeffs.detect_scale * detects;
dicklyon@534 32 [state, updated] = CARFAC_AGC_Recurse(AGC_coeffs, ins, n_AGC_stages, ...
dicklyon@534 33 n_ears, n_ch, optimize_for_mono, stage, state);
dicklyon@534 34
dicklyon@534 35
dicklyon@534 36
dicklyon@534 37
dicklyon@534 38
dicklyon@534 39 function [state, updated] = CARFAC_AGC_Recurse(coeffs, ins, n_stages, ...
dicklyon@534 40 n_ears, n_ch, mono, stage, state)
dicklyon@534 41 % function [state, updated = CARFAC_AGC_Recurse(coeffs, ins, n_stages, ...
dicklyon@534 42 % n_ears, n_ch, mono, stage, state)
dicklyon@534 43
dicklyon@534 44 decim = coeffs.decimation(stage); % decim phase for this stage
dicklyon@534 45 decim_phase = mod(state(1).decim_phase(stage) + 1, decim);
dicklyon@534 46 state(1).decim_phase(stage) = decim_phase;
dicklyon@534 47
dicklyon@534 48 % accumulate input for this stage from detect or previous stage:
dicklyon@534 49 for ear = 1:n_ears
dicklyon@534 50 state(ear).input_accum(:, stage) = ...
dicklyon@534 51 state(ear).input_accum(:, stage) + ins(:, ear);
dicklyon@534 52 end
dicklyon@534 53
dicklyon@534 54 % nothing else to do if it's not the right decim_phase
dicklyon@534 55 if decim_phase == 0
dicklyon@534 56 % do lots of work, at decimated rate
dicklyon@534 57
dicklyon@534 58 % decimated inputs for this stage, and to be decimated more for next:
dicklyon@534 59 for ear = 1:n_ears
dicklyon@534 60 ins(:,ear) = state(ear).input_accum(:, stage) / decim;
dicklyon@534 61 state(ear).input_accum(:, stage) = 0; % reset accumulator
dicklyon@534 62 end
dicklyon@534 63
dicklyon@534 64 if stage < n_stages % recurse to evaluate next stage(s)
dicklyon@534 65 state = CARFAC_AGC_Recurse(coeffs, ins, n_stages, ...
dicklyon@534 66 n_ears, n_ch, mono, stage+1, state);
dicklyon@534 67 end
dicklyon@534 68
dicklyon@534 69 epsilon = coeffs.AGC_epsilon(stage); % for this stage's LPF pole
dicklyon@534 70 stage_gain = coeffs.AGC_stage_gain;
dicklyon@534 71
dicklyon@534 72 for ear = 1:n_ears
dicklyon@534 73 AGC_in = ins(:,ear); % the newly decimated input for this ear
dicklyon@534 74
dicklyon@534 75 % AGC_in = max(0, AGC_in); % don't let neg inputs in
dicklyon@534 76
dicklyon@534 77 % add the latest output (state) of next stage...
dicklyon@534 78 if stage < n_stages
dicklyon@534 79 AGC_in = AGC_in + stage_gain * state(ear).AGC_memory(:, stage+1);
dicklyon@534 80 end
dicklyon@534 81
dicklyon@534 82 AGC_stage_state = state(ear).AGC_memory(:, stage);
dicklyon@534 83 % first-order recursive smoothing filter update, in time:
dicklyon@534 84 AGC_stage_state = AGC_stage_state + ...
dicklyon@534 85 epsilon * (AGC_in - AGC_stage_state);
dicklyon@534 86 % spatial smooth:
dicklyon@534 87 AGC_stage_state = ...
dicklyon@534 88 CARFAC_Spatial_Smooth(coeffs, stage, AGC_stage_state);
dicklyon@534 89 % and store the state back (in C++, do it all in place?)
dicklyon@534 90 state(ear).AGC_memory(:, stage) = AGC_stage_state;
dicklyon@534 91
dicklyon@534 92 if ~mono
dicklyon@534 93 if ear == 1
dicklyon@534 94 this_stage_sum = AGC_stage_state;
dicklyon@534 95 else
dicklyon@534 96 this_stage_sum = this_stage_sum + AGC_stage_state;
dicklyon@534 97 end
dicklyon@534 98 end
dicklyon@534 99 end
dicklyon@534 100 if ~mono
dicklyon@534 101 mix_coeff = coeffs.AGC_mix_coeffs(stage);
dicklyon@534 102 if mix_coeff > 0
dicklyon@534 103 this_stage_mean = this_stage_sum / n_ears;
dicklyon@534 104 for ear = 1:n_ears
dicklyon@534 105 state(ear).AGC_memory(:, stage) = ...
dicklyon@534 106 state(ear).AGC_memory(:, stage) + ...
dicklyon@534 107 mix_coeff * ...
dicklyon@534 108 (this_stage_mean - state(ear).AGC_memory(:, stage));
dicklyon@534 109 end
dicklyon@534 110 end
dicklyon@534 111 end
dicklyon@534 112 updated = 1; % bool to say we have new state
dicklyon@534 113 else
dicklyon@534 114 updated = 0;
dicklyon@534 115 end