comparison trunk/matlab/bmm/carfac/CARFAC_Design.m @ 561:3dff17554c6d

add an ears array level everywhere
author dicklyon@google.com
date Mon, 23 Apr 2012 22:58:40 +0000
parents ab7fabe2af5d
children fb602edc2d55
comparison
equal deleted inserted replaced
560:ab7fabe2af5d 561:3dff17554c6d
15 % distributed under the License is distributed on an "AS IS" BASIS, 15 % distributed under the License is distributed on an "AS IS" BASIS,
16 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 % See the License for the specific language governing permissions and 17 % See the License for the specific language governing permissions and
18 % limitations under the License. 18 % limitations under the License.
19 19
20 function CF = CARFAC_Design(fs, CF_CAR_params, CF_AGC_params, CF_IHC_params) 20 function CF = CARFAC_Design(n_ears, fs, CF_CAR_params, CF_AGC_params, CF_IHC_params)
21 % function CF = CARFAC_Design(fs, CF_CAR_params, ... 21 % function CF = CARFAC_Design(fs, CF_CAR_params, ...
22 % CF_AGC_params, ERB_break_freq, ERB_Q, CF_IHC_params) 22 % CF_AGC_params, ERB_break_freq, ERB_Q, CF_IHC_params)
23 % 23 %
24 % This function designs the CARFAC (Cascade of Asymmetric Resonators with 24 % This function designs the CARFAC (Cascade of Asymmetric Resonators with
25 % Fast-Acting Compression); that is, it take bundles of parameters and 25 % Fast-Acting Compression); that is, it take bundles of parameters and
39 % ERB_Q = 1000/(24.7*4.37); % 9.2645 39 % ERB_Q = 1000/(24.7*4.37); % 9.2645
40 % 40 %
41 % All args are defaultable; for sample/default args see the code; they 41 % All args are defaultable; for sample/default args see the code; they
42 % make 96 channels at default fs = 22050, 114 channels at 44100. 42 % make 96 channels at default fs = 22050, 114 channels at 44100.
43 43
44 if nargin < 1
45 n_ears = 1; % if more than 1, make them identical channels;
46 % then modify the design if necessary for different reasons
47 end
48
49 if nargin < 2
50 fs = 22050;
51 end
52
53 if nargin < 3
54 CF_CAR_params = struct( ...
55 'velocity_scale', 0.2, ... % for the "cubic" velocity nonlinearity
56 'v_offset', 0.01, ... % offset gives a quadratic part
57 'v2_corner', 0.2, ... % corner for essential nonlin
58 'v_damp_max', 0.01, ... % damping delta damping from velocity nonlin
59 'min_zeta', 0.10, ... % minimum damping factor in mid-freq channels
60 'first_pole_theta', 0.85*pi, ...
61 'zero_ratio', sqrt(2), ... % how far zero is above pole
62 'high_f_damping_compression', 0.5, ... % 0 to 1 to compress zeta
63 'ERB_per_step', 0.5, ... % assume G&M's ERB formula
64 'min_pole_Hz', 30, ...
65 'ERB_break_freq', 165.3, ... % Greenwood map's break freq.
66 'ERB_Q', 1000/(24.7*4.37)); % Glasberg and Moore's high-cf ratio
67 end
68
44 if nargin < 4 69 if nargin < 4
70 CF_AGC_params = struct( ...
71 'n_stages', 4, ...
72 'time_constants', [1, 4, 16, 64]*0.002, ...
73 'AGC_stage_gain', 2, ... % gain from each stage to next slower stage
74 'decimation', [8, 2, 2, 2], ... % how often to update the AGC states
75 'AGC1_scales', [1.0, 1.4, 2.0, 2.8], ... % in units of channels
76 'AGC2_scales', [1.6, 2.25, 3.2, 4.5], ... % spread more toward base
77 'detect_scale', 0.25, ... % the desired damping range
78 'AGC_mix_coeff', 0.5);
79 end
80
81 if nargin < 5
45 % HACK: these constant control the defaults 82 % HACK: these constant control the defaults
46 one_cap = 0; % bool; 0 for new two-cap hack 83 one_cap = 0; % bool; 0 for new two-cap hack
47 just_hwr = 0; % book; 0 for normal/fancy IHC; 1 for HWR 84 just_hwr = 0; % book; 0 for normal/fancy IHC; 1 for HWR
48 if just_hwr 85 if just_hwr
49 CF_IHC_params = struct('just_hwr', 1); % just a simple HWR 86 CF_IHC_params = struct('just_hwr', 1); % just a simple HWR
66 'tau2_in', 0.005 ); % recovery tau is slower 103 'tau2_in', 0.005 ); % recovery tau is slower
67 end 104 end
68 end 105 end
69 end 106 end
70 107
71 if nargin < 3 108
72 CF_AGC_params = struct( ...
73 'n_stages', 4, ...
74 'time_constants', [1, 4, 16, 64]*0.002, ...
75 'AGC_stage_gain', 2, ... % gain from each stage to next slower stage
76 'decimation', [8, 2, 2, 2], ... % how often to update the AGC states
77 'AGC1_scales', [1.0, 1.4, 2.0, 2.8], ... % in units of channels
78 'AGC2_scales', [1.6, 2.25, 3.2, 4.5], ... % spread more toward base
79 'detect_scale', 0.25, ... % the desired damping range
80 'AGC_mix_coeff', 0.5);
81 end
82
83 if nargin < 2
84 CF_CAR_params = struct( ...
85 'velocity_scale', 0.2, ... % for the "cubic" velocity nonlinearity
86 'v_offset', 0.01, ... % offset gives a quadratic part
87 'v2_corner', 0.2, ... % corner for essential nonlin
88 'v_damp_max', 0.01, ... % damping delta damping from velocity nonlin
89 'min_zeta', 0.10, ... % minimum damping factor in mid-freq channels
90 'first_pole_theta', 0.85*pi, ...
91 'zero_ratio', sqrt(2), ... % how far zero is above pole
92 'high_f_damping_compression', 0.5, ... % 0 to 1 to compress zeta
93 'ERB_per_step', 0.5, ... % assume G&M's ERB formula
94 'min_pole_Hz', 30, ...
95 'ERB_break_freq', 165.3, ... % Greenwood map's break freq.
96 'ERB_Q', 1000/(24.7*4.37)); % Glasberg and Moore's high-cf ratio
97 end
98
99 if nargin < 1
100 fs = 22050;
101 end
102 109
103 % first figure out how many filter stages (PZFC/CARFAC channels): 110 % first figure out how many filter stages (PZFC/CARFAC channels):
104 pole_Hz = CF_CAR_params.first_pole_theta * fs / (2*pi); 111 pole_Hz = CF_CAR_params.first_pole_theta * fs / (2*pi);
105 n_ch = 0; 112 n_ch = 0;
106 while pole_Hz > CF_CAR_params.min_pole_Hz 113 while pole_Hz > CF_CAR_params.min_pole_Hz
119 end 126 end
120 % now we have n_ch, the number of channels, and pole_freqs array 127 % now we have n_ch, the number of channels, and pole_freqs array
121 128
122 max_channels_per_octave = log(2) / log(pole_freqs(1)/pole_freqs(2)); 129 max_channels_per_octave = log(2) / log(pole_freqs(1)/pole_freqs(2));
123 130
131 % convert to include an ear_array, each w coeffs and state...
132 CAR_coeffs = CARFAC_DesignFilters(CF_CAR_params, fs, pole_freqs);
133 AGC_coeffs = CARFAC_DesignAGC(CF_AGC_params, fs, n_ch);
134 IHC_coeffs = CARFAC_DesignIHC(CF_IHC_params, fs, n_ch);
135 % copy same designed coeffs into each ear (can do differently in the
136 % future:
137 for ear = 1:n_ears
138 ears(ear).CAR_coeffs = CAR_coeffs;
139 ears(ear).AGC_coeffs = AGC_coeffs;
140 ears(ear).IHC_coeffs = IHC_coeffs;
141 end
142
124 CF = struct( ... 143 CF = struct( ...
125 'fs', fs, ... 144 'fs', fs, ...
126 'max_channels_per_octave', max_channels_per_octave, ... 145 'max_channels_per_octave', max_channels_per_octave, ...
127 'CAR_params', CF_CAR_params, ... 146 'CAR_params', CF_CAR_params, ...
128 'AGC_params', CF_AGC_params, ... 147 'AGC_params', CF_AGC_params, ...
129 'IHC_params', CF_IHC_params, ... 148 'IHC_params', CF_IHC_params, ...
130 'n_ch', n_ch, ... 149 'n_ch', n_ch, ...
131 'pole_freqs', pole_freqs, ... 150 'pole_freqs', pole_freqs, ...
132 'CAR_coeffs', CARFAC_DesignFilters(CF_CAR_params, fs, pole_freqs), ... 151 'ears', ears, ...
133 'AGC_coeffs', CARFAC_DesignAGC(CF_AGC_params, fs, n_ch), ... 152 'n_ears', n_ears );
134 'IHC_coeffs', CARFAC_DesignIHC(CF_IHC_params, fs, n_ch), ...
135 'n_ears', 0 );
136 153
137 154
138 155
139 %% Design the filter coeffs: 156 %% Design the filter coeffs:
140 function CAR_coeffs = CARFAC_DesignFilters(CAR_params, fs, pole_freqs) 157 function CAR_coeffs = CARFAC_DesignFilters(CAR_params, fs, pole_freqs)
236 % response as a distribution to be convolved ntimes: 253 % response as a distribution to be convolved ntimes:
237 % TODO (dicklyon): specify spread and delay instead of scales??? 254 % TODO (dicklyon): specify spread and delay instead of scales???
238 delay = (AGC2_scales(stage) - AGC1_scales(stage)) / ntimes; 255 delay = (AGC2_scales(stage) - AGC1_scales(stage)) / ntimes;
239 spread_sq = (AGC1_scales(stage)^2 + AGC2_scales(stage)^2) / ntimes; 256 spread_sq = (AGC1_scales(stage)^2 + AGC2_scales(stage)^2) / ntimes;
240 257
241 % get pole positions to better match intended spread and delay of 258 % get pole positions to better match intended spread and delay of
242 % [[geometric distribution]] in each direction (see wikipedia) 259 % [[geometric distribution]] in each direction (see wikipedia)
243 u = 1 + 1 / spread_sq; % these are based on off-line algebra hacking. 260 u = 1 + 1 / spread_sq; % these are based on off-line algebra hacking.
244 p = u - sqrt(u^2 - 1); % pole that would give spread if used twice. 261 p = u - sqrt(u^2 - 1); % pole that would give spread if used twice.
245 dp = delay * (1 - 2*p +p^2)/2; 262 dp = delay * (1 - 2*p +p^2)/2;
246 polez1 = p - dp; 263 polez1 = p - dp;
331 348
332 %% the IHC design coeffs: 349 %% the IHC design coeffs:
333 function IHC_coeffs = CARFAC_DesignIHC(IHC_params, fs, n_ch) 350 function IHC_coeffs = CARFAC_DesignIHC(IHC_params, fs, n_ch)
334 351
335 if IHC_params.just_hwr 352 if IHC_params.just_hwr
336 IHC_coeffs = struct( ... 353 IHC_coeffs = struct( ...
337 'n_ch', n_ch, ... 354 'n_ch', n_ch, ...
338 'just_hwr', 1); 355 'just_hwr', 1);
339 else 356 else
340 if IHC_params.one_cap 357 if IHC_params.one_cap
341 ro = 1 / CARFAC_Detect(2); % output resistance 358 ro = 1 / CARFAC_Detect(2); % output resistance
342 c = IHC_params.tau_out / ro; 359 c = IHC_params.tau_out / ro;
343 ri = IHC_params.tau_in / c; 360 ri = IHC_params.tau_in / c;
360 % one-channel state for testing/verification: 377 % one-channel state for testing/verification:
361 IHC_state = struct( ... 378 IHC_state = struct( ...
362 'cap_voltage', IHC_coeffs.rest_cap, ... 379 'cap_voltage', IHC_coeffs.rest_cap, ...
363 'lpf1_state', 0, ... 380 'lpf1_state', 0, ...
364 'lpf2_state', 0, ... 381 'lpf2_state', 0, ...
365 'ihc_accum', 0); 382 'ihc_accum', 0);
366 else 383 else
367 ro = 1 / CARFAC_Detect(2); % output resistance 384 ro = 1 / CARFAC_Detect(2); % output resistance
368 c2 = IHC_params.tau2_out / ro; 385 c2 = IHC_params.tau2_out / ro;
369 r2 = IHC_params.tau2_in / c2; 386 r2 = IHC_params.tau2_in / c2;
370 c1 = IHC_params.tau1_out / r2; 387 c1 = IHC_params.tau1_out / r2;
408 % CF.CAR_params 425 % CF.CAR_params
409 % CF.AGC_params 426 % CF.AGC_params
410 % CF.CAR_coeffs 427 % CF.CAR_coeffs
411 % CF.AGC_coeffs 428 % CF.AGC_coeffs
412 % CF.IHC_coeffs 429 % CF.IHC_coeffs
413 % CF = 430 % CF =
414 % fs: 22050 431 % fs: 22050
415 % max_channels_per_octave: 12.2709 432 % max_channels_per_octave: 12.2709
416 % CAR_params: [1x1 struct] 433 % CAR_params: [1x1 struct]
417 % AGC_params: [1x1 struct] 434 % AGC_params: [1x1 struct]
418 % IHC_params: [1x1 struct] 435 % IHC_params: [1x1 struct]
420 % pole_freqs: [71x1 double] 437 % pole_freqs: [71x1 double]
421 % CAR_coeffs: [1x1 struct] 438 % CAR_coeffs: [1x1 struct]
422 % AGC_coeffs: [1x1 struct] 439 % AGC_coeffs: [1x1 struct]
423 % IHC_coeffs: [1x1 struct] 440 % IHC_coeffs: [1x1 struct]
424 % n_ears: 0 441 % n_ears: 0
425 % ans = 442 % ans =
426 % velocity_scale: 0.2000 443 % velocity_scale: 0.2000
427 % v_offset: 0.0100 444 % v_offset: 0.0100
428 % v2_corner: 0.2000 445 % v2_corner: 0.2000
429 % v_damp_max: 0.0100 446 % v_damp_max: 0.0100
430 % min_zeta: 0.1000 447 % min_zeta: 0.1000
433 % high_f_damping_compression: 0.5000 450 % high_f_damping_compression: 0.5000
434 % ERB_per_step: 0.5000 451 % ERB_per_step: 0.5000
435 % min_pole_Hz: 30 452 % min_pole_Hz: 30
436 % ERB_break_freq: 165.3000 453 % ERB_break_freq: 165.3000
437 % ERB_Q: 9.2645 454 % ERB_Q: 9.2645
438 % ans = 455 % ans =
439 % n_stages: 4 456 % n_stages: 4
440 % time_constants: [0.0020 0.0080 0.0320 0.1280] 457 % time_constants: [0.0020 0.0080 0.0320 0.1280]
441 % AGC_stage_gain: 2 458 % AGC_stage_gain: 2
442 % decimation: [8 2 2 2] 459 % decimation: [8 2 2 2]
443 % AGC1_scales: [1 1.4000 2 2.8000] 460 % AGC1_scales: [1 1.4000 2 2.8000]
444 % AGC2_scales: [1.6000 2.2500 3.2000 4.5000] 461 % AGC2_scales: [1.6000 2.2500 3.2000 4.5000]
445 % detect_scale: 0.2500 462 % detect_scale: 0.2500
446 % AGC_mix_coeff: 0.5000 463 % AGC_mix_coeff: 0.5000
447 % ans = 464 % ans =
448 % n_ch: 71 465 % n_ch: 71
449 % velocity_scale: 0.2000 466 % velocity_scale: 0.2000
450 % v_offset: 0.0100 467 % v_offset: 0.0100
451 % v2_corner: 0.2000 468 % v2_corner: 0.2000
452 % v_damp_max: 0.0100 469 % v_damp_max: 0.0100
454 % a0_coeffs: [71x1 double] 471 % a0_coeffs: [71x1 double]
455 % c0_coeffs: [71x1 double] 472 % c0_coeffs: [71x1 double]
456 % h_coeffs: [71x1 double] 473 % h_coeffs: [71x1 double]
457 % g0_coeffs: [71x1 double] 474 % g0_coeffs: [71x1 double]
458 % zr_coeffs: [71x1 double] 475 % zr_coeffs: [71x1 double]
459 % ans = 476 % ans =
460 % n_ch: 71 477 % n_ch: 71
461 % n_AGC_stages: 4 478 % n_AGC_stages: 4
462 % AGC_stage_gain: 2 479 % AGC_stage_gain: 2
463 % AGC_epsilon: [0.1659 0.0867 0.0443 0.0224] 480 % AGC_epsilon: [0.1659 0.0867 0.0443 0.0224]
464 % decimation: [8 2 2 2] 481 % decimation: [8 2 2 2]
468 % AGC_spatial_FIR: [3x4 double] 485 % AGC_spatial_FIR: [3x4 double]
469 % AGC_spatial_n_taps: [3 3 3 3] 486 % AGC_spatial_n_taps: [3 3 3 3]
470 % AGC_mix_coeffs: [0 0.0454 0.0227 0.0113] 487 % AGC_mix_coeffs: [0 0.0454 0.0227 0.0113]
471 % AGC_gain: 15 488 % AGC_gain: 15
472 % detect_scale: 0.0167 489 % detect_scale: 0.0167
473 % ans = 490 % ans =
474 % n_ch: 71 491 % n_ch: 71
475 % just_hwr: 0 492 % just_hwr: 0
476 % lpf_coeff: 0.4327 493 % lpf_coeff: 0.4327
477 % out1_rate: 0.0045 494 % out1_rate: 0.0045
478 % in1_rate: 0.0023 495 % in1_rate: 0.0023