Mercurial > hg > aimc
comparison trunk/matlab/bmm/carfac/CARFAC_AGCStep.m @ 516:68c15d43fcc8
Added MATLAB code for Lyon's CAR-FAC filter cascade.
author | tom@acousticscale.org |
---|---|
date | Wed, 15 Feb 2012 21:26:40 +0000 |
parents | |
children | 2b96cb7ea4f7 |
comparison
equal
deleted
inserted
replaced
454:49b7b984e957 | 516:68c15d43fcc8 |
---|---|
1 % Copyright 2012, Google, Inc. | |
2 % Author: Richard F. Lyon | |
3 % | |
4 % This Matlab file is part of an implementation of Lyon's cochlear model: | |
5 % "Cascade of Asymmetric Resonators with Fast-Acting Compression" | |
6 % to supplement Lyon's upcoming book "Human and Machine Hearing" | |
7 % | |
8 % Licensed under the Apache License, Version 2.0 (the "License"); | |
9 % you may not use this file except in compliance with the License. | |
10 % You may obtain a copy of the License at | |
11 % | |
12 % http://www.apache.org/licenses/LICENSE-2.0 | |
13 % | |
14 % Unless required by applicable law or agreed to in writing, software | |
15 % distributed under the License is distributed on an "AS IS" BASIS, | |
16 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
17 % See the License for the specific language governing permissions and | |
18 % limitations under the License. | |
19 | |
20 function state = CARFAC_AGCStep(AGC_coeffs, avg_detects, state) | |
21 % function state = CARFAC_AGCStep(AGC_coeffs, avg_detects, state) | |
22 % | |
23 % one time step (at decimated low AGC rate) of the AGC state update | |
24 | |
25 n_AGC_stages = length(AGC_coeffs.AGC_epsilon); | |
26 n_mics = length(state); | |
27 n_ch = size(state(1).AGC_sum, 1); % number of channels | |
28 | |
29 optimize_for_mono = n_mics == 1; % mono optimization | |
30 if ~optimize_for_mono | |
31 stage_sum = zeros(n_ch, 1); | |
32 end | |
33 | |
34 for stage = 1:n_AGC_stages | |
35 if ~optimize_for_mono % skip if mono | |
36 if stage > 1 | |
37 prev_stage_mean = stage_sum / n_mics; | |
38 end | |
39 stage_sum(:) = 0; % sum accumulating over mics at this stage | |
40 end | |
41 epsilon = AGC_coeffs.AGC_epsilon(stage); % for this stage's LPF pole | |
42 polez1 = AGC_coeffs.AGC1_polez(stage); | |
43 polez2 = AGC_coeffs.AGC2_polez(stage); | |
44 for mic = 1:n_mics | |
45 if stage == 1 | |
46 AGC_in = AGC_coeffs.detect_scale * avg_detects(:,mic); | |
47 AGC_in = max(0, AGC_in); % don't let neg inputs in | |
48 else | |
49 % prev. stage mixed with prev_stage_sum | |
50 if optimize_for_mono | |
51 % Mono optimization ignores AGC_mix_coeff, | |
52 % assuming all(prev_stage_mean == AGC_memory(:, stage - 1)); | |
53 % but we also don't even allocate or compute the sum or mean. | |
54 AGC_in = AGC_coeffs.AGC_stage_gain * ... | |
55 state(mic).AGC_memory(:, stage - 1); | |
56 else | |
57 AGC_in = AGC_coeffs.AGC_stage_gain * ... | |
58 (AGC_coeffs.AGC_mix_coeff * prev_stage_mean + ... | |
59 (1 - AGC_coeffs.AGC_mix_coeff) * ... | |
60 state(mic).AGC_memory(:, stage - 1)); | |
61 end | |
62 end | |
63 AGC_stage = state(mic).AGC_memory(:, stage); | |
64 % first-order recursive smooting filter update: | |
65 AGC_stage = AGC_stage + epsilon * (AGC_in - AGC_stage); | |
66 | |
67 % spatially spread it; using diffusion coeffs like in smooth1d | |
68 AGC_stage = SmoothDoubleExponential(AGC_stage, polez1, polez2); | |
69 | |
70 state(mic).AGC_memory(:, stage) = AGC_stage; | |
71 if stage == 1 | |
72 state(mic).sum_AGC = AGC_stage; | |
73 else | |
74 state(mic).sum_AGC = state(mic).sum_AGC + AGC_stage; | |
75 end | |
76 if ~optimize_for_mono | |
77 stage_sum = stage_sum + AGC_stage; | |
78 end | |
79 end | |
80 end | |
81 | |
82 |