annotate matlab/bmm/carfac/CARFAC_CAR_Step.m @ 502:37c007925536

Separate the OHC nonlinear function into new file CARFAC_OHC_NLF.m. Update Design doc a bit. Add optional outputs and hacks that I used with Roy to look at distortion effects in OHC.
author dicklyon@google.com
date Sat, 12 May 2012 04:31:59 +0000
parents 52f659be9008
children a0869cb1c99b
rev   line source
dicklyon@473 1 % Copyright 2012, Google, Inc.
dicklyon@473 2 % Author: Richard F. Lyon
dicklyon@473 3 %
dicklyon@473 4 % This Matlab file is part of an implementation of Lyon's cochlear model:
dicklyon@473 5 % "Cascade of Asymmetric Resonators with Fast-Acting Compression"
dicklyon@473 6 % to supplement Lyon's upcoming book "Human and Machine Hearing"
dicklyon@473 7 %
dicklyon@473 8 % Licensed under the Apache License, Version 2.0 (the "License");
dicklyon@473 9 % you may not use this file except in compliance with the License.
dicklyon@473 10 % You may obtain a copy of the License at
dicklyon@473 11 %
dicklyon@473 12 % http://www.apache.org/licenses/LICENSE-2.0
dicklyon@473 13 %
dicklyon@473 14 % Unless required by applicable law or agreed to in writing, software
dicklyon@473 15 % distributed under the License is distributed on an "AS IS" BASIS,
dicklyon@473 16 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dicklyon@473 17 % See the License for the specific language governing permissions and
dicklyon@473 18 % limitations under the License.
dicklyon@473 19
dicklyon@473 20 function [zY, state] = CARFAC_CAR_Step(x_in, CAR_coeffs, state)
dicklyon@473 21 % function [zY, state] = CARFAC_CAR_Step(x_in, CAR_coeffs, state)
dicklyon@473 22 %
dicklyon@473 23 % One sample-time update step for the filter part of the CARFAC.
dicklyon@473 24
dicklyon@473 25 % Most of the update is parallel; finally we ripple inputs at the end.
dicklyon@473 26
dicklyon@473 27 % Local nonlinearity zA and AGC feedback zB reduce pole radius:
dicklyon@473 28 zA = state.zA_memory;
dicklyon@473 29 zB = state.zB_memory + state.dzB_memory; % AGC interpolation
dicklyon@473 30 r1 = CAR_coeffs.r1_coeffs;
dicklyon@473 31 g = state.g_memory + state.dg_memory; % interp g
dicklyon@473 32
dicklyon@473 33 % zB and zA are "extra damping", and multiply zr (compressed theta):
dicklyon@473 34 r = r1 - CAR_coeffs.zr_coeffs .* (zA + zB);
dicklyon@473 35
dicklyon@473 36 % now reduce state by r and rotate with the fixed cos/sin coeffs:
dicklyon@473 37 z1 = r .* (CAR_coeffs.a0_coeffs .* state.z1_memory - ...
dicklyon@473 38 CAR_coeffs.c0_coeffs .* state.z2_memory);
dicklyon@473 39 % z1 = z1 + inputs;
dicklyon@473 40 z2 = r .* (CAR_coeffs.c0_coeffs .* state.z1_memory + ...
dicklyon@473 41 CAR_coeffs.a0_coeffs .* state.z2_memory);
dicklyon@473 42
dicklyon@502 43 % update the nonlinear function of "velocity", into zA:
dicklyon@502 44 zA = CARFAC_OHC_NLF(state.z2_memory - z2, CAR_coeffs);
dicklyon@473 45
dicklyon@473 46 zY = CAR_coeffs.h_coeffs .* z2; % partial output
dicklyon@473 47
dicklyon@473 48 % Ripple input-output path, instead of parallel, to avoid delay...
dicklyon@473 49 % this is the only part that doesn't get computed "in parallel":
dicklyon@473 50 in_out = x_in;
dicklyon@473 51 for ch = 1:length(zY)
dicklyon@473 52 % could do this here, or later in parallel:
dicklyon@473 53 z1(ch) = z1(ch) + in_out;
dicklyon@473 54 % ripple, saving final channel outputs in zY
dicklyon@473 55 in_out = g(ch) * (in_out + zY(ch));
dicklyon@473 56 zY(ch) = in_out;
dicklyon@473 57 end
dicklyon@473 58
dicklyon@473 59 % put new state back in place of old
dicklyon@473 60 % (z1 and z2 are genuine temps; the others can update by reference in C)
dicklyon@473 61 state.z1_memory = z1;
dicklyon@473 62 state.z2_memory = z2;
dicklyon@473 63 state.zA_memory = zA;
dicklyon@473 64 state.zB_memory = zB;
dicklyon@473 65 state.zY_memory = zY;
dicklyon@473 66 state.g_memory = g;
dicklyon@473 67