Mercurial > hg > aimc
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_AGCStep.m Wed Feb 15 21:26:40 2012 +0000 @@ -0,0 +1,82 @@ +% Copyright 2012, Google, Inc. +% Author: Richard F. Lyon +% +% This Matlab file is part of an implementation of Lyon's cochlear model: +% "Cascade of Asymmetric Resonators with Fast-Acting Compression" +% to supplement Lyon's upcoming book "Human and Machine Hearing" +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +function state = CARFAC_AGCStep(AGC_coeffs, avg_detects, state) +% function state = CARFAC_AGCStep(AGC_coeffs, avg_detects, state) +% +% one time step (at decimated low AGC rate) of the AGC state update + +n_AGC_stages = length(AGC_coeffs.AGC_epsilon); +n_mics = length(state); +n_ch = size(state(1).AGC_sum, 1); % number of channels + +optimize_for_mono = n_mics == 1; % mono optimization +if ~optimize_for_mono + stage_sum = zeros(n_ch, 1); +end + +for stage = 1:n_AGC_stages + if ~optimize_for_mono % skip if mono + if stage > 1 + prev_stage_mean = stage_sum / n_mics; + end + stage_sum(:) = 0; % sum accumulating over mics at this stage + end + epsilon = AGC_coeffs.AGC_epsilon(stage); % for this stage's LPF pole + polez1 = AGC_coeffs.AGC1_polez(stage); + polez2 = AGC_coeffs.AGC2_polez(stage); + for mic = 1:n_mics + if stage == 1 + AGC_in = AGC_coeffs.detect_scale * avg_detects(:,mic); + AGC_in = max(0, AGC_in); % don't let neg inputs in + else + % prev. stage mixed with prev_stage_sum + if optimize_for_mono + % Mono optimization ignores AGC_mix_coeff, + % assuming all(prev_stage_mean == AGC_memory(:, stage - 1)); + % but we also don't even allocate or compute the sum or mean. + AGC_in = AGC_coeffs.AGC_stage_gain * ... + state(mic).AGC_memory(:, stage - 1); + else + AGC_in = AGC_coeffs.AGC_stage_gain * ... + (AGC_coeffs.AGC_mix_coeff * prev_stage_mean + ... + (1 - AGC_coeffs.AGC_mix_coeff) * ... + state(mic).AGC_memory(:, stage - 1)); + end + end + AGC_stage = state(mic).AGC_memory(:, stage); + % first-order recursive smooting filter update: + AGC_stage = AGC_stage + epsilon * (AGC_in - AGC_stage); + + % spatially spread it; using diffusion coeffs like in smooth1d + AGC_stage = SmoothDoubleExponential(AGC_stage, polez1, polez2); + + state(mic).AGC_memory(:, stage) = AGC_stage; + if stage == 1 + state(mic).sum_AGC = AGC_stage; + else + state(mic).sum_AGC = state(mic).sum_AGC + AGC_stage; + end + if ~optimize_for_mono + stage_sum = stage_sum + AGC_stage; + end + end +end + +