dicklyon@473: % Copyright 2012, Google, Inc. dicklyon@473: % Author: Richard F. Lyon dicklyon@473: % dicklyon@473: % This Matlab file is part of an implementation of Lyon's cochlear model: dicklyon@473: % "Cascade of Asymmetric Resonators with Fast-Acting Compression" dicklyon@473: % to supplement Lyon's upcoming book "Human and Machine Hearing" dicklyon@473: % dicklyon@473: % Licensed under the Apache License, Version 2.0 (the "License"); dicklyon@473: % you may not use this file except in compliance with the License. dicklyon@473: % You may obtain a copy of the License at dicklyon@473: % dicklyon@473: % http://www.apache.org/licenses/LICENSE-2.0 dicklyon@473: % dicklyon@473: % Unless required by applicable law or agreed to in writing, software dicklyon@473: % distributed under the License is distributed on an "AS IS" BASIS, dicklyon@473: % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. dicklyon@473: % See the License for the specific language governing permissions and dicklyon@473: % limitations under the License. dicklyon@473: dicklyon@504: function [state, updated] = CARFAC_AGC_Step(detects, coeffs, state) dicklyon@504: % function [state, updated] = CARFAC_AGC_Step(detects, coeffs, state) dicklyon@473: % dicklyon@498: % one time step of the AGC state update; decimates internally dicklyon@473: dicklyon@473: stage = 1; dicklyon@623: AGC_in = coeffs(1).detect_scale * detects; dicklyon@498: [state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, stage, state); dicklyon@473: dicklyon@473: dicklyon@498: function [state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, ... dicklyon@498: stage, state) dicklyon@498: % function [state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, ... dicklyon@498: % stage, state) dicklyon@473: dicklyon@498: % decim factor for this stage, relative to input or prev. stage: dicklyon@623: decim = coeffs(stage).decimation; dicklyon@498: % decim phase of this stage (do work on phase 0 only): dicklyon@623: decim_phase = mod(state(stage).decim_phase + 1, decim); dicklyon@623: state(stage).decim_phase = decim_phase; dicklyon@473: dicklyon@473: % accumulate input for this stage from detect or previous stage: dicklyon@623: state(stage).input_accum = state(stage).input_accum + AGC_in; dicklyon@473: dicklyon@473: % nothing else to do if it's not the right decim_phase dicklyon@473: if decim_phase == 0 dicklyon@498: % do lots of work, at decimated rate. dicklyon@498: % decimated inputs for this stage, and to be decimated more for next: dicklyon@623: AGC_in = state(stage).input_accum / decim; dicklyon@623: state(stage).input_accum(:) = 0; % reset accumulator dicklyon@473: dicklyon@623: if stage < coeffs(1).n_AGC_stages dicklyon@498: state = CARFAC_AGC_Recurse(coeffs, AGC_in, stage+1, state); dicklyon@498: % and add its output to this stage input, whether it updated or not: dicklyon@623: AGC_in = AGC_in + ... dicklyon@623: coeffs(stage).AGC_stage_gain * state(stage + 1).AGC_memory; dicklyon@473: end dicklyon@473: dicklyon@623: AGC_stage_state = state(stage).AGC_memory; dicklyon@498: % first-order recursive smoothing filter update, in time: dicklyon@498: AGC_stage_state = AGC_stage_state + ... dicklyon@623: coeffs(stage).AGC_epsilon * (AGC_in - AGC_stage_state); dicklyon@498: % spatial smooth: dicklyon@498: AGC_stage_state = ... dicklyon@623: CARFAC_Spatial_Smooth(coeffs(stage), AGC_stage_state); dicklyon@498: % and store the state back (in C++, do it all in place?) dicklyon@623: state(stage).AGC_memory = AGC_stage_state; dicklyon@473: dicklyon@473: updated = 1; % bool to say we have new state dicklyon@473: else dicklyon@473: updated = 0; dicklyon@473: end