Mercurial > hg > aimc
changeset 463:638d4f0ae139
Improve AGC coeffs design with better math
author | dicklyon@google.com |
---|---|
date | Wed, 07 Mar 2012 00:03:09 +0000 |
parents | 87699cb4cf71 |
children | 7b57ab0d0126 |
files | matlab/bmm/carfac/CARFAC_Design.m |
diffstat | 1 files changed, 32 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/matlab/bmm/carfac/CARFAC_Design.m Thu Mar 01 19:49:24 2012 +0000 +++ b/matlab/bmm/carfac/CARFAC_Design.m Wed Mar 07 00:03:09 2012 +0000 @@ -84,8 +84,8 @@ 'time_constants', [1, 4, 16, 64]*0.002, ... 'AGC_stage_gain', 2, ... % gain from each stage to next slower stage 'decimation', [8, 2, 2, 2], ... % how often to update the AGC states - 'AGC1_scales', [1, 2, 4, 8]*1, ... % in units of channels - 'AGC2_scales', [1, 2, 4, 8]*1.5, ... % spread more toward base + 'AGC1_scales', [1, 2, 4, 6]*1, ... % in units of channels + 'AGC2_scales', [1, 2, 4, 6]*1.5, ... % spread more toward base 'detect_scale', 0.15, ... % the desired damping range 'AGC_mix_coeff', 0.5); end @@ -186,9 +186,9 @@ h = sin(theta) .* f; filter_coeffs.h_coeffs = h; -r2 = r; % aim for unity DC gain at min damping, here; or could try r^2 -filter_coeffs.g_coeffs = 1 ./ (1 + h .* r2 .* sin(theta) ./ ... - (1 - 2 * r2 .* cos(theta) + r2 .^ 2)); +% unity gain at min damping, radius r: +filter_coeffs.g_coeffs = (1 - 2*r.*cos(theta) + r.^2) ./ ... + (1 - 2*r .* cos(theta) + h .* r .* sin(theta) + r.^2); %% the AGC design coeffs: @@ -216,35 +216,38 @@ n_iterations = 1; % how many times to apply smoothing filter in a stage % effective number of smoothings in a time constant: - ntimes = n_iterations * tau * (fs / decim); - % divide the spatial variance by effective number of smoothings: - % t is the variance of the distribution (impulse response width squared) - t1 = (AGC1_scales(stage)^2) / ntimes; - t2 = (AGC2_scales(stage)^2) / ntimes; - % the back-and-forth IIR method coefficients: - polez1 = 1 + 1/t1 - sqrt((1+1/t1)^2 - 1); - polez2 = 1 + 1/t2 - sqrt((1+1/t2)^2 - 1); + ntimes = n_iterations * tau * (fs / decim); + + % decide on target spread (variance) and delay (mean) of impulse + % response as a distribution to be convolved ntimes: + delay = (AGC2_scales(stage) - AGC1_scales(stage)) / ntimes; + spread_sq = (AGC1_scales(stage)^2 + AGC2_scales(stage)^2) / ntimes; + + % get pole positions to better match intended spread and delay: + u = 1 + 1 / spread_sq; % these are based on off-line algebra hacking. + p = u - sqrt(u^2 - 1); % pole that would give spread if used twice. + dp = delay * (1 - 2*p +p^2)/2; + polez1 = p - dp; + polez2 = p + dp; AGC_coeffs.AGC_polez1(stage) = polez1; AGC_coeffs.AGC_polez2(stage) = polez2; - % above method has spatial "delay" near sqrt(t2) - sqrt(t1) per time, - % or net delay that is not independent of ntimes. A problem??? + % from [[Geometric distribution]] mean and variance from wikipedia, + % to verify that we got what we intended, very nearly, and make the + % FIR version to match the poles version: + % delay = polez2/(1-polez2) - polez1/(1-polez1); + % spread_sq = polez1/(1-polez1)^2 + polez2/(1-polez2)^2; % try a 3-tap FIR as an alternative: n_taps = 3; - % from geometric distribution mean and variance from wikipedia: - delay = polez2/(1-polez2) - polez1/(1-polez1); - total_delay = delay * ntimes - spread_sq = polez1/(1-polez1)^2 + polez2/(1-polez2)^2; - total_spread = sqrt(spread_sq * ntimes) - - delay1 = delay; % keep this as 1-iteration delay reference... a = (spread_sq + delay*delay - delay) / 2; b = (spread_sq + delay*delay + delay) / 2; AGC_spatial_FIR = [a, 1 - a - b, b]; % stored as 5 taps done = AGC_spatial_FIR(2) > 0.1; % not OK if center tap is too low % if 1 iteration is not good with 3 taps go to 5 taps, then more - % iterations if needed, and then fall back to double-exponential IIR: + % iterations if needed, and maybe fall back to double-exponential IIR: + spread_sq1 = spread_sq; % keep this as 1-iteration spread reference... + delay1 = delay; % keep this as 1-iteration delay reference... while ~done % smoothing condition, middle value if n_taps == 3 % first time through, go wider but stick to 1 iteration @@ -254,13 +257,8 @@ % already at 5 taps, so just increase iterations n_iterations = n_iterations + 1; % number of times to apply spatial end - ntimes = n_iterations * tau * (fs / decim); % effective number of smoothings - % divide the spatial variance by effective number of smoothings: - % t is the variance of the distribution (impulse response width squared) - t1 = (AGC1_scales(stage)^2) / ntimes; - t2 = (AGC2_scales(stage)^2) / ntimes; - spread_sq = t1 + t2; - delay = delay1 / n_iterations; % maybe better than sqrt(t2) - sqrt(t1); + spread_sq = spread_sq1 / n_iterations; + delay = delay1 / n_iterations; % 5-tap design duplicates the a and b coeffs; stores just 3 coeffs: % a and b from their sum and diff as before: (sum \pm diff) / 2: a = ((spread_sq + delay*delay)*2/5 - delay*2/3) / 2; @@ -284,13 +282,11 @@ end end -AGC_coeffs.AGC_spatial_FIR -AGC_coeffs.AGC_spatial_iterations -AGC_coeffs.AGC_n_taps -AGC_coeffs.AGC_polez1 -AGC_coeffs.AGC_polez2 +AGC_coeffs.AGC_gain = total_DC_gain; -AGC_coeffs.AGC_gain = total_DC_gain; +% print some results +AGC_coeffs +AGC_spatial_FIR = AGC_coeffs.AGC_spatial_FIR %% the IHC design coeffs: