changeset 619:2e456754fe20

Better functionization of SAI, and new way to make picture with lag marginal and smoothed history of lag marginal.
author dicklyon@google.com
date Mon, 13 May 2013 21:15:56 +0000
parents e01caec17186
children 9c268a806bf2
files trunk/matlab/bmm/carfac/MakeMovieFromPngsAndWav.m trunk/matlab/bmm/carfac/SAI_BlendFrameIntoComposite.m trunk/matlab/bmm/carfac/SAI_DesignLayers.m trunk/matlab/bmm/carfac/SAI_RunLayered.m trunk/matlab/bmm/carfac/SAI_StabilizeLayer.m trunk/matlab/bmm/carfac/SAI_UpdateBuffers.m
diffstat 6 files changed, 96 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/matlab/bmm/carfac/MakeMovieFromPngsAndWav.m	Fri May 10 20:12:49 2013 +0000
+++ b/trunk/matlab/bmm/carfac/MakeMovieFromPngsAndWav.m	Mon May 13 21:15:56 2013 +0000
@@ -20,7 +20,7 @@
 function MakeMovieFromPngsAndWav(frame_rate, png_name_pattern, ...
   wav_filename, out_filename)
 
-system(['rm ', out_filename]);
+system(['rm "', out_filename, '"']);
 
 if ~exist(wav_filename, 'file')
   error('wave file is missing', wav_filename)
@@ -29,8 +29,8 @@
 ffmpeg_command = ['/opt/local/bin/ffmpeg' ...
   ' -r ' num2str(frame_rate) ...
   ' -i ' png_name_pattern ...
-  ' -i ' wav_filename ...
-  ' -b:v 1024k' ...
-  ' ' out_filename];
+  ' -i "' wav_filename ...
+  '" -b:v 1024k' ...
+  ' "' out_filename '"'];
 
 system(ffmpeg_command);
--- a/trunk/matlab/bmm/carfac/SAI_BlendFrameIntoComposite.m	Fri May 10 20:12:49 2013 +0000
+++ b/trunk/matlab/bmm/carfac/SAI_BlendFrameIntoComposite.m	Mon May 13 21:15:56 2013 +0000
@@ -17,9 +17,10 @@
 % See the License for the specific language governing permissions and
 % limitations under the License.
 
-function composite_frame = SAI_BlendFrameIntoComposite(new_frame, ...
+function composite_frame = SAI_BlendFrameIntoComposite( ...
   layer_struct, composite_frame)
 
+new_frame = layer_struct.frame;
 alpha = layer_struct.alpha;
 lag_curve = layer_struct.lag_curve;
 target_columns = layer_struct.target_indices;
--- a/trunk/matlab/bmm/carfac/SAI_DesignLayers.m	Fri May 10 20:12:49 2013 +0000
+++ b/trunk/matlab/bmm/carfac/SAI_DesignLayers.m	Mon May 13 21:15:56 2013 +0000
@@ -49,15 +49,15 @@
 if nargin < 2
   width_per_layer = 32;  % resolution "half life" in space
 end
-future_lags = 3 * width_per_layer;
-width_first_layer = future_lags + 2 * width_per_layer;
+future_lags = 4 * width_per_layer;
+width_first_layer = future_lags + 1 * width_per_layer;
 width_extra_last_layer = 2 * width_per_layer;
 left_overlap = 15;
 right_overlap = 15;
 first_window_width = 400;  % or maybe use seglen?  or 0.020 * fs?
-min_window_width = 2*width_per_layer;  % or somewhere on that order
+min_window_width = 1*width_per_layer;  % or somewhere on that order
 window_exponent = 1.4;
-alpha_max = 0.5;
+alpha_max = 1; 
 
 % Start with NAP_samples_per_SAI_sample, declining to 1 from here:
 max_samples_per = 2^(n_layers - 1);
@@ -121,6 +121,9 @@
   layer_array(layer).alpha = alpha * alpha_max;
   
   offset = offset + width;  % total width from left through this layer.
+  
+  % Smooth across channels a little before picking triggers:
+  layer_array(layer).channel_smoothing_scale = 0.25*(layer-1);
 end
 total_width = offset;  % Return size of SAI this will make.
 
@@ -165,8 +168,9 @@
   % location in the range of the window to a fixed location.  Assume
   % using two window placements overlapped 50%.
   n_triggers = 2;
+  layer_array(layer).n_window_pos = n_triggers;
   layer_array(layer).buffer_width = layer_array(layer).frame_width + ...
-    ceil((1 + (n_triggers - 1)/2) * layer_array(layer).window_width);
+    floor((1 + (n_triggers - 1)/2) * layer_array(layer).window_width);
 end
 
 return
--- a/trunk/matlab/bmm/carfac/SAI_RunLayered.m	Fri May 10 20:12:49 2013 +0000
+++ b/trunk/matlab/bmm/carfac/SAI_RunLayered.m	Mon May 13 21:15:56 2013 +0000
@@ -41,7 +41,7 @@
 % Make the composite SAI image array.
 composite_frame = zeros(n_ch, total_width);
 
-seglen = round(fs * 0.020);  % Pick about 20 ms segments
+seglen = round(fs / 30);  % Pick about 60 fps
 frame_rate = fs / seglen;
 n_segs = ceil(n_samp / seglen);
 
@@ -49,8 +49,14 @@
 for layer = 1:n_layers
   layer_array(layer).nap_buffer = zeros(layer_array(layer).buffer_width, n_ch);
   layer_array(layer).nap_fraction = 0;  % leftover fraction to shift in.
+  % The SAI frame is transposed to be image-like.
+  layer_array(layer).frame = zeros(n_ch, layer_array(layer).frame_width);
 end
 
+n_marginal_rows = 34;
+marginals = [];
+
+average_frame = 0;
 for seg_num = 1:n_segs
   % k_range is the range of input sample indices for this segment
   if seg_num == n_segs
@@ -75,69 +81,36 @@
   for layer = n_layers:-1:1  % blend from coarse to fine
     update_interval = layer_array(layer).update_interval;
     if 0 == mod(seg_num, update_interval)
-      nap_buffer = real(layer_array(layer).nap_buffer);
-      n_buffer_times = size(nap_buffer, 1);
-      width = layer_array(layer).frame_width;  % To render linear SAI to.
-      new_frame = zeros(n_ch, width);
-      
-      % Make the window to use for all the channels at this layer.
-      layer_factor = 1.5;
-      window_size = layer_array(layer).window_width;
-      after_samples = layer_array(layer).future_lags;
-
-      window_range = (1:window_size) + ...
-        (n_buffer_times - window_size) - after_samples;
-      window = sin((1:window_size)' * pi / window_size);
-      % This should not go negative!
-      offset_range = (1:width) + ...
-        (n_buffer_times - width - window_size);
-      % CHECK
-      if any(offset_range < 0)
-        error;
-      end
-      
-      % smooth across channels; more in later layers
-      smoothed_buffer =  smooth1d(nap_buffer', 0.25*(layer - 2))';
-      
-      % For each buffer column (channel), pick a trigger and align into SAI_frame
-      for ch = 1:n_ch
-        smooth_wave = smoothed_buffer(:, ch);  % for the trigger
-        
-        [peak_val, trigger_time] = max(smooth_wave(window_range) .* window);
-        nap_wave = nap_buffer(:, ch);  % for the waveform
-        if peak_val <= 0  % just use window center instead
-          [peak_val, trigger_time] = max(window);
-        end
-        if layer == n_layers  % mark the trigger points to display as imaginary.
-          layer_array(layer).nap_buffer(trigger_time + window_range(1) - 1, ch) = ...
-            layer_array(layer).nap_buffer(trigger_time + window_range(1) - 1, ch) + 1i;
-        end
-        new_frame(ch, :) = nap_wave(trigger_time + offset_range)';
-      end
-      composite_frame = SAI_BlendFrameIntoComposite(new_frame, ...
+      layer_array(layer) = SAI_StabilizeLayer(layer_array(layer));
+      new_frame = layer_array(layer).frame;
+      composite_frame = SAI_BlendFrameIntoComposite( ...
         layer_array(layer), composite_frame);
     end
   end
-  
-  
+ 
+  if isempty(marginals)
+    composite_width = size(composite_frame, 2);
+    marginals = zeros(n_marginal_rows, composite_width);
+  end
+  for row = n_marginal_rows:-1:11
+    % smooth from row above (lower number)
+    marginals(row, :) = marginals(row, :) + ...
+      2^((10 - row)/2) * (1.06*marginals(row - 1, :) - marginals(row, :));
+  end
   lag_marginal = mean(composite_frame, 1);  % means max out near 1 or 2
-  frame_bottom = zeros(size(composite_frame));  % will end up being 1/3
-  n_bottom_rows = size(frame_bottom, 1);
-  for height = 1:n_bottom_rows
-    big_ones = lag_marginal > 1*height/n_bottom_rows;
-    frame_bottom(n_bottom_rows - height + 1, big_ones) = 2;  % 2 for black
+  for row = 10:-1:1
+    marginals(row, :) = (lag_marginal - smooth1d(lag_marginal, 30)') - ...
+      (10 - row) / 40;
   end
     
   if 0 == mod(seg_num, update_interval) || seg_num == 1
     coc_gram = layer_array(end).nap_buffer';
     [n_ch, n_width] = size(composite_frame);
     coc_gram = [coc_gram, zeros(n_ch, n_width - size(coc_gram, 2))];
-    trigger_gram = 2 * (imag(coc_gram) ~= 0);
-    coc_gram = real(coc_gram);
   end
   
-  display_frame = [coc_gram; trigger_gram; ...
-    composite_frame(floor(1:0.5:end), :); frame_bottom];
+  display_frame = [coc_gram; ...
+    composite_frame(floor(1:0.5:end), :); 20*max(0,marginals)];
   
   cmap = jet;
   cmap = 1 - gray;  % jet
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/matlab/bmm/carfac/SAI_StabilizeLayer.m	Mon May 13 21:15:56 2013 +0000
@@ -0,0 +1,55 @@
+function layer_struct = SAI_StabilizeLayer(layer_struct)
+% Pick trigger points in buffer, shift rows to offset_from_end,
+% and blend into frame
+
+frame = layer_struct.frame;
+
+nap_buffer = real(layer_struct.nap_buffer);
+n_buffer_times = size(nap_buffer, 1);
+[n_ch, width] = size(frame);
+
+% Make the window to use for all the channels at this layer.
+window_size = layer_struct.window_width;
+n_window_pos = layer_struct.n_window_pos;
+% Windows are always (approx) 50% overlapped:
+d_win = window_size / 2;
+
+after_samples = layer_struct.future_lags;
+
+window_range = (1:window_size) + ...
+  (n_buffer_times - window_size) - after_samples - ...
+  floor((n_window_pos - 1) * d_win);
+window = sin((1:window_size)' * pi / window_size);
+% This should not go negative!
+offset_range = (1:width) + ...
+  (n_buffer_times - width - window_size) - floor((n_window_pos - 1) * d_win);
+% CHECK
+if any(offset_range < 0)
+  error;
+end
+
+% smooth across channels; more in later layers
+smoothed_buffer =  smooth1d(nap_buffer', layer_struct.channel_smoothing_scale)';
+
+% For each buffer column (channel), pick a trigger and align into SAI_frame
+for ch = 1:n_ch
+  smooth_wave = smoothed_buffer(:, ch);  % for the trigger
+  
+  % Do several window positions and triggers
+  for w = 1:n_window_pos
+    % move the window to later and go aggain
+    [peak_val, trigger_time] = max(smooth_wave(window_range + ...
+      floor((w - 1) * d_win)) .* window);
+    nap_wave = nap_buffer(:, ch);  % for the waveform
+    if peak_val <= 0  % just use window center instead
+      [peak_val, trigger_time] = max(window);
+    end
+    % TODO(dicklyon):  alpha blend here.
+    trigger_time = trigger_time + floor((w - 1) * d_win);
+    alpha = (0.025 + peak_val) / (0.5 + peak_val);  % alpha 0.05 to near 1.0
+    frame(ch, :) = alpha * nap_wave(trigger_time + offset_range)' + ...
+      (1 - alpha) * frame(ch, :);
+  end
+end
+
+layer_struct.frame = frame;
--- a/trunk/matlab/bmm/carfac/SAI_UpdateBuffers.m	Fri May 10 20:12:49 2013 +0000
+++ b/trunk/matlab/bmm/carfac/SAI_UpdateBuffers.m	Mon May 13 21:15:56 2013 +0000
@@ -37,7 +37,7 @@
 % Array of what to shift in to first or next layer.
 new_chunk = seg_naps;
 
-gain = 1.1;  % gain from layer to layer; could be layer dependent.
+gain = 1.05;  % gain from layer to layer; could be layer dependent.
 
 %% 
 % Decimate using a 2-3-4-filter and partial differencing emphasize onsets: