tom@516
|
1 % Copyright 2012, Google, Inc.
|
tom@516
|
2 % Author: Richard F. Lyon
|
tom@516
|
3 %
|
tom@516
|
4 % This Matlab file is part of an implementation of Lyon's cochlear model:
|
tom@516
|
5 % "Cascade of Asymmetric Resonators with Fast-Acting Compression"
|
tom@516
|
6 % to supplement Lyon's upcoming book "Human and Machine Hearing"
|
tom@516
|
7 %
|
tom@516
|
8 % Licensed under the Apache License, Version 2.0 (the "License");
|
tom@516
|
9 % you may not use this file except in compliance with the License.
|
tom@516
|
10 % You may obtain a copy of the License at
|
tom@516
|
11 %
|
tom@516
|
12 % http://www.apache.org/licenses/LICENSE-2.0
|
tom@516
|
13 %
|
tom@516
|
14 % Unless required by applicable law or agreed to in writing, software
|
tom@516
|
15 % distributed under the License is distributed on an "AS IS" BASIS,
|
tom@516
|
16 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
tom@516
|
17 % See the License for the specific language governing permissions and
|
tom@516
|
18 % limitations under the License.
|
tom@516
|
19
|
dicklyon@517
|
20 function [sai_frame, sai_state, naps] = CARFAC_SAI(naps, k, sai_state, SAI_params)
|
dicklyon@517
|
21 % function sai = CARFAC_SAI(naps, k, sai_state, SAI_params)
|
tom@516
|
22 %
|
dicklyon@517
|
23 % Calculate the Stabilized Auditory Image from naps;
|
dicklyon@517
|
24 % I think this is a binaural SAI by Steven Ness
|
dicklyon@517
|
25 %
|
dicklyon@517
|
26 % k seems to be a time index; it's an incremental update of the images...
|
dicklyon@517
|
27 % but this doesn't sound like a proper incremental approach...
|
tom@516
|
28 %
|
tom@516
|
29
|
dicklyon@517
|
30 [n_samp, n_ch, n_mics] = size(naps);
|
tom@516
|
31
|
dicklyon@517
|
32 if nargin < 4
|
dicklyon@517
|
33 SAI_params = struct( ...
|
dicklyon@517
|
34 'frame_jump', 200, ...
|
dicklyon@517
|
35 'sai_width', 500, ...
|
dicklyon@517
|
36 'threshold_alpha', 0.99, ...
|
dicklyon@517
|
37 'threshold_jump_factor', 1.2, ...
|
dicklyon@517
|
38 'threshold_jump_offset', 0.1};
|
dicklyon@517
|
39 end
|
tom@516
|
40
|
dicklyon@517
|
41 threshold_alpha = SAI_params.threshold_alpha;
|
dicklyon@517
|
42 threshold_jump = SAI_params.threshold_jump_factor;
|
dicklyon@517
|
43 threshold_offset = SAI_params.threshold_jump_offset;
|
tom@516
|
44
|
dicklyon@517
|
45 sai2 = reshape(sai_state.sai, SAI_params.sai_width * n_ch, n_mics);
|
dicklyon@517
|
46 naps2 = reshape(naps, n_samp * n_ch, n_mics);
|
tom@516
|
47
|
dicklyon@517
|
48 for mic = 1:n_mics
|
dicklyon@517
|
49 data = naps(k, :, mic)';
|
dicklyon@517
|
50 above_threshold = (sai_state(mic).lastdata > ...
|
dicklyon@517
|
51 sai_state(mic).thresholds) & ...
|
dicklyon@517
|
52 (sai_state(mic).lastdata > data);
|
dicklyon@517
|
53 sai_state(mic).thresholds(above_threshold) = ...
|
dicklyon@517
|
54 data(above_threshold) * threshold_jump + threshold_offset;
|
dicklyon@517
|
55 sai_state(mic).thresholds(~above_threshold) = ...
|
dicklyon@517
|
56 sai_state(mic).thresholds(~above_threshold) * threshold_alpha;
|
dicklyon@517
|
57 sai_state(mic).lastdata = data;
|
dicklyon@517
|
58
|
dicklyon@517
|
59 % Update SAI image with strobe data.
|
dicklyon@517
|
60 othermic = 3 - mic;
|
dicklyon@517
|
61
|
dicklyon@517
|
62 % Channels that are above the threhsold
|
dicklyon@517
|
63 above_ch = find(above_threshold);
|
dicklyon@517
|
64
|
dicklyon@517
|
65 % If we are above the threshold, set the trigger index and reset the
|
dicklyon@517
|
66 % sai_index
|
dicklyon@517
|
67 sai_state(mic).trigger_index(above_ch) = k;
|
dicklyon@517
|
68 sai_state(mic).sai_index(above_ch) = 1;
|
dicklyon@517
|
69
|
dicklyon@517
|
70 % Copy the right data from the nap to the sai
|
dicklyon@517
|
71 chans = (1:n_ch)';
|
dicklyon@517
|
72 fromindices = sai_state(mic).trigger_index() + (chans - 1) * n_samp;
|
dicklyon@517
|
73 toindices = min((sai_state(mic).sai_index() + (chans - 1) * sai_params.sai_width), sai_params.sai_width * n_ch);
|
dicklyon@517
|
74 sai2(toindices,mic) = naps2(fromindices, othermic);
|
dicklyon@517
|
75
|
dicklyon@517
|
76 sai_state(mic).trigger_index(:) = sai_state(mic).trigger_index(:) + 1;
|
dicklyon@517
|
77 sai_state(mic).sai_index(:) = sai_state(mic).sai_index(:) + 1;
|
dicklyon@517
|
78 end
|
tom@516
|
79
|
tom@516
|
80
|
dicklyon@517
|
81 sai_frame = reshape(sai2,sai_params.sai_width,n_ch,n_mics);
|
dicklyon@517
|
82 sai_state.sai = sai; % probably this is not exactly what we want to store as state...
|
tom@516
|
83
|
tom@516
|
84
|