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