Mercurial > hg > aimc
changeset 563:fb602edc2d55
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 | 167d8ec2468e |
children | 9c4c3675c3f8 |
files | trunk/matlab/bmm/carfac/CARFAC_CAR_Step.m trunk/matlab/bmm/carfac/CARFAC_Design.m trunk/matlab/bmm/carfac/CARFAC_Design_Doc.txt trunk/matlab/bmm/carfac/CARFAC_OHC_NLF.m trunk/matlab/bmm/carfac/CARFAC_Run.m trunk/matlab/bmm/carfac/CARFAC_Run_Segment.m trunk/matlab/bmm/carfac/CARFAC_hacking.m |
diffstat | 7 files changed, 146 insertions(+), 56 deletions(-) [+] |
line wrap: on
line diff
--- a/trunk/matlab/bmm/carfac/CARFAC_CAR_Step.m Tue May 01 23:32:24 2012 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_CAR_Step.m Sat May 12 04:31:59 2012 +0000 @@ -29,9 +29,6 @@ zB = state.zB_memory + state.dzB_memory; % AGC interpolation r1 = CAR_coeffs.r1_coeffs; g = state.g_memory + state.dg_memory; % interp g -v_offset = CAR_coeffs.v_offset; -v2_corner = CAR_coeffs.v2_corner; -v_damp_max = CAR_coeffs.v_damp_max; % zB and zA are "extra damping", and multiply zr (compressed theta): r = r1 - CAR_coeffs.zr_coeffs .* (zA + zB); @@ -43,11 +40,8 @@ z2 = r .* (CAR_coeffs.c0_coeffs .* state.z1_memory + ... CAR_coeffs.a0_coeffs .* state.z2_memory); -% update the "velocity" for cubic nonlinearity, into zA: -zA = (((state.z2_memory - z2) .* CAR_coeffs.velocity_scale) + ... - v_offset) .^ 2; -% soft saturation to make it more like an "essential" nonlinearity: -zA = v_damp_max * zA ./ (v2_corner + zA); +% update the nonlinear function of "velocity", into zA: +zA = CARFAC_OHC_NLF(state.z2_memory - z2, CAR_coeffs); zY = CAR_coeffs.h_coeffs .* z2; % partial output
--- a/trunk/matlab/bmm/carfac/CARFAC_Design.m Tue May 01 23:32:24 2012 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_Design.m Sat May 12 04:31:59 2012 +0000 @@ -53,7 +53,7 @@ if nargin < 3 CF_CAR_params = struct( ... 'velocity_scale', 0.2, ... % for the "cubic" velocity nonlinearity - 'v_offset', 0.01, ... % offset gives a quadratic part + 'v_offset', 0.04, ... % offset gives a quadratic part 'v2_corner', 0.2, ... % corner for essential nonlin 'v_damp_max', 0.01, ... % damping delta damping from velocity nonlin 'min_zeta', 0.10, ... % minimum damping factor in mid-freq channels @@ -71,7 +71,7 @@ 'n_stages', 4, ... '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 + 'decimation', [4, 2, 2, 2], ... % how often to update the AGC states 'AGC1_scales', [1.0, 1.4, 2.0, 2.8], ... % in units of channels 'AGC2_scales', [1.6, 2.25, 3.2, 4.5], ... % spread more toward base 'detect_scale', 0.25, ... % the desired damping range
--- a/trunk/matlab/bmm/carfac/CARFAC_Design_Doc.txt Tue May 01 23:32:24 2012 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_Design_Doc.txt Sat May 12 04:31:59 2012 +0000 @@ -7,7 +7,7 @@ processor, for mono, stereo, or multi-channel sound inputs. This file describes aspects of the software design. -The implementation will include equivalent Maltab, C++, Python, and +The implementation will include equivalent Matlab, C++, Python, and perhaps other versions. They should all be based on the same set of classes (or structs) and functions, with roughly equivalent functionality and names where possible. The examples here are Matlab, @@ -20,7 +20,10 @@ includes various sub-objects representing the parameters, designs, and states of different parts of the CAR-FAC model. -The three main subsystems of the CARFAC are the cascade of asymmetric +The CARFAC class includes a vector of "ear" objects -- one for mono, +two for stereo, or more. + +The three main subsystems of the EAR are the cascade of asymmetric resonators (CAR), the inner hair cell (IHC), and the automatic gain control (AGC). These are not intended to work independently, so may not have corresponding classes to combine all their aspects (in the @@ -35,8 +38,6 @@ These names can be used both for the classes, and slightly modified for the member variables, arguments, temps, etc. - -- (presently we have "filters" where I say "CAR"; I'll change it) -- - The params are inputs that specify the system; the coeffs are things like filter coefficients, things computed once and used at run time; the state is whatever internal state is needed between running the
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_OHC_NLF.m Sat May 12 04:31:59 2012 +0000 @@ -0,0 +1,7 @@ +function nlf = CARFAC_OHC_NLF(velocities, CAR_coeffs) + +nlf = ((velocities .* CAR_coeffs.velocity_scale) + ... + CAR_coeffs.v_offset) .^ 2; +% soft saturation to make it more like an "essential" nonlinearity: +nlf = CAR_coeffs.v_damp_max * nlf ./ (CAR_coeffs.v2_corner + nlf); +
--- a/trunk/matlab/bmm/carfac/CARFAC_Run.m Tue May 01 23:32:24 2012 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_Run.m Sat May 12 04:31:59 2012 +0000 @@ -17,9 +17,9 @@ % See the License for the specific language governing permissions and % limitations under the License. -function [CF, decim_naps, naps, BM] = CARFAC_Run ... +function [CF, decim_naps, naps, BM, ohc, agc] = CARFAC_Run ... (CF, input_waves, AGC_plot_fig_num) -% function [CF, decim_naps, naps] = CARFAC_Run ... +% function [CF, decim_naps, naps, BM, ohc, agc] = CARFAC_Run ... % (CF, input_waves, AGC_plot_fig_num) % This function runs the CARFAC; that is, filters a 1 or more channel % sound input to make one or more neural activity patterns (naps). @@ -38,10 +38,7 @@ % the input_waves are assumed to be sampled at the same rate as the % CARFAC is designed for; a resampling may be needed before calling this. % -% The function works as an outer iteration on time, updating all the -% filters and AGC states concurrently, so that the different channels can -% interact easily. The inner loops are over filterbank channels, and -% this level should be kept efficient. +% ohc and agc are optional extra outputs for diagnosing internals. [n_samp, n_ears] = size(input_waves); n_ch = CF.n_ch; @@ -56,6 +53,18 @@ BM = []; end +if nargout > 4 + ohc = zeros(n_samp, n_ch, n_ears); +else + ohc = []; +end + +if nargout > 5 + agc = zeros(n_samp, n_ch, n_ears); +else + agc = []; +end + if n_ears ~= CF.n_ears error('bad number of input_waves channels passed to CARFAC_Run') end @@ -89,7 +98,8 @@ end % Process a segment to get a slice of decim_naps, and plot AGC state: if ~isempty(BM) - [seg_naps, CF, seg_BM] = CARFAC_Run_Segment(CF, input_waves(k_range, :)); + % ask for everything in this case, for laziness: + [seg_naps, CF, seg_BM, seg_ohc, seg_agc] = CARFAC_Run_Segment(CF, input_waves(k_range, :)); else [seg_naps, CF] = CARFAC_Run_Segment(CF, input_waves(k_range, :)); end @@ -108,6 +118,20 @@ end end + if ~isempty(ohc) + for ear = 1:n_ears + % Accumulate segment naps to make full naps + ohc(k_range, :, ear) = seg_ohc(:, :, ear); + end + end + + if ~isempty(agc) + for ear = 1:n_ears + % Accumulate segment naps to make full naps + agc(k_range, :, ear) = seg_agc(:, :, ear); + end + end + if ~isempty(decim_naps) for ear = 1:n_ears decim_naps(seg_num, :, ear) = CF.ears(ear).IHC_state.ihc_accum / seglen;
--- a/trunk/matlab/bmm/carfac/CARFAC_Run_Segment.m Tue May 01 23:32:24 2012 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_Run_Segment.m Sat May 12 04:31:59 2012 +0000 @@ -17,8 +17,10 @@ % See the License for the specific language governing permissions and % limitations under the License. -function [naps, CF, BM] = CARFAC_Run_Segment(CF, input_waves, open_loop) -% function [naps, CF, BM] = CARFAC_Run_Segment(CF, input_waves, open_loop) +function [naps, CF, BM, seg_ohc, seg_agc] = CARFAC_Run_Segment(... + CF, input_waves, open_loop) +% function [naps, CF, BM, seg_ohc, seg_agc] = CARFAC_Run_Segment(... +% CF, input_waves, open_loop) % % This function runs the CARFAC; that is, filters a 1 or more channel % sound input segment to make one or more neural activity patterns (naps); @@ -41,9 +43,8 @@ % interact easily. The inner loops are over filterbank channels, and % this level should be kept efficient. % -% See other functions for designing and characterizing the CARFAC: -% CF = CARFAC_Design(fs, CF_CAR_params, CF_AGC_params, n_ears) -% transfns = CARFAC_Transfer_Functions(CF, to_chans, from_chans) +% seg_ohc seg_agc are optional extra outputs useful for seeing what the +% ohc nonlinearity and agc are doing; both in terms of extra damping. if nargin < 3 open_loop = 0; @@ -65,12 +66,18 @@ naps = zeros(n_samp, n_ch, n_ears); % allocate space for result if do_BM BM = zeros(n_samp, n_ch, n_ears); + seg_ohc = zeros(n_samp, n_ch, n_ears); + seg_agc = zeros(n_samp, n_ch, n_ears); end detects = zeros(n_ch, n_ears); for k = 1:n_samp % at each time step, possibly handle multiple channels for ear = 1:n_ears + + % This would be cleaner if we could just get and use a reference to + % CF.ears(ear), but Matlab doesn't work that way... + [car_out, CF.ears(ear).CAR_state] = CARFAC_CAR_Step( ... input_waves(k, ear), CF.ears(ear).CAR_coeffs, CF.ears(ear).CAR_state); @@ -86,6 +93,9 @@ naps(k, :, ear) = ihc_out; % output to neural activity pattern if do_BM BM(k, :, ear) = car_out; + state = CF.ears(ear).CAR_state; + seg_ohc(k, :, ear) = state.zA_memory; + seg_agc(k, :, ear) = state.zB_memory;; end end
--- a/trunk/matlab/bmm/carfac/CARFAC_hacking.m Tue May 01 23:32:24 2012 +0000 +++ b/trunk/matlab/bmm/carfac/CARFAC_hacking.m Sat May 12 04:31:59 2012 +0000 @@ -26,29 +26,37 @@ if use_plan_file file_signal = wavread('plan.wav'); - file_signal = file_signal(8100+(1:20000)); % trim for a faster test + % file_signal = file_signal(8100+(1:20000)); % trim for a faster test + file_signal = file_signal(10000+(1:10000)); % trim for a faster test else - flist = [1000]; - alist = [1]; - flist = 1000; - alist = 1; - sine_signal = 0; - times = (0:19999)' / 22050; - for fno = 1:length(flist) - sine_signal = sine_signal + alist(fno)*sin(flist(fno)*2*pi*times); - end - growth_power = 0; % use 0 for flat, 4 or more for near exponential - file_signal = 1.0 * (sine_signal .* (times/max(times)).^growth_power); + flist = [1000]; + alist = [1]; + flist = 1000; + alist = 1; + sine_signal = 0; + times = (0:19999)' / 22050; + for fno = 1:length(flist) + sine_signal = sine_signal + alist(fno)*sin(flist(fno)*2*pi*times); + end + growth_power = 0; % use 0 for flat, 4 or more for near exponential + file_signal = 1.0 * (sine_signal .* (times/max(times)).^growth_power); end % repeat with negated signal to compare responses: % file_signal = [file_signal; -file_signal]; % 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:60 +do_distortion_figs = 0; % use 1 for distortion figure hack.... +if do_distortion_figs + dB_list = -40:20:0 +else + dB_list = -80:20:60 +end +% dB = dB_list(1); +% test_signal = 10^(dB/20)* file_signal(1:4000) % lead-in []; +test_signal = []; +for dB = dB_list test_signal = [test_signal; file_signal * 10^(dB/20)]; end @@ -57,28 +65,28 @@ agc_plot_fig_num = 6; -for n_ears = 1:2 +for n_ears = 1 % 1:2 CF_struct = CARFAC_Design(n_ears); % default design - + 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); - - [CF_struct, nap_decim, nap, BM] = CARFAC_Run(CF_struct, test_signal, ... + + [CF_struct, nap_decim, nap, BM, ohc, agc] = CARFAC_Run(CF_struct, test_signal, ... agc_plot_fig_num); - -% nap = deskew(nap); % deskew doesn't make much difference - -% 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)); - + + % nap = deskew(nap); % deskew doesn't make much difference + + % dB_BM = 10/log(10) * log(filter(1, [1, -0.995], BM(:, 20:50, :).^2)); + dB_BM = 10/log(10) * log(filter(1, [1, -0.995], BM(:, :, :).^2)); + % only ear 1: MultiScaleSmooth(dB_BM(5000:200:end, :, 1), 1); - + % Display results for 1 or 2 ears: for ear = 1:n_ears smooth_nap = nap_decim(:, :, ear); @@ -90,13 +98,59 @@ title('smooth nap from nap decim') colormap(1 - gray); end - + % Show resulting data, even though M-Lint complains: CF_struct - CF_struct.CAR_state - CF_struct.AGC_state + CF_struct.ears(1).CAR_state + CF_struct.ears(1).AGC_state min_max_decim = [min(nap_decim(:)), max(nap_decim(:))] - + + %% + if do_distortion_figs + channels = [38, 39, 40]; + times = 0000 + (3200:3599); + smoothed_ohc = ohc; + epsi = 0.4; + % smoothed_ohc = filter(epsi, [1, -(1-epsi)], smoothed_ohc); + % smoothed_ohc = filter(epsi, [1, -(1-epsi)], smoothed_ohc); + + figure(101); hold off + plot(smoothed_ohc(times, channels)) + hold on + plot(smoothed_ohc(times, channels(2)), 'k-', 'LineWidth', 1.5) + title('OHC') + + figure(105); hold off + plot(agc(times, channels)) + hold on + plot(agc(times, channels(2)), 'k-', 'LineWidth', 1.5) + title('AGC') + + figure(103); hold off + plot(BM(times, channels)) + hold on + plot(BM(times, channels(2)), 'k-', 'LineWidth', 1.5) + title('BM') + + extra_damping = smoothed_ohc + agc; + figure(102); hold off + plot(extra_damping(times, channels)) + hold on + plot(extra_damping(times, channels(2)), 'k-', 'LineWidth', 1.5) + title('extra damping') + + distortion = -(extra_damping - smooth1d(extra_damping, 10)) .* BM; + distortion = filter(epsi, [1, -(1-epsi)], distortion); + distortion = filter(epsi, [1, -(1-epsi)], distortion); + % distortion = filter(epsi, [1, -(1-epsi)], distortion); + figure(104); hold off + plot(distortion(times, channels)) + hold on + plot(distortion(times, channels(2)), 'k-', 'LineWidth', 1.5) + title('distortion') + + end + %% end % Expected result: Figure 3 looks like figure 2, a tiny bit darker.