Mercurial > hg > aimc
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 |