Mercurial > hg > aimc
changeset 559:89b1fe5de60f
Simplify AGC_Step, moving multi-aural cross coupling to new function CARFAC_Cross_Couple
author | dicklyon@google.com |
---|---|
date | Tue, 10 Apr 2012 05:40:18 +0000 |
parents | 8ca6eb401a03 |
children | ab7fabe2af5d |
files | trunk/matlab/bmm/carfac/CARFAC_AGC_Step.m trunk/matlab/bmm/carfac/CARFAC_Cross_Couple.m trunk/matlab/bmm/carfac/CARFAC_Design.m trunk/matlab/bmm/carfac/CARFAC_Run_Segment.m trunk/matlab/bmm/carfac/CARFAC_hacking.m |
diffstat | 5 files changed, 89 insertions(+), 94 deletions(-) [+] |
line wrap: on
line diff
--- a/trunk/matlab/bmm/carfac/CARFAC_AGC_Step.m Mon Apr 09 13:22:28 2012 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_AGC_Step.m Tue Apr 10 05:40:18 2012 +0000 @@ -17,96 +17,53 @@ % See the License for the specific language governing permissions and % limitations under the License. -function [state, updated] = CARFAC_AGC_Step(AGC_coeffs, detects, state) -% function [state, updated] = CARFAC_AGC_Step(AGC_coeffs, detects, state) +function [state, updated] = CARFAC_AGC_Step(coeffs, detects, state) +% function [state, updated] = CARFAC_AGC_Step(coeffs, detects, state) % -% one time step (at decimated low AGC rate) of the AGC state update - -n_ears = length(state); -[n_ch, n_AGC_stages] = size(state(1).AGC_memory); % number of channels - -optimize_for_mono = n_ears == 1; % mono optimization +% one time step of the AGC state update; decimates internally stage = 1; -ins = AGC_coeffs.detect_scale * detects; -[state, updated] = CARFAC_AGC_Recurse(AGC_coeffs, ins, n_AGC_stages, ... - n_ears, n_ch, optimize_for_mono, stage, state); +AGC_in = coeffs.detect_scale * detects; +[state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, stage, state); +function [state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, ... + stage, state) +% function [state, updated] = CARFAC_AGC_Recurse(coeffs, AGC_in, ... +% stage, state) - - -function [state, updated] = CARFAC_AGC_Recurse(coeffs, ins, n_stages, ... - n_ears, n_ch, mono, stage, state) -% function [state, updated = CARFAC_AGC_Recurse(coeffs, ins, n_stages, ... -% n_ears, n_ch, mono, stage, state) - -decim = coeffs.decimation(stage); % decim phase for this stage +% decim factor for this stage, relative to input or prev. stage: +decim = coeffs.decimation(stage); +% decim phase of this stage (do work on phase 0 only): decim_phase = mod(state(1).decim_phase(stage) + 1, decim); -state(1).decim_phase(stage) = decim_phase; +state.decim_phase(stage) = decim_phase; % accumulate input for this stage from detect or previous stage: -for ear = 1:n_ears - state(ear).input_accum(:, stage) = ... - state(ear).input_accum(:, stage) + ins(:, ear); -end +state.input_accum(:, stage) = state.input_accum(:, stage) + AGC_in; % nothing else to do if it's not the right decim_phase if decim_phase == 0 - % do lots of work, at decimated rate + % do lots of work, at decimated rate. + % decimated inputs for this stage, and to be decimated more for next: + AGC_in = state.input_accum(:, stage) / decim; + state.input_accum(:, stage) = 0; % reset accumulator - % decimated inputs for this stage, and to be decimated more for next: - for ear = 1:n_ears - ins(:,ear) = state(ear).input_accum(:, stage) / decim; - state(ear).input_accum(:, stage) = 0; % reset accumulator + if stage < length(coeffs.decimation) % recurse to evaluate next stage(s) + state = CARFAC_AGC_Recurse(coeffs, AGC_in, stage+1, state); + % and add its output to this stage input, whether it updated or not: + AGC_in = AGC_in + coeffs.AGC_stage_gain * state.AGC_memory(:, stage+1); end - if stage < n_stages % recurse to evaluate next stage(s) - state = CARFAC_AGC_Recurse(coeffs, ins, n_stages, ... - n_ears, n_ch, mono, stage+1, state); - end + AGC_stage_state = state.AGC_memory(:, stage); + % first-order recursive smoothing filter update, in time: + AGC_stage_state = AGC_stage_state + ... + coeffs.AGC_epsilon(stage) * (AGC_in - AGC_stage_state); + % spatial smooth: + AGC_stage_state = ... + CARFAC_Spatial_Smooth(coeffs, stage, AGC_stage_state); + % and store the state back (in C++, do it all in place?) + state.AGC_memory(:, stage) = AGC_stage_state; - epsilon = coeffs.AGC_epsilon(stage); % for this stage's LPF pole - stage_gain = coeffs.AGC_stage_gain; - - for ear = 1:n_ears - AGC_in = ins(:,ear); % the newly decimated input for this ear - - % add the latest output (state) of next stage... - if stage < n_stages - AGC_in = AGC_in + stage_gain * state(ear).AGC_memory(:, stage+1); - end - - AGC_stage_state = state(ear).AGC_memory(:, stage); - % first-order recursive smoothing filter update, in time: - AGC_stage_state = AGC_stage_state + ... - epsilon * (AGC_in - AGC_stage_state); - % spatial smooth: - AGC_stage_state = ... - CARFAC_Spatial_Smooth(coeffs, stage, AGC_stage_state); - % and store the state back (in C++, do it all in place?) - state(ear).AGC_memory(:, stage) = AGC_stage_state; - - if ~mono - if ear == 1 - this_stage_sum = AGC_stage_state; - else - this_stage_sum = this_stage_sum + AGC_stage_state; - end - end - end - if ~mono - mix_coeff = coeffs.AGC_mix_coeffs(stage); - if mix_coeff > 0 - this_stage_mean = this_stage_sum / n_ears; - for ear = 1:n_ears - state(ear).AGC_memory(:, stage) = ... - state(ear).AGC_memory(:, stage) + ... - mix_coeff * ... - (this_stage_mean - state(ear).AGC_memory(:, stage)); - end - end - end updated = 1; % bool to say we have new state else updated = 0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_Cross_Couple.m Tue Apr 10 05:40:18 2012 +0000 @@ -0,0 +1,29 @@ +function AGC_state = CARFAC_Cross_Couple(AGC_coeffs, AGC_state); + +n_ears = length(AGC_state); +mix_coeffs = AGC_coeffs.AGC_mix_coeffs; +n_stages = length(mix_coeffs); + +% now cross-ear mix the stages that updated (leading stages at phase 0): +for stage = 1:n_stages + if AGC_state(1).decim_phase(stage) > 0 + break % all recently updated stages are finished + else + mix_coeff = mix_coeffs(stage); + if mix_coeff > 0 % Typically stage 1 has 0 so no work on that one. + this_stage_sum = 0; + % sum up over the ears and get their mean: + for ear = 1:n_ears + stage_state = AGC_state(ear).AGC_memory(:, stage); + this_stage_sum = this_stage_sum + stage_state; + end + this_stage_mean = this_stage_sum / n_ears; + % now move them all toward the mean: + for ear = 1:n_ears + stage_state = AGC_state(ear).AGC_memory(:, stage); + AGC_state(ear).AGC_memory(:, stage) = ... + stage_state + mix_coeff * (this_stage_mean - stage_state); + end + end + end +end
--- a/trunk/matlab/bmm/carfac/CARFAC_Design.m Mon Apr 09 13:22:28 2012 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_Design.m Tue Apr 10 05:40:18 2012 +0000 @@ -151,6 +151,8 @@ 'v_damp_max', CAR_params.v_damp_max ... ); +% don't really need these zero arrays, but it's a clue to what fields +% and types are need in ohter language implementations: CAR_coeffs.r1_coeffs = zeros(n_ch, 1); CAR_coeffs.a0_coeffs = zeros(n_ch, 1); CAR_coeffs.c0_coeffs = zeros(n_ch, 1); @@ -213,7 +215,7 @@ 'AGC_stage_gain', AGC_params.AGC_stage_gain); % AGC1 pass is smoothing from base toward apex; -% AGC2 pass is back, which is done first now +% AGC2 pass is back, which is done first now (in double exp. version) AGC1_scales = AGC_params.AGC1_scales; AGC2_scales = AGC_params.AGC2_scales; @@ -294,7 +296,6 @@ % adjust the detect_scale by the total DC gain of the AGC filters: AGC_coeffs.detect_scale = AGC_params.detect_scale / total_DC_gain; - % % print some results AGC_coeffs AGC_spatial_FIR = AGC_coeffs.AGC_spatial_FIR
--- a/trunk/matlab/bmm/carfac/CARFAC_Run_Segment.m Mon Apr 09 13:22:28 2012 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_Run_Segment.m Tue Apr 10 05:40:18 2012 +0000 @@ -78,20 +78,27 @@ [ihc_out, CF.IHC_state(ear)] = CARFAC_IHC_Step( ... car_out, CF.IHC_coeffs, CF.IHC_state(ear)); - detects(:, ear) = ihc_out; % for input to AGC, and out to SAI - naps(k, :, ear) = ihc_out; % output to neural activity pattern + % run the AGC update step, decimating internally, + [CF.AGC_state(ear), updated] = CARFAC_AGC_Step( ... + CF.AGC_coeffs, ihc_out, CF.AGC_state(ear)); + + % save some output data: + naps(k, :, ear) = ihc_out; % output to neural activity pattern if do_BM BM(k, :, ear) = car_out; end end - % run the AGC update step, taking input from IHC_state, - % decimating internally, all ears at once due to mixing across them: - [CF.AGC_state, updated] = CARFAC_AGC_Step( ... - CF.AGC_coeffs, detects, CF.AGC_state); - % connect the feedback from AGC_state to CAR_state when it updates - if updated & ~open_loop - CF = CARFAC_Close_AGC_Loop(CF); + % connect the feedback from AGC_state to CAR_state when it updates; + % all ears together here due to mixing across them: + if updated + if n_ears > 1 + % do multi-aural cross-coupling: + CF.AGC_state = CARFAC_Cross_Couple(CF.AGC_coeffs, CF.AGC_state); + end + if ~open_loop + CF = CARFAC_Close_AGC_Loop(CF); + end end end
--- a/trunk/matlab/bmm/carfac/CARFAC_hacking.m Mon Apr 09 13:22:28 2012 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_hacking.m Tue Apr 10 05:40:18 2012 +0000 @@ -22,7 +22,7 @@ clear variables %% -use_plan_file = 0; +use_plan_file = 1; if use_plan_file file_signal = wavread('plan.wav'); @@ -48,7 +48,7 @@ % make a long test signal by repeating at different levels: dB = -80; test_signal = 10^(dB/20)* file_signal(1:4000) % lead-in []; -for dB = -80:20:80 +for dB = -80:20:60 test_signal = [test_signal; file_signal * 10^(dB/20)]; end @@ -59,7 +59,12 @@ agc_plot_fig_num = 6; -for n_ears = 1 % 1:2 +for n_ears = 1:2 + if n_ears == 2 + % For the 2-channel pass, add a silent second channel: + test_signal = [test_signal, zeros(size(test_signal))]; + end + CF_struct = CARFAC_Init(CF_struct, n_ears); [CF_struct, nap_decim, nap, BM] = CARFAC_Run(CF_struct, test_signal, ... @@ -70,10 +75,8 @@ % dB_BM = 10/log(10) * log(filter(1, [1, -0.995], BM(:, 38:40, :).^2)); dB_BM = 10/log(10) * log(filter(1, [1, -0.995], BM(:, 20:50, :).^2)); - if n_ears == 1 % because this hack doesn't work for binarual yet - MultiScaleSmooth(dB_BM(5000:200:end, :, :), 1); -% MultiScaleSmooth(nap_decim, 4); - end + % only ear 1: + MultiScaleSmooth(dB_BM(5000:200:end, :, 1), 1); % Display results for 1 or 2 ears: for ear = 1:n_ears @@ -93,8 +96,6 @@ CF_struct.AGC_state min_max_decim = [min(nap_decim(:)), max(nap_decim(:))] - % For the 2-channel pass, add a silent second channel: - test_signal = [test_signal, zeros(size(test_signal))]; end % Expected result: Figure 3 looks like figure 2, a tiny bit darker.