dicklyon@604: % Copyright 2013, Google, Inc. dicklyon@604: % Author: Richard F. Lyon dicklyon@604: % dicklyon@604: % This Matlab file is part of an implementation of Lyon's cochlear model: dicklyon@604: % "Cascade of Asymmetric Resonators with Fast-Acting Compression" dicklyon@604: % to supplement Lyon's upcoming book "Human and Machine Hearing" dicklyon@604: % dicklyon@604: % Licensed under the Apache License, Version 2.0 (the "License"); dicklyon@604: % you may not use this file except in compliance with the License. dicklyon@604: % You may obtain a copy of the License at dicklyon@604: % dicklyon@604: % http://www.apache.org/licenses/LICENSE-2.0 dicklyon@604: % dicklyon@604: % Unless required by applicable law or agreed to in writing, software dicklyon@604: % distributed under the License is distributed on an "AS IS" BASIS, dicklyon@604: % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. dicklyon@604: % See the License for the specific language governing permissions and dicklyon@604: % limitations under the License. dicklyon@604: ronw@634: function [frame_rate, num_frames] = SAI_Run(CF, input_waves) ronw@634: % function [CF, SAI_movie] = SAI_Run(CF, input_waves) ronw@634: % This function runs the CARFAC and display an SAI movie. dicklyon@604: dicklyon@604: n_ch = CF.n_ch; dicklyon@604: [n_samp, n_ears] = size(input_waves); dicklyon@604: if n_ears ~= CF.n_ears dicklyon@604: error('bad number of input_waves channels passed to CARFAC_Run') dicklyon@604: end dicklyon@604: fs = CF.fs; dicklyon@604: dicklyon@623: seglen = round(fs / 30); % Pick about 30 fps dicklyon@623: frame_rate = fs / seglen; dicklyon@604: n_segs = ceil(n_samp / seglen); dicklyon@604: ronw@634: % Design the SAI parameters. ronw@638: sai_struct.width = 256; ronw@638: sai_struct.future_lags = sai_struct.width / 2; ronw@634: sai_struct.window_width = seglen; ronw@634: n_triggers = 2; ronw@634: sai_struct.n_window_pos = n_triggers; ronw@634: sai_struct.channel_smoothing_scale = 0; dicklyon@604: dicklyon@608: ronw@634: % State stored in sai_struct. ronw@634: % Make the history buffer. ronw@634: buffer_width = sai_struct.width + ... ronw@634: floor((1 + (n_triggers - 1)/2) * sai_struct.window_width); ronw@634: sai_struct.nap_buffer = zeros(buffer_width, n_ch); ronw@634: % The SAI frame is transposed to be image-like. ronw@634: sai_struct.frame = zeros(n_ch, sai_struct.width); dicklyon@623: dicklyon@604: for seg_num = 1:n_segs ronw@634: % seg_range is the range of input sample indices for this segment dicklyon@604: if seg_num == n_segs dicklyon@604: % The last segment may be short of seglen, but do it anyway: ronw@634: seg_range = (seglen*(seg_num - 1) + 1):n_samp; dicklyon@604: else ronw@634: seg_range = seglen*(seg_num - 1) + (1:seglen); dicklyon@604: end ronw@634: % NOTE: seg_naps might have multiple channels. ronw@634: [seg_naps, CF] = CARFAC_Run_Segment(CF, input_waves(seg_range, :)); ronw@634: ronw@634: % Rectify. ronw@634: % NOTE: This might not be necessary. ronw@634: seg_naps = max(0, seg_naps); ronw@634: dicklyon@604: if seg_num == n_segs % pad out the last result dicklyon@604: seg_naps = [seg_naps; zeros(seglen - size(seg_naps,1), size(seg_naps, 2))]; dicklyon@604: end dicklyon@604: ronw@634: % Shift new data into the buffer. ronw@634: n_shift = size(seg_naps, 1); ronw@634: sai_struct.nap_buffer = [sai_struct.nap_buffer((1 + n_shift):end,:); seg_naps]; dicklyon@604: ronw@634: sai_struct = SAI_StabilizeLayer(sai_struct); dicklyon@623: dicklyon@604: cmap = 1 - gray; % jet dicklyon@604: figure(10) ronw@634: image(32 * sai_struct.frame); dicklyon@604: colormap(cmap); ronw@634: colorbar dicklyon@604: dicklyon@604: drawnow ronw@634: % imwrite(32*display_frame, cmap, sprintf('frames/frame%05d.png', seg_num)); dicklyon@604: end dicklyon@604: dicklyon@604: num_frames = seg_num; dicklyon@604: dicklyon@604: return