tomwalters@0: function out=adaptedspecgramdemo(y,Fs,t_min,t_max) tomwalters@0: %SPECGRAMDEMO Spectrogram Demo tomwalters@0: % SPECGRAMDEMO(y,Fs) displays a spectrogram of signal y, assuming tomwalters@0: % a sample rate of Fs Hz. If y is specified but Fs is not, tomwalters@0: % a sample rate of 1 Hz is assumed. If no input arguments tomwalters@0: % are supplied, y and Fs are taken from the default data file tomwalters@0: % "mtlb.mat." tomwalters@0: % tomwalters@0: % Context menus and context-sensitive help are enabled throughout tomwalters@0: % the GUI. Explore the visualization options by right-clicking tomwalters@0: % on various GUI items including the spectrogram, the colorbar, tomwalters@0: % etc. For example, the panner may be zoomed by dragging the tomwalters@0: % mouse on the left- and right-hand edges of the highlighted tomwalters@0: % zoom region. Right-clicking the highlighted zoom area brings tomwalters@0: % up a menu for focusing in on the zoom region, and provides tomwalters@0: % a link to context help. tomwalters@0: % tomwalters@0: % See also SPECGRAM, SPTOOL, FDATOOL. tomwalters@0: tomwalters@0: % Author: D. Orofino tomwalters@0: % Copyright 1988-2002 The MathWorks, Inc. tomwalters@0: % $orginal Revision: 1.11 $ $orginal Date: 2002/05/17 14:17:56 $ tomwalters@0: % tomwalters@0: % tomwalters@0: % adapted by Stefan Bleeck 5.3.2003 to give back the selected time. bleeck@3: % bleeck@gmail.com tomwalters@0: tomwalters@0: %%%%%%%%%%%%%%%%%%%%%%%%%% tomwalters@0: % inserted by S.Bleeck tomwalters@0: global tmin; tomwalters@0: global tmax; tomwalters@0: if nargin<4 tomwalters@0: t_max=length(y)/Fs; tomwalters@0: end tomwalters@0: if nargin<3 tomwalters@0: t_min=0; tomwalters@0: end tomwalters@0: tmin=0; tomwalters@0: tmax=length(y); tomwalters@0: %%%%%%%%%%%%%%%%%%%%%%%%%% tomwalters@0: tomwalters@0: if nargin<1, tomwalters@0: default_file = 'mtlb.mat'; tomwalters@0: fprintf(['Loading demo file (%s).\n\n'],default_file); tomwalters@0: s = load(default_file); tomwalters@0: y = s.mtlb; % default dataset tomwalters@0: Fs = s.Fs; tomwalters@0: elseif nargin<2, tomwalters@0: Fs=1; % default sample rate tomwalters@0: end tomwalters@0: tomwalters@0: create_gui(y,Fs,t_min,t_max); tomwalters@0: tomwalters@0: tomwalters@0: %%%%%%%%%%%%%%%%%%%%%%%%%% tomwalters@0: % inserted by S.Bleeck tomwalters@0: out.start=tmin/Fs; tomwalters@0: out.duration=tmax/Fs-tmin/Fs; tomwalters@0: %%%%%%%%%%%%%%%%%%%%%%%%%% tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function zoom_in(hco,eventStruct,hfig) tomwalters@0: tomwalters@0: if nargin<3, hfig=gcbf; end tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: % Get "pixel spacing" of image content tomwalters@0: im_xdata = get(ud.himage,'xdata'); tomwalters@0: im_dx = im_xdata(2)-im_xdata(1); tomwalters@0: tomwalters@0: % Get current axis limit tomwalters@0: xlim = get(ud.hax(1),'xlim'); tomwalters@0: xlim_ctr = sum(xlim)/2; tomwalters@0: dxlim = diff(xlim); tomwalters@0: tomwalters@0: % If current axis limits will only show 1 pixel width, tomwalters@0: % don't bother zooming in any further: tomwalters@0: if dxlim <= im_dx, return; end tomwalters@0: tomwalters@0: % Shrink limits 50% toward center of current limits: tomwalters@0: new_xlim = (xlim + xlim_ctr)/2; tomwalters@0: % Update the spectrogram and time slice axes: tomwalters@0: set(ud.hax(1),'xlim',new_xlim); % [1 3] xxxx tomwalters@0: tomwalters@0: % Update the thumbnail: tomwalters@0: set(ud.hthumb,'xdata',new_xlim([1 2 2 1 1])); tomwalters@0: tomwalters@0: % update the audio selection to be played tomwalters@0: set_audio_selection(hfig, new_xlim * ud.Fs); tomwalters@0: tomwalters@0: % Update zoom signal, if enabled: tomwalters@0: % xxx plot_signal_zoom(hfig); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function zoom_out(hco,eventStruct,hfig) tomwalters@0: tomwalters@0: % Zooming is relative to the current focus window tomwalters@0: % We will not zoom out beyond the current focus window tomwalters@0: tomwalters@0: if nargin<3, hfig=gcbf; end tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: % Get current spectrogram axis limit (= thumbnail limits) tomwalters@0: thumb_xlim = get(ud.hax(1),'xlim'); % thumb limits = spectrogram limits tomwalters@0: thumb_dx = diff(thumb_xlim); tomwalters@0: tomwalters@0: % If spectrogram axis limits >= focus window limits, tomwalters@0: % don't bother zooming out any further: tomwalters@0: hax_time = ud.hax(2); tomwalters@0: focus_xlim = get(hax_time,'xlim'); % = panner xlim tomwalters@0: focus_dx = focus_xlim(2)-focus_xlim(1); tomwalters@0: if thumb_dx >= focus_dx, return; end tomwalters@0: tomwalters@0: % Grow limits 50% away from center of current limits: tomwalters@0: new_xlim = thumb_xlim + [-thumb_dx thumb_dx]/2; tomwalters@0: if new_xlim(1)focus_xlim(2), new_xlim(2)=focus_xlim(2); end tomwalters@0: tomwalters@0: % Update the thumbnail: tomwalters@0: set(ud.hthumb,'xdata',new_xlim([1 2 2 1 1])); tomwalters@0: tomwalters@0: % Sync the spectrogram and time slice axes to the thumbnail: tomwalters@0: set(ud.hax(1),'xlim',new_xlim); % [1 3] xxxx tomwalters@0: tomwalters@0: % update the audio selection to be played tomwalters@0: set_audio_selection(hfig, new_xlim * ud.Fs); tomwalters@0: tomwalters@0: % Update zoom signal, if enabled: tomwalters@0: % xxx plot_signal_zoom(hfig); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function zoom_full(hco,eventStruct,hfig) tomwalters@0: tomwalters@0: if nargin<3, hfig=gcbf; end tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: focusTimeReset(hfig); % reset focus window to full extent tomwalters@0: tomwalters@0: % Get time range of full spectrogram tomwalters@0: im_xdata = get(ud.himage,'xdata'); tomwalters@0: tomwalters@0: % Grow limits 50% away from center of current limits: tomwalters@0: new_xlim(1)=im_xdata(1); tomwalters@0: new_xlim(2)=im_xdata(end); tomwalters@0: tomwalters@0: % Update the spectrogram and time slice axes: tomwalters@0: set(ud.hax([1 3]),'xlim',new_xlim); tomwalters@0: tomwalters@0: % Update the thumbnail: tomwalters@0: set(ud.hthumb,'xdata',new_xlim([1 2 2 1 1])); tomwalters@0: tomwalters@0: % update the audio selection to be played tomwalters@0: set_audio_selection(hfig, new_xlim * ud.Fs); tomwalters@0: tomwalters@0: % Update zoom signal, if enabled: tomwalters@0: % xxx plot_signal_zoom(hfig); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function top_plot_toggle tomwalters@0: tomwalters@0: % XXX UNUSED? tomwalters@0: tomwalters@0: hfig=gcbf; tomwalters@0: ud=get(hfig,'userdata'); tomwalters@0: tomwalters@0: if strcmp(ud.plot.top,'spectrogram_time_slice'), tomwalters@0: newMode='signal_zoom'; tomwalters@0: else tomwalters@0: newMode='spectrogram_time_slice'; tomwalters@0: end tomwalters@0: ud.plot.top=newMode; tomwalters@0: set(hfig,'userdata',ud); tomwalters@0: tomwalters@0: hax_tslice = ud.hax(3); tomwalters@0: tomwalters@0: if strcmp(newMode,'signal_zoom'), tomwalters@0: t = (0:length(ud.y)-1)/ud.Fs; tomwalters@0: set(ud.htslice_line,'xdata',t, 'ydata', ud.y); tomwalters@0: set(hax_tslice,'xlim',[0 max(t)],'ylimmode','auto'); tomwalters@0: else tomwalters@0: % xxx tomwalters@0: set(ud.htslice_line,'ydata', get_spec_tslice(hfig), ... tomwalters@0: 'xdata',ud.t); tomwalters@0: tomwalters@0: b = get(ud.himage,'cdata'); tomwalters@0: blim = [min(b(:)) max(b(:))]; tomwalters@0: spec_xlim = [0 max(ud.t)]; tomwalters@0: set(hax_tslice, 'xlim',spec_xlim, 'ylim',blim); tomwalters@0: end tomwalters@0: tomwalters@0: % Update the top plot (Time slice) tomwalters@0: %update_top_plot(hfig); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function left_plot_toggle tomwalters@0: % Define the newMode flag in ud.plot.left tomwalters@0: tomwalters@0: hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: if strcmp(ud.plot.left,'spectrogram_freq_slice'), tomwalters@0: newMode = 'signal_psd'; tomwalters@0: else tomwalters@0: newMode = 'spectrogram_freq_slice'; tomwalters@0: end tomwalters@0: ud.plot.left = newMode; tomwalters@0: set(hfig,'userdata',ud); tomwalters@0: tomwalters@0: % Update the left plot (Frequency slice and PSD) tomwalters@0: update_left_plot(hfig); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function set_crosshairs(hfig,x,y) tomwalters@0: tomwalters@0: % Get current point in axis ASAP: tomwalters@0: %hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: % Update cache tomwalters@0: ud.crosshair.xctr = x; tomwalters@0: if nargin == 3, tomwalters@0: ud.crosshair.yctr = y; tomwalters@0: else tomwalters@0: y = ud.crosshair.yctr; tomwalters@0: end tomwalters@0: set(hfig,'userdata',ud); tomwalters@0: tomwalters@0: % Update crosshairs tomwalters@0: set([ud.hspec_y ud.htime_y ud.htslice_y], 'xdata',[x x]); tomwalters@0: set([ud.hspec_x ud.hfreq_x], 'ydata',[y y]); tomwalters@0: tomwalters@0: % Update readouts tomwalters@0: update_time_readout(hfig); tomwalters@0: update_freq_readout(hfig); tomwalters@0: update_dB_readout(hfig); tomwalters@0: update_cmap_ptr(hfig); tomwalters@0: tomwalters@0: % For the VERTICAL and H/V crosshairs, tomwalters@0: % update the freq slice display: tomwalters@0: if strcmp(ud.plot.left,'spectrogram_freq_slice'), tomwalters@0: set(ud.hfreq_line,'xdata', get_spec_freq(hfig)); tomwalters@0: end tomwalters@0: tomwalters@0: % For the HORIZONTAL and H/V crosshairs, tomwalters@0: % update the time slice display: tomwalters@0: if strcmp(ud.plot.top,'spectrogram_time_slice'), tomwalters@0: set(ud.htslice_line,'ydata', get_spec_tslice(hfig)); tomwalters@0: end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function center_cross(hco,eventStruct) tomwalters@0: tomwalters@0: hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: % Determine center of spectrogram axis: tomwalters@0: xlim=get(ud.hax(1),'xlim'); tomwalters@0: ylim=get(ud.hax(1),'ylim'); tomwalters@0: tomwalters@0: set_crosshairs(hfig,mean(xlim),mean(ylim)); tomwalters@0: update_cmap_ptr(hfig); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbmotion_thumb(hco,eventStruct) tomwalters@0: % thumbnail motion tomwalters@0: tomwalters@0: % Get current point in axis ASAP: tomwalters@0: hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax = ud.hax(2); tomwalters@0: cp = get(hax,'currentpoint'); tomwalters@0: curr_x = cp(1,1); tomwalters@0: tomwalters@0: xdata = get(ud.hthumb,'xdata'); tomwalters@0: xmotion = curr_x - ud.thumb.origPt; tomwalters@0: width = ud.thumb.width; tomwalters@0: xdata = ud.thumb.xdata + xmotion; tomwalters@0: tomwalters@0: % Constrain to axis limits, so we don't lose cursor: tomwalters@0: xlim=get(hax,'xlim'); tomwalters@0: min_xdata = min(xdata); tomwalters@0: max_xdata = max(xdata); tomwalters@0: if min_xdata < xlim(1), tomwalters@0: xdata=[xlim(1) xlim([1 1])+width xlim([1 1])]; tomwalters@0: elseif max_xdata > xlim(2), tomwalters@0: xdata = [xlim(2)-width xlim([2 2]) xlim([2 2])-width]; tomwalters@0: end tomwalters@0: tomwalters@0: % If the patch is larger than the zoom window tomwalters@0: if min(xdata)<=xlim(1) & max(xdata)>=xlim(2), tomwalters@0: % error('wbmotion_thumb: xdata is out of bounds'); tomwalters@0: return tomwalters@0: end tomwalters@0: tomwalters@0: % Update the thumbnail: tomwalters@0: set(ud.hthumb,'xdata',xdata); tomwalters@0: tomwalters@0: % Scroll the spectrogram and time-slice axes: tomwalters@0: % xxxx tomwalters@0: set(ud.hax([1]),'xlim',xdata(1:2)); % [1 3] xxx tomwalters@0: tomwalters@0: % update the audio selection to be played tomwalters@0: set_audio_selection(hfig, xdata(1:2) * ud.Fs); tomwalters@0: tomwalters@0: %if strcmp(ud.plot.top,'spectrogram_time_slice'), tomwalters@0: % set(ud.htslice_line,'ydata', get_spec_tslice(hfig)); % xxxx tomwalters@0: %end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbmotion_thumbleft(hco,eventStruct) tomwalters@0: % thumbnail LEFT motion tomwalters@0: tomwalters@0: % Get current point in axis ASAP: tomwalters@0: hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: % current object may be either the patch, or the signal line tomwalters@0: hax = ud.hax(2); tomwalters@0: cp = get(hax,'currentpoint'); tomwalters@0: curr_x = cp(1,1); tomwalters@0: tomwalters@0: xdata = get(ud.hthumb,'xdata'); tomwalters@0: xmotion = curr_x - ud.thumb.origPt; tomwalters@0: width = ud.thumb.width; tomwalters@0: xdata = ud.thumb.xdata; tomwalters@0: xdata([1 4 5]) = xdata([1 4 5]) + xmotion; tomwalters@0: tomwalters@0: % Constrain to axis limits, so we don't lose cursor: tomwalters@0: xlim = get(hax,'xlim'); tomwalters@0: min_xdata = min(xdata); tomwalters@0: if min_xdata < xlim(1), tomwalters@0: xdata=[xlim(1) xdata([2 3])' xlim([1 1])]; tomwalters@0: elseif min_xdata >= xdata(2), tomwalters@0: xdata = ud.thumb.xdata; tomwalters@0: end tomwalters@0: tomwalters@0: % Update the thumbnail: tomwalters@0: set(ud.hthumb,'xdata',xdata); tomwalters@0: tomwalters@0: % Scroll the spectrogram: tomwalters@0: set(ud.hax(1),'xlim',xdata(1:2)); tomwalters@0: tomwalters@0: % update the audio selection to be played tomwalters@0: set_audio_selection(hfig, xdata(1:2) * ud.Fs); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbmotion_thumbright(hco,eventStruct) tomwalters@0: % thumbnail RIGHT motion tomwalters@0: tomwalters@0: % Get current point in axis ASAP: tomwalters@0: hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: hax = ud.hax(2); tomwalters@0: cp = get(hax,'currentpoint'); tomwalters@0: curr_x = cp(1,1); tomwalters@0: tomwalters@0: xdata = get(ud.hthumb,'xdata'); tomwalters@0: xmotion = curr_x - ud.thumb.origPt; tomwalters@0: width = ud.thumb.width; tomwalters@0: xdata = ud.thumb.xdata; tomwalters@0: xdata([2 3]) = xdata([2 3]) + xmotion; tomwalters@0: tomwalters@0: % Constrain to axis limits, so we don't lose cursor: tomwalters@0: xlim = get(hax,'xlim'); tomwalters@0: max_xdata = max(xdata); tomwalters@0: if max_xdata > xlim(2), tomwalters@0: xdata([2:3]) = xlim(2); tomwalters@0: elseif max_xdata <= xdata(1), tomwalters@0: xdata = ud.thumb.xdata; tomwalters@0: end tomwalters@0: tomwalters@0: % Update the thumbnail: tomwalters@0: set(ud.hthumb,'xdata',xdata); tomwalters@0: tomwalters@0: % Scroll the spectrogram: tomwalters@0: set(ud.hax(1),'xlim',xdata(1:2)); tomwalters@0: tomwalters@0: % update the audio selection to be played tomwalters@0: set_audio_selection(hfig, xdata(1:2) * ud.Fs); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbup_thumb(hco,eventStruct) tomwalters@0: tomwalters@0: % set spectrogram and time-slice xlims tomwalters@0: hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: xdata = get(ud.hthumb,'xdata'); tomwalters@0: xlim = [min(xdata) max(xdata)]; tomwalters@0: tomwalters@0: % Commented out, due to flash: tomwalters@0: %set(ud.hax([1 3]),'xlim',xlim); tomwalters@0: % tomwalters@0: % This is fine: tomwalters@0: %set(ud.hax(1),'xlim',xlim); tomwalters@0: % tomwalters@0: % xxx the following line causes flash in the spect image tomwalters@0: % this is the time-slice axis: tomwalters@0: % xxx xxx BAD NEWS! tomwalters@0: % why does this affect the spectrogram axis? (overlap? clipping?) tomwalters@0: %set(ud.hax(3),'xlim',xlim); tomwalters@0: tomwalters@0: changePtr(gcbf,'hand'); tomwalters@0: install_cursorfcns(gcbf,'thumb'); tomwalters@0: tomwalters@0: % Turn back on image axis visibility, tomwalters@0: % which was turned off during wbdown_thumb tomwalters@0: % so that it does not flash while panning: tomwalters@0: % xxx tomwalters@0: % Leave off! tomwalters@0: %set(ud.hax(1),'vis','on'); tomwalters@0: % tomwalters@0: % Turn on crosshair visibility, which was shut off tomwalters@0: % during thumbnail panning (wbdown_thumb): tomwalters@0: set([ud.hspec_y ud.hspec_x ud.htslice_y],'vis','on'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbup_thumbleft(hco,eventStruct) tomwalters@0: % set spectrogram and time-slice xlims tomwalters@0: hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: xdata = get(ud.hthumb,'xdata'); tomwalters@0: xlim = [min(xdata) max(xdata)]; tomwalters@0: tomwalters@0: % Commented out, due to flash: tomwalters@0: %set(ud.hax([1 3]),'xlim',xlim); tomwalters@0: % tomwalters@0: % This is fine: tomwalters@0: set(ud.hax(1),'xlim',xlim); tomwalters@0: % tomwalters@0: % xxx the following line causes flash in the spect image tomwalters@0: % this is the time-slice axis: tomwalters@0: % xxx xxx xxx tomwalters@0: %set(ud.hax(3),'xlim',xlim); tomwalters@0: tomwalters@0: changePtr(gcbf,'ldrag'); tomwalters@0: install_cursorfcns(gcbf,'thumbleft'); tomwalters@0: tomwalters@0: % Turn on crosshair visibility, which was shut off tomwalters@0: % during thumbnail panning (wbdown_thumb): tomwalters@0: set([ud.hspec_y ud.hspec_x],'vis','on'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbup_thumbright(hco,eventStruct) tomwalters@0: % set spectrogram and time-slice xlims tomwalters@0: hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: xdata = get(ud.hthumb,'xdata'); tomwalters@0: xlim = [min(xdata) max(xdata)]; tomwalters@0: tomwalters@0: % Commented out, due to flash: tomwalters@0: %set(ud.hax([1 3]),'xlim',xlim); tomwalters@0: % tomwalters@0: % This is fine: tomwalters@0: set(ud.hax(1),'xlim',xlim); tomwalters@0: % tomwalters@0: % xxx the following line causes flash in the spect image tomwalters@0: % this is the time-slice axis: tomwalters@0: % xxx xxx tomwalters@0: %set(ud.hax(3),'xlim',xlim); tomwalters@0: tomwalters@0: changePtr(gcbf,'rdrag'); tomwalters@0: install_cursorfcns(gcbf,'thumbright'); tomwalters@0: tomwalters@0: % Turn on crosshair visibility, which was shut off tomwalters@0: % during thumbnail panning (wbdown_thumb): tomwalters@0: set([ud.hspec_y ud.hspec_x],'vis','on'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function update_status(hfig,str) tomwalters@0: % UPDATE_STATUS Update status text. tomwalters@0: tomwalters@0: % If str is not a string, skip tomwalters@0: % -1 is often used to "skip" the update tomwalters@0: if ischar(str), tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: set(ud.htext_status,'string',str); tomwalters@0: end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function play_sound(hco, eventStruct) tomwalters@0: % PLAY_SOUND Play the selected sound segment tomwalters@0: tomwalters@0: hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: y = get(ud.htime_plot,'ydata'); tomwalters@0: Fs = ud.Fs; tomwalters@0: tomwalters@0: xdata=get(ud.hthumb,'xdata'); tomwalters@0: xlim=[min(xdata) max(xdata)]; tomwalters@0: xidx=floor(xlim*Fs)+1; tomwalters@0: if xidx(1)<1, xidx(1)=1; end tomwalters@0: if xidx(2)>length(y), xidx(2)=length(y); end tomwalters@0: tomwalters@0: % Normalize sound and play: tomwalters@0: mx=max(abs(y)); tomwalters@0: try tomwalters@0: wavplay(y(xidx(1):xidx(2))./mx,Fs,'sync'); tomwalters@0: catch tomwalters@0: msg = lasterr; tomwalters@0: errordlg(msg,'Audio Playback Error','modal'); tomwalters@0: end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: % called by audioplayer during playback (if audioplayer enabled) tomwalters@0: function update_audio_position(hco, eventStruct) tomwalters@0: if hco.isplaying, % only do this if playback is in progress tomwalters@0: currentPosition = get(hco, 'CurrentSample') / get(hco, 'SampleRate'); tomwalters@0: set_crosshairs(get(hco, 'UserData'), currentPosition); tomwalters@0: end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: % utility to easily set playback boundaries tomwalters@0: function set_audio_selection(hfig, selectionPair) tomwalters@0: %%%%%%%%%%%%%%%%%%%%%%%%%% tomwalters@0: % inserted by S.Bleeck tomwalters@0: global tmin; tomwalters@0: global tmax; tomwalters@0: %%%%%%%%%%%%%%%%%%%%%%%%%% tomwalters@0: if ~ isempty(getappdata(hfig, 'audioSelection')), % only do this if audioplayer enabled tomwalters@0: selection.inPoint = selectionPair(1); tomwalters@0: if selection.inPoint < 1, selection.inPoint = 1; end tomwalters@0: selection.outPoint = selectionPair(2); tomwalters@0: setappdata(hfig, 'audioSelection', selection); tomwalters@0: %%%%%%%%%%%%%%%%%%%%%%%%%% tomwalters@0: % inserted by S.Bleeck tomwalters@0: % set the global times, so that we can pick them up tomwalters@0: tmin=selection.inPoint; tomwalters@0: tmax=selection.outPoint; tomwalters@0: %%%%%%%%%%%%%%%%%%%%%%%%%% tomwalters@0: end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: % used to set the "put back position" of the vertical crosshair tomwalters@0: function start_function(hobj, eventStruct) tomwalters@0: hfig = get(hobj, 'UserData'); tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: set(hobj, 'StopFcn', {@stop_function, ud.crosshair.xctr}); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: % when playback has completed, puts back the vertical crosshair tomwalters@0: % to where it was when playback was initiated tomwalters@0: function stop_function(hobj, eventStruct, where) tomwalters@0: while isplaying(hobj), pause(0); end % let playback complete tomwalters@0: if get(hobj, 'CurrentSample') == 1, % if paused, don't put it back tomwalters@0: set_crosshairs(get(hobj, 'UserData'), where); tomwalters@0: end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function set_cmap_limits(hfig, new_dr) tomwalters@0: % Set new colormap limits tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_spec = ud.hax(1); tomwalters@0: hax_cbar = ud.hax(5); tomwalters@0: himage_cbar = ud.himage_cbar; tomwalters@0: tomwalters@0: % Set new dynamic range limits into spectrogram image tomwalters@0: set(hax_spec,'clim',new_dr); tomwalters@0: tomwalters@0: % colorbar is 1:256 tomwalters@0: % actual spectrogram dynamic range is orig_dr tomwalters@0: % new spectrogram dynamic range is new_dr tomwalters@0: orig_dr = get(himage_cbar,'ydata'); tomwalters@0: diff_dr = new_dr - orig_dr; tomwalters@0: cmapIndices_per_dB = 256./diff(orig_dr); % a constant tomwalters@0: diff_clim = diff_dr .* cmapIndices_per_dB; tomwalters@0: cbar_clim = [1 256] + diff_clim; tomwalters@0: set(himage_cbar,'cdatamapping','scaled'); % do during creation tomwalters@0: set(hax_cbar,'clim',cbar_clim); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function reset_cmap_limits(hco,eventStruct) tomwalters@0: % Reset colormap limits to dynamic range of spectrogram data tomwalters@0: tomwalters@0: hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: orig_dr = get(ud.himage_cbar,'ydata'); tomwalters@0: set_cmap_limits(hfig, orig_dr); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function manual_cmap_limits(hco,eventStruct,hfig) tomwalters@0: % manual_cmap_limits Manual change to colormap dynamic range limits tomwalters@0: tomwalters@0: if nargin<3, tomwalters@0: hfig = gcbf; tomwalters@0: end tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_spec = ud.hax(1); tomwalters@0: tomwalters@0: % Prompt for changes to cmap limits: tomwalters@0: clim = get(hax_spec,'clim'); tomwalters@0: % 'dB value of first color in colormap:' tomwalters@0: % 'dB value of last color in colormap:' tomwalters@0: prompt={'Value of top color in colormap (dB):', ... tomwalters@0: 'Value of bottom color in colormap (dB):'}; tomwalters@0: def = {num2str(clim(2)), num2str(clim(1))}; tomwalters@0: dlgTitle='Adjust dynamic range of colormap'; tomwalters@0: lineNo=1; tomwalters@0: strs=inputdlg(prompt,dlgTitle,lineNo,def); tomwalters@0: if isempty(strs), tomwalters@0: return tomwalters@0: end tomwalters@0: new_dr = [str2num(strs{2}) str2num(strs{1})]; tomwalters@0: tomwalters@0: set_cmap_limits(hfig,new_dr); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbmotion_cmap(hco,eventStruct) tomwalters@0: % WBMOTION_CMAP Graphical change to colormap dynamic range limits tomwalters@0: tomwalters@0: hfig = gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_spec = ud.hax(1); tomwalters@0: hax_cbar = ud.hax(5); tomwalters@0: tomwalters@0: % Determine cursor starting and current points ASAP: tomwalters@0: cp = get(hax_cbar,'CurrentPoint'); tomwalters@0: newPt = cp(1,2); % y-coord only tomwalters@0: dy = newPt - ud.cbar.origPt; tomwalters@0: tomwalters@0: % if SelectionType was normal, tomwalters@0: % update top or bottom of colorbar, only, tomwalters@0: % depending on whether user started drag tomwalters@0: % in the top or bottom of bar, respectively. tomwalters@0: % if SelectionType was extend, tomwalters@0: % update both top AND bottom of bar simultaneously, tomwalters@0: % translating colormap region. tomwalters@0: if strcmp(ud.cbar.SelectionType,'extend'), tomwalters@0: change_dr = [dy dy]; tomwalters@0: else tomwalters@0: if ud.cbar.StartInTop, tomwalters@0: change_dr = [0 dy]; tomwalters@0: else tomwalters@0: change_dr = [dy 0]; tomwalters@0: end tomwalters@0: end tomwalters@0: new_dr = ud.cbar.starting_dr + change_dr; tomwalters@0: if diff(new_dr)<=0, tomwalters@0: new_dr = ud.cbar.starting_dr; tomwalters@0: end tomwalters@0: tomwalters@0: % Colorbar range is 1 to 256. tomwalters@0: % Actual spectrogram dynamic range is orig_dr tomwalters@0: % New spectrogram dynamic range is new_dr tomwalters@0: orig_dr = get(ud.himage_cbar,'ydata'); % a constant tomwalters@0: cmapIndices_per_dB = 256./diff(orig_dr); % a constant tomwalters@0: diff_dr = new_dr - orig_dr; tomwalters@0: diff_clim = diff_dr .* cmapIndices_per_dB; tomwalters@0: cbar_clim = [1 256] + diff_clim; tomwalters@0: tomwalters@0: if diff(cbar_clim)>0, tomwalters@0: % Protect against poor choice of values tomwalters@0: set(hax_cbar,'clim',cbar_clim,'userdata',new_dr); tomwalters@0: end tomwalters@0: tomwalters@0: % We defer setting the new dynamic range limits tomwalters@0: % into the spectrogram image axis, as it will create tomwalters@0: % too much flash. Instead, on button-up, the new tomwalters@0: % limit is set. See wbup_cmap() for details. tomwalters@0: tomwalters@0: % Set new dynamic range limits into spectrogram image tomwalters@0: % Note: userdata could be empty if this is the first entry... tomwalters@0: % xxx tomwalters@0: %set(ud.hax(1),'clim',new_dr); tomwalters@0: set(hax_spec,'clim',new_dr); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function isChange = changePtr(hfig, newPtr) tomwalters@0: tomwalters@0: % Get current pointer name: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: % Is this a change in pointer type? tomwalters@0: isChange = ~strcmp(ud.currPtr,newPtr); tomwalters@0: if isChange, tomwalters@0: setptr(hfig, newPtr); tomwalters@0: ud.currPtr = newPtr; tomwalters@0: set(hfig,'userdata',ud); tomwalters@0: end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbmotion_general(hco,eventStruct,hfig) tomwalters@0: % General button motion tomwalters@0: % tomwalters@0: % Determines if cursor is over a crosshair tomwalters@0: % If so, changes pointer and installs crosshair buttondowns tomwalters@0: % If not, changes back to normal cursor and general buttondowns tomwalters@0: % as necessary. tomwalters@0: tomwalters@0: if nargin<3, tomwalters@0: hfig = gcbf; tomwalters@0: end tomwalters@0: [isOverHV, isSegmentAxis, isCmapAxis,isTopHalfCmap, isThumb] = ... tomwalters@0: over_crosshair(hfig); tomwalters@0: tomwalters@0: if ~any(isOverHV), tomwalters@0: % Not hovering over a crosshair tomwalters@0: tomwalters@0: if isSegmentAxis, tomwalters@0: % Over an axis in which we can get a delta-time measurement tomwalters@0: if changePtr(hfig,'crosshair'), tomwalters@0: install_cursorfcns(hfig,'segment'); tomwalters@0: end tomwalters@0: tomwalters@0: elseif isCmapAxis, tomwalters@0: % Over the colormap axes tomwalters@0: % Install the up/down pointer: tomwalters@0: if isTopHalfCmap, tomwalters@0: if changePtr(hfig,'udrag'), tomwalters@0: update_status(hfig,'Adjust upper dynamic range (shift to translate)'); tomwalters@0: install_cursorfcns(hfig,'cmap'); tomwalters@0: end tomwalters@0: else tomwalters@0: if changePtr(hfig,'ddrag'), tomwalters@0: update_status(hfig,'Adjust lower dynamic range (shift to translate)'); tomwalters@0: install_cursorfcns(hfig,'cmap'); tomwalters@0: end tomwalters@0: end tomwalters@0: tomwalters@0: elseif any(isThumb), tomwalters@0: % Over thumbnail - isThumb is a 3-element vector, [left center right], tomwalters@0: % indicating whether cursor is over left edge, right edge, or is over tomwalters@0: % the general thumbnail patch itself. tomwalters@0: tomwalters@0: % Install appropriate pointer: tomwalters@0: if isThumb(1), tomwalters@0: % Over left edge tomwalters@0: if changePtr(hfig,'ldrag'), tomwalters@0: install_cursorfcns(hfig,'thumbleft'); tomwalters@0: end tomwalters@0: elseif isThumb(3), tomwalters@0: % Over right edge tomwalters@0: if changePtr(hfig,'rdrag'), tomwalters@0: install_cursorfcns(hfig,'thumbright'); tomwalters@0: end tomwalters@0: else tomwalters@0: % Over general patch region tomwalters@0: if changePtr(hfig,'hand'), tomwalters@0: install_cursorfcns(hfig,'thumb'); tomwalters@0: end tomwalters@0: end tomwalters@0: tomwalters@0: else tomwalters@0: % Not over a special axes: tomwalters@0: if changePtr(hfig,'arrow'), tomwalters@0: install_cursorfcns(hfig,'general'); tomwalters@0: end tomwalters@0: end tomwalters@0: tomwalters@0: else tomwalters@0: % Pointer is over a crosshair (vert or horiz or both) tomwalters@0: if all(isOverHV), tomwalters@0: % Over both horiz and vert (near crosshair center): tomwalters@0: if changePtr(hfig,'fleur'), tomwalters@0: install_cursorfcns(hfig,'hvcross'); tomwalters@0: end tomwalters@0: elseif isOverHV(1), tomwalters@0: % Over H crosshair tomwalters@0: if changePtr(hfig,'uddrag'), tomwalters@0: install_cursorfcns(hfig,'hcross'); tomwalters@0: end tomwalters@0: else tomwalters@0: % Over V crosshair tomwalters@0: if changePtr(hfig,'lrdrag'), tomwalters@0: install_cursorfcns(hfig,'vcross'); tomwalters@0: end tomwalters@0: end tomwalters@0: end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function [y,isSegmentAxis,isCmapAxis,... tomwalters@0: isTopHalfCmap, isThumb] = over_crosshair(hfig) tomwalters@0: % Is the cursor hovering over the crosshairs? tomwalters@0: % There are two crosshairs, one an H-crosshair, the other tomwalters@0: % a V-crosshair. The H and V crosshairs span several tomwalters@0: % different axes. tomwalters@0: % tomwalters@0: % Function returns a 2-element vector, indicating whether tomwalters@0: % the cursor is currently over the H- and/or V-crosshairs. tomwalters@0: % y = [isOverH isOverV] tomwalters@0: tomwalters@0: y = [0 0]; tomwalters@0: isSegmentAxis = 0; tomwalters@0: isCmapAxis = 0; tomwalters@0: isTopHalfCmap = 0; tomwalters@0: isThumb = [0 0 0]; % left, middle, right regions tomwalters@0: tomwalters@0: % First, are we over any axes? tomwalters@0: hax = overAxes(hfig); tomwalters@0: if isempty(hax), return; end % not over an axis tomwalters@0: tomwalters@0: % Get current point in axis: tomwalters@0: cp = get(hax,'currentpoint'); tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: % Axis which are "segmentable" have a vertical crosshair tomwalters@0: % e.g., spectrogram and time axes only tomwalters@0: isCmapAxis = (hax==ud.hax(5)); tomwalters@0: isSegmentAxis = (hax==ud.hax(1)); tomwalters@0: tomwalters@0: % Determine if any horiz or vert crosshairs are tomwalters@0: % in this axis ... store as [anyHoriz anyVert]: tomwalters@0: hasHVCrossHairs = [any(hax==ud.hax([1 4])) ... tomwalters@0: any(hax==ud.hax(1:3))]; tomwalters@0: tomwalters@0: % Is cursor in colormap axis? tomwalters@0: if (isCmapAxis), tomwalters@0: % is cursor in top half of colormap axis? tomwalters@0: orig_dr = get(ud.hax(1),'clim'); tomwalters@0: isTopHalfCmap = (cp(1,2) >= sum(orig_dr)/2); tomwalters@0: end tomwalters@0: tomwalters@0: if any(hasHVCrossHairs), tomwalters@0: % Get cursor & crosshair positions: tomwalters@0: crosshair_pos = [ud.crosshair.xctr ud.crosshair.yctr]; tomwalters@0: cursor_delta = abs(crosshair_pos - cp(1,1:2)); tomwalters@0: axis_dx = diff(get(hax,'xlim')); tomwalters@0: axis_dy = diff(get(hax,'ylim')); tomwalters@0: axis_delta = [axis_dx axis_dy]; tomwalters@0: tomwalters@0: % Is cursor within 1 percent of crosshair centers? tomwalters@0: % Limit test uses the reciprocal of the percentage tolerance tomwalters@0: % 1-percent -> 1 / 0.01 = 100 tomwalters@0: % 1.5-percent -> 1 / 0.015 ~= 67 tomwalters@0: % 2-percent -> 1 / 0.02 = 50 tomwalters@0: % tomwalters@0: % Finally, allow a true result only if the axis tomwalters@0: % has a crosshair of the corresponding type tomwalters@0: % tomwalters@0: y = fliplr(cursor_delta * 67 < axis_delta) & hasHVCrossHairs; tomwalters@0: end tomwalters@0: tomwalters@0: % Are we over the thumbnail patch? tomwalters@0: % Check if we're over the time axis: tomwalters@0: if (hax == ud.hax(2)), tomwalters@0: % Get thumb patch limits: tomwalters@0: xdata=get(ud.hthumb,'xdata'); tomwalters@0: xlim=[min(xdata) max(xdata)]; tomwalters@0: tomwalters@0: % Is cursor over general patch area? tomwalters@0: thumb_delta = xlim - cp(1,1); tomwalters@0: isThumb(2) = thumb_delta(1)<=0 & thumb_delta(2)>=0; tomwalters@0: tomwalters@0: % Is cursor over left or right thumbnail edge? tomwalters@0: % Use same tolerance as crosshair test: tomwalters@0: axis_dx = diff(get(hax,'xlim')); tomwalters@0: isThumb([1 3]) = (abs(thumb_delta) * 67 < axis_dx); tomwalters@0: end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function h=overAxes(hfig) tomwalters@0: % overAxes Determine if pointer is currently over an tomwalters@0: % axis of the figure; the axis list comes from the tomwalters@0: % figure UserData (ud.hax). tomwalters@0: tomwalters@0: p = get(0,'PointerLocation'); tomwalters@0: figPos = get(hfig,'Position'); tomwalters@0: if ~isempty(figPos), tomwalters@0: x = (p(1)-figPos(1))/figPos(3); tomwalters@0: y = (p(2)-figPos(2))/figPos(4); tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: for h = ud.hax, tomwalters@0: r = get(h,'Position'); tomwalters@0: if (x > r(1)) & (x < r(1)+r(3)) & ... tomwalters@0: (y > r(2)) & (y < r(2)+r(4)), tomwalters@0: return; tomwalters@0: end tomwalters@0: end tomwalters@0: end tomwalters@0: h = []; tomwalters@0: return tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function y=isLeftClick(hfig) tomwalters@0: tomwalters@0: % Keywords for key/button combinations: tomwalters@0: % Left Right tomwalters@0: % none: normal alt tomwalters@0: % Shift: extend alt tomwalters@0: % Ctrl: alt alt tomwalters@0: % Double: open alt tomwalters@0: tomwalters@0: y=strcmp(get(hfig,'SelectionType'),'normal'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbdown_hcross(hco,eventStruct) tomwalters@0: % window button down in h-crosshair mode tomwalters@0: if ~isLeftClick(gcbf), return; end tomwalters@0: install_cursorfcns(gcbf,'hcross_buttondown'); tomwalters@0: wbmotion_cross([],[],'h'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbdown_vcross(hco,eventStruct) tomwalters@0: % window button down in v-crosshair mode tomwalters@0: if ~isLeftClick(gcbf), return; end tomwalters@0: install_cursorfcns(gcbf,'vcross_buttondown'); tomwalters@0: wbmotion_cross([],[],'v'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbdown_hvcross(hco,eventStruct) tomwalters@0: % window button down in hv-crosshair mode tomwalters@0: if ~isLeftClick(gcbf), return; end tomwalters@0: install_cursorfcns(gcbf,'hvcross_buttondown'); tomwalters@0: wbmotion_cross([],[],'hv'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbdown_segment(hco,eventStruct) tomwalters@0: % window button down in segmentation mode tomwalters@0: if ~isLeftClick(gcbf), return; end tomwalters@0: install_cursorfcns(gcbf,'segment_buttondown'); tomwalters@0: wbmotion_segment([],[],gcbf); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbdown_thumb(hco,eventStruct) tomwalters@0: % window button down in thumbnail mode tomwalters@0: if ~isLeftClick(gcbf), return; end tomwalters@0: tomwalters@0: % cache y-coord of pointer tomwalters@0: ud = get(gcbf,'userdata'); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: cp = get(hax_time,'currentpoint'); tomwalters@0: xdata = get(ud.hthumb,'xdata'); tomwalters@0: width = max(xdata)-min(xdata); tomwalters@0: tomwalters@0: ud.thumb.origPt = cp(1,1); % x-coord only tomwalters@0: ud.thumb.width = width; tomwalters@0: ud.thumb.xdata = xdata; tomwalters@0: set(gcbf,'userdata',ud); tomwalters@0: tomwalters@0: changePtr(gcbf,'closedhand'); tomwalters@0: install_cursorfcns(gcbf,'thumb_buttondown'); tomwalters@0: tomwalters@0: tomwalters@0: % Turn off image axis visibility, tomwalters@0: % so that it does not flash while panning: tomwalters@0: % tomwalters@0: % xxx off permanently now: tomwalters@0: %set(ud.hax(1),'vis','off'); tomwalters@0: % tomwalters@0: % Turn off crosshair visibility: tomwalters@0: set([ud.hspec_y ud.hspec_x ud.htslice_y],'vis','off'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbdown_thumbleft(hco,eventStruct) tomwalters@0: tomwalters@0: % window button down in LEFT thumbnail mode tomwalters@0: if ~isLeftClick(gcbf), return; end tomwalters@0: tomwalters@0: % cache y-coord of pointer tomwalters@0: ud = get(gcbf,'userdata'); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: cp = get(hax_time,'currentpoint'); tomwalters@0: xdata = get(ud.hthumb,'xdata'); tomwalters@0: width = max(xdata)-min(xdata); tomwalters@0: tomwalters@0: ud.thumb.origPt = cp(1,1); % x-coord only tomwalters@0: ud.thumb.width = width; tomwalters@0: ud.thumb.xdata = xdata; tomwalters@0: set(gcbf,'userdata',ud); tomwalters@0: tomwalters@0: install_cursorfcns(gcbf,'thumbleft_buttondown'); tomwalters@0: tomwalters@0: % Turn off crosshair visibility: tomwalters@0: set([ud.hspec_y ud.hspec_x],'vis','off'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbdown_thumbright(hco,eventStruct) tomwalters@0: tomwalters@0: % window button down in LEFT thumbnail mode tomwalters@0: if ~isLeftClick(gcbf), return; end tomwalters@0: tomwalters@0: % cache y-coord of pointer tomwalters@0: ud = get(gcbf,'userdata'); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: cp = get(hax_time,'currentpoint'); tomwalters@0: xdata = get(ud.hthumb,'xdata'); tomwalters@0: width = max(xdata)-min(xdata); tomwalters@0: tomwalters@0: ud.thumb.origPt = cp(1,1); % x-coord only tomwalters@0: ud.thumb.width = width; tomwalters@0: ud.thumb.xdata = xdata; tomwalters@0: set(gcbf,'userdata',ud); tomwalters@0: tomwalters@0: install_cursorfcns(gcbf,'thumbright_buttondown'); tomwalters@0: tomwalters@0: % Turn off crosshair visibility: tomwalters@0: set([ud.hspec_y ud.hspec_x],'vis','off'); tomwalters@0: tomwalters@0: %---------------------------------------------------- tomwalters@0: function wbdown_cmap(hco,eventStruct) tomwalters@0: % window button down in colormap mode tomwalters@0: tomwalters@0: hfig = gcbf; tomwalters@0: tomwalters@0: % Only allow left (normal) or shift+left (extend) tomwalters@0: st = get(hfig,'SelectionType'); tomwalters@0: i=strmatch(st,{'normal','extend','open'}); tomwalters@0: if isempty(i), return; end tomwalters@0: tomwalters@0: if i==3, tomwalters@0: % open dynamic range menu tomwalters@0: manual_cmap_limits([],[],hfig); tomwalters@0: return tomwalters@0: elseif i==2, tomwalters@0: % Shift+left button = translate, tomwalters@0: % show up/down cursor during drag tomwalters@0: % NOTE: cannot update cursor when shift is pressed tomwalters@0: % but no mouse button is pressed (no event!) tomwalters@0: changePtr(hfig,'uddrag'); % xxx tomwalters@0: end tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: % cache y-coord of pointer tomwalters@0: hax_cbar = ud.hax(5); tomwalters@0: cp = get(hax_cbar,'currentpoint'); tomwalters@0: ud.cbar.origPt = cp(1,2); % y-coord only tomwalters@0: ud.cbar.SelectionType = st; % normal or extend tomwalters@0: tomwalters@0: % The current clim is in the spectrogram image tomwalters@0: % We want to know the midpoint of this tomwalters@0: orig_dr = get(ud.hax(1),'clim'); tomwalters@0: ud.cbar.midPt = sum(orig_dr)/2; tomwalters@0: tomwalters@0: % Determine if pointer went down in top or bottom tomwalters@0: % half of colorbar: tomwalters@0: ud.cbar.StartInTop = (ud.cbar.origPt >= ud.cbar.midPt); tomwalters@0: tomwalters@0: % Cache original dynamic range: tomwalters@0: hax_spec = ud.hax(1); tomwalters@0: ud.cbar.starting_dr = get(hax_spec,'clim'); tomwalters@0: set(hfig,'userdata',ud); tomwalters@0: tomwalters@0: install_cursorfcns(hfig,'cmap_buttondown'); tomwalters@0: tomwalters@0: % Set initial clim into userdata in case motion tomwalters@0: % callback not performed (motion updates userdata). tomwalters@0: % wbup_cmap reads the userdata tomwalters@0: % tomwalters@0: % Turn off visibility during drag to prevent flash tomwalters@0: set(hax_cbar, ... tomwalters@0: 'userdata',ud.cbar.starting_dr, ... tomwalters@0: 'vis','off'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbup_hcross(hco,eventStruct) tomwalters@0: % window button up in h-crosshair mode tomwalters@0: install_cursorfcns(gcbf,'hcross'); tomwalters@0: update_cmap_ptr(gcbf); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbup_vcross(hco,eventStruct) tomwalters@0: % window button up in v-crosshair mode tomwalters@0: install_cursorfcns(gcbf,'vcross'); tomwalters@0: update_cmap_ptr(gcbf); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbup_hvcross(hco,eventStruct) tomwalters@0: % window button up in hv-crosshair mode tomwalters@0: install_cursorfcns(gcbf,'hvcross'); tomwalters@0: update_cmap_ptr(gcbf); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbup_segment(hco,eventStruct) tomwalters@0: % window button up in segmentation mode tomwalters@0: install_cursorfcns(gcbf,'segment'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbup_cmap(hco,eventStruct) tomwalters@0: % window button up in colormap mode tomwalters@0: install_cursorfcns(gcbf,'cmap'); tomwalters@0: tomwalters@0: % Set new dynamic range limits into spectrogram image tomwalters@0: % Note: userdata could be empty if this is the first entry... tomwalters@0: ud = get(gcbf,'userdata'); tomwalters@0: hax_cbar=ud.hax(5); tomwalters@0: set(ud.hax(1),'clim',get(hax_cbar,'userdata')); tomwalters@0: set(hax_cbar,'vis','on'); % re-enable axis vis tomwalters@0: tomwalters@0: % Set new status msg, since it doesn't update tomwalters@0: % in the install_cursorfcns fcn for cmap callbacks tomwalters@0: % Do this by calling the general mouse-motion fcn: tomwalters@0: wbmotion_general([],[]); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function update_cmap_ptr(hfig) tomwalters@0: % Update colormap pointer: tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: v = get_spec_val(hfig); % value in dB tomwalters@0: dy_tri = ud.crosshair.cbar.dy_tri; tomwalters@0: set(ud.hcmap_arrow,'ydata', [v+dy_tri v-dy_tri v]); tomwalters@0: tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function [i,j] = get_adjusted_crosshair_idx(hfig) tomwalters@0: % Find image matrix coordinate pair (j,i) under crosshair. tomwalters@0: % Adjust crosshair for "half-pixel offset" implicit in image display tomwalters@0: tomwalters@0: ud=get(hfig,'userdata'); tomwalters@0: xc=ud.crosshair.xctr; tomwalters@0: yc=ud.crosshair.yctr; tomwalters@0: himage=ud.himage; tomwalters@0: im=get(himage,'cdata'); tomwalters@0: tomwalters@0: % Get image pixel size: tomwalters@0: xdata=get(himage,'xdata'); tomwalters@0: if length(xdata)>1, dx = xdata(2)-xdata(1); else dx=0; end tomwalters@0: tomwalters@0: ydata=get(himage,'ydata'); tomwalters@0: if length(ydata)>1, dy = ydata(2)-ydata(1); else dy=0; end tomwalters@0: tomwalters@0: % Remove half a pixel size from apparent cursor position: tomwalters@0: xc=xc-dx/2; tomwalters@0: yc=yc-dy/2; tomwalters@0: tomwalters@0: % Find pixel coordinate under the crosshair: tomwalters@0: i=find(xc>=xdata); tomwalters@0: if isempty(i), i=1; tomwalters@0: else i=i(end)+1; tomwalters@0: end tomwalters@0: j=find(yc>=ydata); tomwalters@0: if isempty(j), j=1; tomwalters@0: else j=j(end)+1; tomwalters@0: end tomwalters@0: sz=size(im); tomwalters@0: if i>sz(2), i=sz(2); end tomwalters@0: if j>sz(1), j=sz(1); end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function v = get_spec_val(hfig) tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: im = get(ud.himage,'cdata'); tomwalters@0: [i,j] = get_adjusted_crosshair_idx(hfig); tomwalters@0: v = double(im(j,i)); % Get pixel value in double-precision tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function v = get_spec_freq(hfig) tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: im = get(ud.himage,'cdata'); tomwalters@0: [i,j] = get_adjusted_crosshair_idx(hfig); tomwalters@0: v = im(:,i); % Get pixel row in uint8 tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function v = get_spec_tslice(hfig) tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: im = get(ud.himage,'cdata'); tomwalters@0: [i,j] = get_adjusted_crosshair_idx(hfig); tomwalters@0: v = im(j,:); % Get pixel column tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function update_time_readout(hfig,diffTime) tomwalters@0: tomwalters@0: % xxx tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: if nargin<2, tomwalters@0: t=ud.crosshair.xctr; tomwalters@0: prefix=''; tomwalters@0: else tomwalters@0: t=diffTime - ud.crosshair.xctr; tomwalters@0: prefix='\Deltat '; tomwalters@0: end tomwalters@0: tomwalters@0: % Update time readout tomwalters@0: [y,e,u] = engunits(t, 'latex','time'); tomwalters@0: %str=[prefix num2str(y) ' ' u]; tomwalters@0: str=[prefix sprintf('%.4f',y) ' ' u]; tomwalters@0: set(ud.htext_time,'string',str); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function update_freq_readout(hfig,diffFreq) tomwalters@0: tomwalters@0: ud=get(hfig,'userdata'); tomwalters@0: if nargin<2, tomwalters@0: f=ud.crosshair.yctr; tomwalters@0: prefix=''; tomwalters@0: else tomwalters@0: f=diffFreq - ud.crosshair.yctr; tomwalters@0: prefix='\Deltaf '; tomwalters@0: end tomwalters@0: tomwalters@0: % Update freq readout tomwalters@0: [y,e,u] = engunits(f,'latex'); tomwalters@0: %str=[prefix num2str(y) ' ' u 'Hz']; tomwalters@0: str=[prefix sprintf('%.4f',y) ' ' u 'Hz']; tomwalters@0: set(ud.htext_freq,'string',str); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function update_dB_readout(hfig,diffAmpl) tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: if nargin<2, tomwalters@0: a=get_spec_val(hfig); tomwalters@0: prefix=''; tomwalters@0: else tomwalters@0: a=diffAmpl - get_spec_val(hfig); tomwalters@0: prefix='\Deltaa='; tomwalters@0: end tomwalters@0: tomwalters@0: % Update mag readout tomwalters@0: %str=[prefix num2str(a) ' dB']; tomwalters@0: str=[prefix sprintf('%.4f',a) ' dB']; tomwalters@0: set(ud.htext_mag,'string',str); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function clear_dB_readout(hfig) tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: set(ud.htext_mag,'string',''); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbmotion_cross(hco,eventStruct,sel) tomwalters@0: % motion callback during horiz/vert-crosshair selection tomwalters@0: % sel='h', 'v', or 'hv' tomwalters@0: tomwalters@0: % Get current point in axis ASAP: tomwalters@0: hfig = gcbf; tomwalters@0: hco = gco; tomwalters@0: switch get(hco,'type') tomwalters@0: case 'axes' tomwalters@0: hax=hco; tomwalters@0: otherwise tomwalters@0: hax=get(hco,'parent'); tomwalters@0: end tomwalters@0: tomwalters@0: cp = get(hax,'currentpoint'); tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: x = cp(1,1); tomwalters@0: y = cp(1,2); tomwalters@0: tomwalters@0: switch sel tomwalters@0: case 'h' tomwalters@0: x=ud.crosshair.xctr; tomwalters@0: case 'v' tomwalters@0: y=ud.crosshair.yctr; tomwalters@0: end tomwalters@0: tomwalters@0: % Constrain to axis limits, so we don't lose cursor: tomwalters@0: if any(sel=='v'), tomwalters@0: xlim=get(hax,'xlim'); tomwalters@0: if xxlim(2), tomwalters@0: x=xlim(2); tomwalters@0: end tomwalters@0: end tomwalters@0: tomwalters@0: if any(sel=='h'), tomwalters@0: ylim=get(hax,'ylim'); tomwalters@0: if yylim(2), tomwalters@0: y=ylim(2); tomwalters@0: end tomwalters@0: end tomwalters@0: set_crosshairs(hfig,x,y); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function wbmotion_segment(hco,eventStruct,hfig) tomwalters@0: % motion callback during segmentation selection tomwalters@0: tomwalters@0: % xxx tomwalters@0: % Get current point in axis ASAP: tomwalters@0: if nargin<3, tomwalters@0: hfig = gcbf; tomwalters@0: end tomwalters@0: tomwalters@0: hax=gco; tomwalters@0: t=get(hax,'type'); tomwalters@0: if ~strcmp(t,'axes'), tomwalters@0: hax = get(hax,'parent'); tomwalters@0: end tomwalters@0: cp = get(hax,'currentpoint'); tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: x = cp(1,1); tomwalters@0: y = cp(1,2); tomwalters@0: tomwalters@0: % Constrain to axis limits, so we don't lose cursor: tomwalters@0: xlim=get(hax,'xlim'); tomwalters@0: if xxlim(2), tomwalters@0: x=xlim(2); tomwalters@0: end tomwalters@0: ylim=get(hax,'ylim'); tomwalters@0: if yylim(2), tomwalters@0: y=ylim(2); tomwalters@0: end tomwalters@0: tomwalters@0: update_time_readout(hfig,x); tomwalters@0: update_freq_readout(hfig,y); tomwalters@0: clear_dB_readout(hfig); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function install_cursorfcns(hfig,cursorType) tomwalters@0: tomwalters@0: switch lower(cursorType) tomwalters@0: case 'none' tomwalters@0: dn = []; tomwalters@0: motion = []; tomwalters@0: up = []; tomwalters@0: status = ''; tomwalters@0: tomwalters@0: case 'general' tomwalters@0: dn = []; tomwalters@0: motion = @wbmotion_general; tomwalters@0: up = []; tomwalters@0: status = 'Ready'; tomwalters@0: tomwalters@0: case 'segment' tomwalters@0: dn = @wbdown_segment; tomwalters@0: motion = @wbmotion_general; tomwalters@0: up = []; tomwalters@0: status = 'Ready'; tomwalters@0: tomwalters@0: case 'segment_buttondown' tomwalters@0: dn = []; tomwalters@0: motion = @wbmotion_segment; tomwalters@0: up = @wbup_segment; tomwalters@0: status = 'Difference from crosshair'; tomwalters@0: tomwalters@0: case 'thumb' tomwalters@0: % button not pushed, thumbnail highlighted tomwalters@0: dn = @wbdown_thumb; tomwalters@0: motion = @wbmotion_general; tomwalters@0: up = []; tomwalters@0: status = 'Pan zoom window'; tomwalters@0: tomwalters@0: case 'thumb_buttondown' tomwalters@0: % button pushed, thumbnail highlighted tomwalters@0: dn = []; tomwalters@0: motion = @wbmotion_thumb; tomwalters@0: up = @wbup_thumb; tomwalters@0: status = 'Release to set zoom window'; tomwalters@0: tomwalters@0: case 'thumbleft' tomwalters@0: % button not pushed, left thumbnail edge highlighted tomwalters@0: dn = @wbdown_thumbleft; tomwalters@0: motion = @wbmotion_general; tomwalters@0: up = []; tomwalters@0: status = 'Adjust zoom window left edge'; tomwalters@0: tomwalters@0: case 'thumbleft_buttondown' tomwalters@0: % button pushed, thumbnail highlighted tomwalters@0: dn = []; tomwalters@0: motion = @wbmotion_thumbleft; tomwalters@0: up = @wbup_thumbleft; tomwalters@0: status = 'Release to set zoom window'; tomwalters@0: tomwalters@0: case 'thumbright' tomwalters@0: % button not pushed, right thumbnail edge highlighted tomwalters@0: dn = @wbdown_thumbright; tomwalters@0: motion = @wbmotion_general; tomwalters@0: up = []; tomwalters@0: status = 'Adjust zoom window right edge'; tomwalters@0: tomwalters@0: case 'thumbright_buttondown' tomwalters@0: % button pushed, right thumbnail edge highlighted tomwalters@0: dn = []; tomwalters@0: motion = @wbmotion_thumbright; tomwalters@0: up = @wbup_thumbright; tomwalters@0: status = 'Release to set zoom window'; tomwalters@0: tomwalters@0: case 'hcross' tomwalters@0: % button not pushed, h-crosshair highlighted tomwalters@0: dn = @wbdown_hcross; tomwalters@0: motion = @wbmotion_general; tomwalters@0: up = []; tomwalters@0: status = 'Move horizontal cursor'; tomwalters@0: tomwalters@0: case 'hcross_buttondown' tomwalters@0: % button pushed while over horiz cross-hair tomwalters@0: dn = []; tomwalters@0: motion = {@wbmotion_cross,'h'}; tomwalters@0: up = @wbup_hcross; tomwalters@0: status = 'Release to update cursor'; tomwalters@0: tomwalters@0: case 'vcross' tomwalters@0: dn = @wbdown_vcross; tomwalters@0: motion = @wbmotion_general; tomwalters@0: up = []; tomwalters@0: status = 'Move vertical cursor'; tomwalters@0: tomwalters@0: case 'vcross_buttondown' tomwalters@0: dn = []; tomwalters@0: motion = {@wbmotion_cross,'v'}; tomwalters@0: up = @wbup_vcross; tomwalters@0: status = 'Release to update cursor'; tomwalters@0: tomwalters@0: case 'hvcross' tomwalters@0: dn = @wbdown_hvcross; tomwalters@0: motion = @wbmotion_general; tomwalters@0: up = []; tomwalters@0: status = 'Move crosshair cursor'; tomwalters@0: tomwalters@0: case 'hvcross_buttondown' tomwalters@0: dn = []; tomwalters@0: motion = {@wbmotion_cross,'hv'}; tomwalters@0: up = @wbup_hvcross; tomwalters@0: status = 'Release to update cursor'; tomwalters@0: tomwalters@0: % Change dynamic range of colormap tomwalters@0: case 'cmap' tomwalters@0: dn = @wbdown_cmap; tomwalters@0: motion = @wbmotion_general; tomwalters@0: up = []; tomwalters@0: % Status is set in wbmotion_general function tomwalters@0: % since it depends on which pointer we're using tomwalters@0: status = -1; tomwalters@0: tomwalters@0: case 'cmap_buttondown' tomwalters@0: dn = []; tomwalters@0: motion = @wbmotion_cmap; tomwalters@0: up = @wbup_cmap; tomwalters@0: status = 'Release to update colormap'; tomwalters@0: tomwalters@0: otherwise tomwalters@0: error('Unrecognized cursorfcn'); tomwalters@0: end tomwalters@0: tomwalters@0: set(hfig, ... tomwalters@0: 'windowbuttondownfcn', dn, ... tomwalters@0: 'windowbuttonmotionfcn',motion, ... tomwalters@0: 'windowbuttonupfcn', up) tomwalters@0: tomwalters@0: update_status(hfig,status); tomwalters@0: tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function resize_fig(hco,eventStruct) tomwalters@0: % Callback to resize the figure tomwalters@0: tomwalters@0: update_axes_with_eng_units(gcbf); tomwalters@0: tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function update_axes_with_eng_units(hfig) tomwalters@0: tomwalters@0: % Update the tick marks for axes that are using engineering units tomwalters@0: % For example, a resize could have added or removed ticks, and the tomwalters@0: % axes would no longer have the proper tick marks tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: hax_freq = ud.hax(4); tomwalters@0: tomwalters@0: % Update freq-axis labels for engineering units, etc: tomwalters@0: yy=get(hax_freq,'ytick'); tomwalters@0: [cs,eu] = convert2engstrs(yy); tomwalters@0: set(hax_freq,'yticklabel',cs); tomwalters@0: set(get(hax_freq,'ylabel'),'string',['Frequency, ' eu 'Hz']); tomwalters@0: tomwalters@0: % Update time-axis labels for engineering units, etc: tomwalters@0: yy=get(hax_time,'xtick'); tomwalters@0: [cs,eu] = convert2engstrs(yy,'time'); tomwalters@0: set(hax_time,'xticklabel',cs); tomwalters@0: set(get(hax_time,'xlabel'),'string',['Time, ' eu]); tomwalters@0: tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function update_gui(hco, eventStruct, hfig) tomwalters@0: tomwalters@0: if nargin<3, hfig=gcbf; end tomwalters@0: tomwalters@0: ptr.ptr = get(hfig,'pointer'); tomwalters@0: ptr.shape = get(hfig,'pointershapecdata'); tomwalters@0: ptr.hot = get(hfig,'pointershapehotspot'); tomwalters@0: setptr(hfig,'watch'); % set user's expectations... tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_spec = ud.hax(1); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: hax_tslice = ud.hax(3); tomwalters@0: hax_freq = ud.hax(4); tomwalters@0: hax_cbar = ud.hax(5); tomwalters@0: hax_cbar_ind = ud.hax(6); tomwalters@0: tomwalters@0: % Get spectrogram parameters: tomwalters@0: Nwin = str2double(get(ud.spect.nwin,'string')); tomwalters@0: Nlap = str2double(get(ud.spect.nlap,'string')); tomwalters@0: Nfft = str2double(get(ud.spect.nfft,'string')); tomwalters@0: tomwalters@0: % Recompute spectrogram tomwalters@0: y = ud.y; tomwalters@0: Fs = ud.Fs; tomwalters@0: window = 'blackman'; tomwalters@0: w = feval(window,Nwin,'periodic'); tomwalters@0: try tomwalters@0: [b,f,t]=specgram(y,Nfft,Fs,w,Nlap); tomwalters@0: [Pxx, W] = pwelch(y,w,Nlap,Nfft,Fs); tomwalters@0: catch tomwalters@0: % Error occurred tomwalters@0: % Put up modal error display, then tomwalters@0: % get spectrogram params from cache (userdata) tomwalters@0: msg = lasterr; tomwalters@0: errordlg(msg,'Specgram Demo Error','modal'); tomwalters@0: tomwalters@0: % Reset Nwin/Nlap/Nfft: tomwalters@0: Nwin = get(ud.spect.nwin,'userdata'); tomwalters@0: Nlap = get(ud.spect.nlap,'userdata'); tomwalters@0: Nfft = get(ud.spect.nfft,'userdata'); tomwalters@0: set(ud.spect.nwin,'string',num2str(Nwin)); tomwalters@0: set(ud.spect.nlap,'string',num2str(Nlap)); tomwalters@0: set(ud.spect.nfft,'string',num2str(Nfft)); tomwalters@0: return tomwalters@0: end tomwalters@0: tomwalters@0: % Update new values into "old" cache (userdata field) tomwalters@0: % Also, update strings themselves, in case spaces have tomwalters@0: % been removed, etc: tomwalters@0: set(ud.spect.nwin,'string',num2str(Nwin),'userdata',Nwin); tomwalters@0: set(ud.spect.nlap,'string',num2str(Nlap),'userdata',Nlap); tomwalters@0: set(ud.spect.nfft,'string',num2str(Nfft),'userdata',Nfft); tomwalters@0: tomwalters@0: ud.f = f; tomwalters@0: ud.t = t; tomwalters@0: tomwalters@0: % Pxx is the distribution of power per unit frequency. tomwalters@0: ud.Pxx = Pxx; tomwalters@0: tomwalters@0: % W is the vector of normalized frequencies at which the PSD is estimated. tomwalters@0: ud.w = W; tomwalters@0: tomwalters@0: % Carefully execute log10: tomwalters@0: wstate=warning; tomwalters@0: warning off; tomwalters@0: b = 20*log10(abs(b)); tomwalters@0: warning(wstate); tomwalters@0: tomwalters@0: % Handle -inf's: tomwalters@0: i_inf = find(isinf(b(:))); tomwalters@0: if ~isempty(i_inf), tomwalters@0: % Set all -inf points to next-lowest value: tomwalters@0: b(i_inf)=inf; tomwalters@0: min_val=min(b(:)); tomwalters@0: b(i_inf)=min_val; tomwalters@0: end tomwalters@0: tomwalters@0: blim = [min(b(:)) max(b(:))]; tomwalters@0: spec_xlim = [0 max(t)]; tomwalters@0: spec_ylim = [0 max(f)]; tomwalters@0: tomwalters@0: % Update spectrogram tomwalters@0: % XXX UINT8 change: tomwalters@0: set(ud.himage,'cdata',b, 'xdata',t, 'ydata',f); tomwalters@0: %set(ud.himage,'cdata',uint8( (b-blim(1))./(blim(2)-blim(1))*255 + 1 ), 'xdata',t, 'ydata',f); tomwalters@0: set(hax_spec,'xlim',spec_xlim, 'ylim', spec_ylim); tomwalters@0: tomwalters@0: % Update colorbar tomwalters@0: %XXX UINT8 change: tomwalters@0: set(ud.himage_cbar, 'ydata',blim, 'cdata', (1:256)'); tomwalters@0: %set(ud.himage_cbar, 'ydata',[1 256], 'cdata', (1:256)'); tomwalters@0: set(hax_cbar,'ylim',blim); tomwalters@0: set(hax_cbar_ind, 'ylim',blim); tomwalters@0: tomwalters@0: % Update time slice tomwalters@0: rows=size(b,1); tomwalters@0: bi=floor(rows/2); if bi<1, bi=1; end tomwalters@0: set(ud.htslice_line,'xdata',t, 'ydata',b(bi,:)); tomwalters@0: set(hax_tslice, 'xlim',spec_xlim, 'ylim',blim); tomwalters@0: % Use 2 ticks only tomwalters@0: new_ticks = return2ticks(hax_tslice); tomwalters@0: set(hax_tslice,'Ytick',new_ticks); tomwalters@0: tomwalters@0: % frequency slice tomwalters@0: cols=size(b,2); tomwalters@0: bj=floor(cols/2); if bj<1, bj=1; end tomwalters@0: set(ud.hfreq_line, 'xdata',b(:,bj),'ydata',f); tomwalters@0: set(hax_freq, 'ylim',spec_ylim,'xlim',blim); tomwalters@0: tomwalters@0: % Use 2 ticks only tomwalters@0: new_xticks = return2ticks(ud.hax(4)); tomwalters@0: set(ud.hax(4),'Xtick',new_xticks); tomwalters@0: tomwalters@0: tomwalters@0: % full time trace tomwalters@0: ylen=length(y); tomwalters@0: half_nfft = ceil(Nfft/2); tomwalters@0: t1=(0 : length(y)-half_nfft)/Fs; tomwalters@0: set(ud.htime_plot,'xdata',t1,'ydata',y(half_nfft:end)); tomwalters@0: set(hax_time, 'xlim',spec_xlim); tomwalters@0: tomwalters@0: update_axes_with_eng_units(hfig); tomwalters@0: tomwalters@0: % setup thumbnail patch tomwalters@0: axylim = get(hax_time,'ylim'); tomwalters@0: ymax = axylim(2); tomwalters@0: ymin = axylim(1); tomwalters@0: tmax = max(t); tomwalters@0: tmin = min(t); tomwalters@0: set(ud.hthumb, ... tomwalters@0: 'xdata',[tmin tmax tmax tmin tmin], ... tomwalters@0: 'ydata',[ymin ymin ymax ymax ymin]); tomwalters@0: tomwalters@0: % Reset crosshair positions tomwalters@0: crosshair = ud.crosshair; tomwalters@0: crosshair.xctr = mean(spec_xlim); tomwalters@0: crosshair.yctr = mean(spec_ylim); tomwalters@0: time_ylim = get(hax_time,'ylim'); tomwalters@0: freq_xlim = get(hax_freq,'xlim'); tomwalters@0: tslice_ylim = get(hax_tslice,'ylim'); tomwalters@0: tomwalters@0: % Crosshairs: tomwalters@0: set(ud.hspec_x, ... tomwalters@0: 'xdata',spec_xlim, ... tomwalters@0: 'ydata',[crosshair.yctr crosshair.yctr]); tomwalters@0: set(ud.hspec_y, ... tomwalters@0: 'xdata',[crosshair.xctr crosshair.xctr], ... tomwalters@0: 'ydata',spec_ylim); tomwalters@0: set(ud.htime_y, ... tomwalters@0: 'xdata',[crosshair.xctr crosshair.xctr], ... tomwalters@0: 'ydata',time_ylim); tomwalters@0: set(ud.htslice_y, ... tomwalters@0: 'xdata',[crosshair.xctr crosshair.xctr], ... tomwalters@0: 'ydata',tslice_ylim); tomwalters@0: set(ud.hfreq_x, ... tomwalters@0: 'xdata',freq_xlim, ... tomwalters@0: 'ydata',[crosshair.yctr crosshair.yctr]); tomwalters@0: tomwalters@0: % Colormap indicator triangle: tomwalters@0: dy_tri=.025*diff(blim); tomwalters@0: yp=b(bi,bj); tomwalters@0: ytri=[yp+dy_tri yp-dy_tri yp ]; tomwalters@0: set(ud.hcmap_arrow, ... tomwalters@0: 'erase','xor', ... tomwalters@0: 'linestyle','none', ... tomwalters@0: 'xdata',[0 0 1], ... tomwalters@0: 'ydata',ytri); tomwalters@0: crosshair.cbar.dy_tri = dy_tri; tomwalters@0: tomwalters@0: % Update user data: tomwalters@0: ud.crosshair = crosshair; tomwalters@0: set(hfig,'userdata',ud); tomwalters@0: tomwalters@0: % Text readouts: tomwalters@0: update_time_readout(hfig); tomwalters@0: update_freq_readout(hfig); tomwalters@0: update_dB_readout(hfig); tomwalters@0: %xxx tomwalters@0: %str=[num2str(b(bi,bj)) ' dB']; tomwalters@0: %set(ud.htext_mag,'string',str); tomwalters@0: tomwalters@0: % Re-establish pointer cursor, etc: tomwalters@0: set(hfig,'pointer',ptr.ptr, ... tomwalters@0: 'pointershapecdata',ptr.shape, ... tomwalters@0: 'pointershapehotspot',ptr.hot); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function printdlg_cb(hco,eventStruct) tomwalters@0: printdlg(gcbf); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function printpreview_cb(hco,eventStruct) tomwalters@0: printpreview(gcbf); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function close_cb(hco,eventStruct) tomwalters@0: close(gcbf); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function hfig=create_gui(y,Fs,tmin,tmax) tomwalters@0: %CREATE_GUI Render the figure and all uicontrols. tomwalters@0: tomwalters@0: % freq, specgram and time tomwalters@0: hfig = figure('numbertitle','off', ... tomwalters@0: 'name','Spectrogram Demo', ... tomwalters@0: 'menubar','none', ... tomwalters@0: 'toolbar','none', ... tomwalters@0: 'resizefcn',@resize_fig, ... tomwalters@0: 'doublebuffer','off', ... tomwalters@0: 'backingstore','off', ... tomwalters@0: 'integerhandle','off', ... tomwalters@0: 'vis','off', ... tomwalters@0: 'pos',[50 15 550 450],... tomwalters@0: 'PaperPositionMode','auto'); tomwalters@0: tomwalters@0: % Try to create audioplayer object for audio playback and tracking cursor tomwalters@0: audioplayer_enabled = true; tomwalters@0: try tomwalters@0: player = audioplayer(y / abs(max(y)), Fs); %make a player for the normalized signal tomwalters@0: set(player, 'UserData', hfig, 'TimerPeriod', 0.05, 'TimerFcn', @update_audio_position, ... tomwalters@0: 'StartFcn', @start_function); tomwalters@0: % the toolbar callback fcns look for these named bits of appdata tomwalters@0: setappdata(hfig, 'theAudioPlayer', player); tomwalters@0: setappdata(hfig, 'theAudioRecorder', []); tomwalters@0: selection.inPoint = tmin*Fs; tomwalters@0: selection.outPoint = tmax*Fs; tomwalters@0: setappdata(hfig, 'audioSelection', selection); % selection starts as "full" tomwalters@0: catch tomwalters@0: audioplayer_enabled = false; tomwalters@0: end tomwalters@0: tomwalters@0: % Load toolbar icons tomwalters@0: icon_file = 'specgramdemoicons.mat'; tomwalters@0: icon = load(icon_file); tomwalters@0: tomwalters@0: % Create toolbar: tomwalters@0: htoolbar = uitoolbar(hfig); tomwalters@0: tomwalters@0: % Print: tomwalters@0: uipushtool('parent',htoolbar, ... tomwalters@0: 'tooltip','Print', ... tomwalters@0: 'clickedcallback',@printdlg_cb, ... tomwalters@0: 'cdata',icon.print); tomwalters@0: % Print preview: tomwalters@0: uipushtool('parent',htoolbar, ... tomwalters@0: 'tooltip','Print Preview', ... tomwalters@0: 'clickedcallback',@printpreview_cb, ... tomwalters@0: 'cdata',icon.printpreview); tomwalters@0: tomwalters@0: if audioplayer_enabled, tomwalters@0: % add Play/Pause/Stop audio toolbar buttons tomwalters@0: [htoolbar, audiobuttons] = render_basicaudiotoolbar(htoolbar); tomwalters@0: tomwalters@0: % set play button to "active" version, because changing the button image tomwalters@0: % causes the whole darn window to repaint! Ick. tomwalters@0: play_button = audiobuttons(1); tomwalters@0: audioIcons = getappdata(htoolbar, 'audioButtonIcons'); tomwalters@0: set(play_button, 'cdata', audioIcons.play_on); tomwalters@0: else tomwalters@0: % Play icon tomwalters@0: uipushtool('parent',htoolbar, ... tomwalters@0: 'tooltip','Play', ... tomwalters@0: 'clickedcallback',@play_sound, ... tomwalters@0: 'cdata',icon.playsound); tomwalters@0: end tomwalters@0: tomwalters@0: % Zoom in, out, full tomwalters@0: uipushtool('parent',htoolbar, ... tomwalters@0: 'separator','on', ... tomwalters@0: 'tooltip','Zoom 100%', ... tomwalters@0: 'clickedcallback', @zoom_full, ... tomwalters@0: 'cdata',icon.fullview); tomwalters@0: uipushtool('parent',htoolbar, ... tomwalters@0: 'tooltip','Zoom In', ... tomwalters@0: 'clickedcallback',@zoom_in, ... tomwalters@0: 'cdata',icon.zoominx); tomwalters@0: uipushtool('parent',htoolbar, ... tomwalters@0: 'tooltip','Zoom Out', ... tomwalters@0: 'clickedcallback',@zoom_out, ... tomwalters@0: 'cdata',icon.zoomoutx); tomwalters@0: % Center crosshairs tomwalters@0: uipushtool('parent',htoolbar, ... tomwalters@0: 'tooltip','Center Crosshair', ... tomwalters@0: 'clickedcallback',@center_cross, ... tomwalters@0: 'separator','on', ... tomwalters@0: 'cdata',icon.center_crosshair); tomwalters@0: tomwalters@0: % What's this? tomwalters@0: uipushtool('parent',htoolbar, ... tomwalters@0: 'separator','on', ... tomwalters@0: 'tooltip','What''s This?', ... tomwalters@0: 'clickedcallback',@HelpWhatsThisCB, ... tomwalters@0: 'cdata',icon.whatsthis); tomwalters@0: tomwalters@0: % specgram tomwalters@0: % inputs: t, f, b tomwalters@0: hax_spec = axes('pos',[.25 .275 .625 .525]); tomwalters@0: himage=image; axis xy; colormap(jet) tomwalters@0: set(himage,'erase','xor','cdatamapping','scaled'); tomwalters@0: set(hax_spec, ... tomwalters@0: 'box','on', ... tomwalters@0: 'draw','fast', ... tomwalters@0: 'xticklabel',''); tomwalters@0: % xxx tomwalters@0: % Shut off image axis visibility tomwalters@0: set(hax_spec, 'vis','off'); tomwalters@0: tomwalters@0: % time slice tomwalters@0: hax_tslice = axes('pos',[.25 .825 .625 .1]); tomwalters@0: htslice_line=line('color','b'); tomwalters@0: set(htslice_line,'erase','xor'); % xxx tomwalters@0: set(hax_tslice, ... tomwalters@0: 'box','on', ... tomwalters@0: 'fontsize',8, ... tomwalters@0: 'draw','fast', ... tomwalters@0: 'xticklabel','', ... tomwalters@0: 'xtick',[], ... tomwalters@0: 'yaxisloc','right'); tomwalters@0: ylabel('dB'); tomwalters@0: sz=size(y); tomwalters@0: tomwalters@0: % Title of time slice plot tomwalters@0: [ey,ee,eu]=engunits(Fs,'latex'); tomwalters@0: str=['Data=[' num2str(sz(1)) 'x' num2str(sz(2)) '], Fs=' ... tomwalters@0: num2str(ey) ' ' eu 'Hz']; tomwalters@0: title(str); tomwalters@0: tomwalters@0: % colorbar tomwalters@0: cmapLen = 256; tomwalters@0: hax_cbar = axes('pos',[.91 .275 .03 .525]); tomwalters@0: himage_cbar = image([0 1],[0 1],(1:cmapLen)'); tomwalters@0: set(himage_cbar,'cdatamapping','scaled','erase','none'); tomwalters@0: set(hax_cbar, ... tomwalters@0: 'draw','fast', ... tomwalters@0: 'fontsize',8, ... tomwalters@0: 'box','on', ... tomwalters@0: 'xticklabel','', ... tomwalters@0: 'Ydir','normal', 'YAxisLocation','right', 'xtick',[]); tomwalters@0: tomwalters@0: % frequency slice tomwalters@0: hax_freq = axes('pos',[.1 .275 .125 .525]); tomwalters@0: hfreq_line=line('color','b'); tomwalters@0: set(hfreq_line,'erase','xor'); tomwalters@0: set(hax_freq, ... tomwalters@0: 'fontsize',8, ... tomwalters@0: 'box','on',... tomwalters@0: 'draw','fast', ... tomwalters@0: 'xdir','rev', ... tomwalters@0: 'xaxisloc','top'); tomwalters@0: ylabel('Frequency, Hz'); tomwalters@0: xlabel('dB'); tomwalters@0: tomwalters@0: % colorbar indicator tomwalters@0: hax_cbar_ind = axes('pos',[.885+.01 .275 .015 .525]); tomwalters@0: set(hax_cbar_ind,'vis','off','xlim',[0 1],'ylim',[0 1], ... tomwalters@0: 'draw','fast', ... tomwalters@0: 'fontsize',8, ... tomwalters@0: 'yaxisloc','right'); tomwalters@0: tomwalters@0: % full time trace tomwalters@0: % inputs: y, Fs tomwalters@0: hax_time = axes('pos',[.25 .15 .625 .1]); tomwalters@0: htime_plot = line('color','b'); tomwalters@0: set(hax_time, ... tomwalters@0: 'box','on',... tomwalters@0: 'fontsize',8, ... tomwalters@0: 'draw','fast', ... tomwalters@0: 'yaxisloc','right'); tomwalters@0: xlabel('Time, secs'); ylabel('Ampl'); tomwalters@0: tomwalters@0: % thumbnail patch tomwalters@0: %bgclr = get(0,'defaultuicontrolbackgr'); tomwalters@0: %bgclr = get(0,'defaultfigurecolor'); tomwalters@0: bgclr = 'b'; tomwalters@0: hthumb = patch([0 0 1 1 0], [0 1 1 0 0], bgclr, ... tomwalters@0: 'edgecolor','k', ... tomwalters@0: 'erase','xor'); tomwalters@0: tomwalters@0: % Crosshairs: tomwalters@0: hspec_x=line('parent',hax_spec, ... tomwalters@0: 'erase','xor'); tomwalters@0: hspec_y=line('parent',hax_spec, ... tomwalters@0: 'erase','xor'); tomwalters@0: htime_y=line('parent',hax_time, ... tomwalters@0: 'linewidth',2, ... tomwalters@0: 'erase','xor'); tomwalters@0: htslice_y=line('parent',hax_tslice, ... tomwalters@0: 'erase','xor'); tomwalters@0: hfreq_x=line('parent',hax_freq, ... tomwalters@0: 'erase','xor'); tomwalters@0: tomwalters@0: % Colormap indicator triangle: tomwalters@0: hcmap_arrow=patch('parent',hax_cbar_ind, ... tomwalters@0: 'xdata',[0 0 1], ... tomwalters@0: 'ydata',[0 0 0]); tomwalters@0: tomwalters@0: % Text readouts: tomwalters@0: % xxx tomwalters@0: hax_readout = axes('pos',[0.02 .09 .185 .15],'vis','off'); tomwalters@0: patch([0 1 1 0 0],[0 0 1 1 0],'w'); tomwalters@0: htext_time = text('parent',hax_readout, 'pos',[0.075 .8], ... tomwalters@0: 'erase','xor'); tomwalters@0: htext_freq = text('parent',hax_readout, 'pos',[0.075 .5], ... tomwalters@0: 'erase','xor'); tomwalters@0: htext_mag = text('parent',hax_readout, 'pos',[0.075 .2], ... tomwalters@0: 'erase','xor'); tomwalters@0: tomwalters@0: % Status bar tomwalters@0: bgc=get(hfig,'color'); tomwalters@0: hax_status = axes('pos',[0.005 0.01 .99 .04]); tomwalters@0: set(hax_status,'vis','off','xlim',[0 1],'ylim',[0 1]); tomwalters@0: % Main status: tomwalters@0: h1=line([0 .45 .45],[0 0 1],'color','w'); tomwalters@0: h2=line([0 0 .45],[0 1 1],'color',[1 1 1]*0); tomwalters@0: htext_status = uicontrol('parent',hfig, ... tomwalters@0: 'style','text', ... tomwalters@0: 'units','norm', ... tomwalters@0: 'pos',[.015 .012 .96-.55 .035], ... tomwalters@0: 'horiz','left', ... tomwalters@0: 'backgr',bgc, ... tomwalters@0: 'string','Ready'); tomwalters@0: tomwalters@0: % Spectrogram controls: tomwalters@0: % tomwalters@0: % segment length tomwalters@0: ylen = length(y); tomwalters@0: Nfft = min(256,ylen); tomwalters@0: Nwin = Nfft; tomwalters@0: % Nlap = min(Nwin,ceil(Nwin/2)); tomwalters@0: Nlap = min(Nwin,200); tomwalters@0: ud.spect.nwin_text = uicontrol('parent',hfig, ... tomwalters@0: 'style','text', ... tomwalters@0: 'units','norm', ... tomwalters@0: 'pos', [.45 .012 .07 .035], ... tomwalters@0: 'backgr',bgc, ... tomwalters@0: 'horiz','right', ... tomwalters@0: 'string','Nwin:'); tomwalters@0: ud.spect.nwin = uicontrol('parent',hfig, ... tomwalters@0: 'style','edit', ... tomwalters@0: 'units','norm', ... tomwalters@0: 'pos', [.45+.07+.005 .01 .08 .04], ... tomwalters@0: 'backgr','white', ... tomwalters@0: 'horiz','left', ... tomwalters@0: 'string',num2str(Nwin), ... tomwalters@0: 'callback',@update_gui); tomwalters@0: % overlap length tomwalters@0: ud.spect.nlap_text = uicontrol('parent',hfig, ... tomwalters@0: 'style','text', ... tomwalters@0: 'units','norm', ... tomwalters@0: 'pos', [.61 .012 .06 .035], ... tomwalters@0: 'backgr',bgc, ... tomwalters@0: 'horiz','right', ... tomwalters@0: 'string','Nlap:'); tomwalters@0: ud.spect.nlap = uicontrol('parent',hfig, ... tomwalters@0: 'style','edit', ... tomwalters@0: 'units','norm', ... tomwalters@0: 'pos', [.61+.06+.005 .01 .08 .04], ... tomwalters@0: 'backgr','white', ... tomwalters@0: 'horiz','left', ... tomwalters@0: 'string',num2str(Nlap), ... tomwalters@0: 'callback',@update_gui); tomwalters@0: % fft length tomwalters@0: ud.spect.nfft_text = uicontrol('parent',hfig, ... tomwalters@0: 'style','text', ... tomwalters@0: 'units','norm', ... tomwalters@0: 'pos', [.76 .012 .05 .035], ... tomwalters@0: 'backgr', bgc, ... tomwalters@0: 'horiz','right', ... tomwalters@0: 'string','Nfft:'); tomwalters@0: ud.spect.nfft = uicontrol('parent',hfig, ... tomwalters@0: 'style','edit', ... tomwalters@0: 'units','norm', ... tomwalters@0: 'pos', [.75+.06+.005 .01 .08 .04], ... tomwalters@0: 'backgr','white', ... tomwalters@0: 'horiz','left', ... tomwalters@0: 'string',num2str(Nfft), ... tomwalters@0: 'callback',@update_gui); tomwalters@0: tomwalters@0: % Window tomwalters@0: tomwalters@0: % Menus tomwalters@0: mFile = uimenu('parent',hfig,'label','&File'); tomwalters@0: uimenu('parent',mFile,'label','&Print','callback',@printdlg_cb); tomwalters@0: uimenu('parent',mFile,'label','&Close', ... tomwalters@0: 'callback',@close_cb,'separator','on'); tomwalters@0: tomwalters@0: uimenu('parent',hfig, 'label','&Window', ... tomwalters@0: 'tag','winmenu', ... tomwalters@0: 'callback', winmenu('callback')); tomwalters@0: % tomwalters@0: % Help menu: tomwalters@0: % tomwalters@0: mHelp = uimenu('parent',hfig,'label','&Help'); tomwalters@0: tomwalters@0: % Help -> Specgramdemo Help tomwalters@0: uimenu('parent',mHelp, ... tomwalters@0: 'Label','Spectrogram Demo &Help', ... tomwalters@0: 'Callback',@HelpSpecgramdemoCB); tomwalters@0: tomwalters@0: % Help -> Signal Processing Toolbox Help tomwalters@0: uimenu('parent',mHelp, ... tomwalters@0: 'Label','Signal Processing &Toolbox Help', ... tomwalters@0: 'Callback',@HelpProductCB); tomwalters@0: tomwalters@0: % Help -> What's This? tomwalters@0: uimenu('parent',mHelp, ... tomwalters@0: 'Label','&What''s This?', ... tomwalters@0: 'Callback', @HelpWhatsThisCB,... tomwalters@0: 'Separator','On'); tomwalters@0: tomwalters@0: % Help -> Demos tomwalters@0: uimenu('parent',mHelp, ... tomwalters@0: 'Label','&Demos', ... tomwalters@0: 'Callback',@HelpDemosCB,... tomwalters@0: 'Separator','On'); tomwalters@0: tomwalters@0: % Help -> About Signal Processing Toolbox tomwalters@0: uimenu('parent',mHelp, ... tomwalters@0: 'Label','&About Signal Processing Toolbox', ... tomwalters@0: 'Callback',@HelpAboutCB,... tomwalters@0: 'Separator','On'); tomwalters@0: tomwalters@0: set(hfig,'colormap',jet(256)); tomwalters@0: tomwalters@0: % Retain info in figure userdata: tomwalters@0: ud.hfig = hfig; tomwalters@0: ud.hax = [hax_spec hax_time hax_tslice hax_freq hax_cbar hax_cbar_ind]; tomwalters@0: ud.hspec_x = hspec_x; tomwalters@0: ud.hspec_y = hspec_y; tomwalters@0: ud.htime_y = htime_y; tomwalters@0: ud.htslice_y = htslice_y; tomwalters@0: ud.hfreq_x = hfreq_x; tomwalters@0: ud.hcmap_arrow = hcmap_arrow; tomwalters@0: ud.hfreq_line = hfreq_line; tomwalters@0: ud.htslice_line = htslice_line; tomwalters@0: ud.htime_plot = htime_plot; tomwalters@0: ud.htext_time = htext_time; tomwalters@0: ud.htext_freq = htext_freq; tomwalters@0: ud.htext_mag = htext_mag; tomwalters@0: ud.htext_status= htext_status; tomwalters@0: ud.crosshair = []; tomwalters@0: ud.himage = himage; tomwalters@0: ud.himage_cbar = himage_cbar; tomwalters@0: ud.hthumb = hthumb; tomwalters@0: ud.f=[]; tomwalters@0: ud.t=[]; tomwalters@0: ud.y=y; tomwalters@0: ud.Fs=Fs; tomwalters@0: ud.currPtr = ''; % current pointer tomwalters@0: ud.Pxx = []; tomwalters@0: ud.w = []; tomwalters@0: tomwalters@0: % Set plot default modes: tomwalters@0: ud.plot.top = 'spectrogram_time_slice'; tomwalters@0: ud.plot.left = 'spectrogram_freq_slice'; tomwalters@0: tomwalters@0: set(hfig,'userdata',ud); tomwalters@0: tomwalters@0: winmenu(hfig); % Initialize the submenu, after ud is installed tomwalters@0: tomwalters@0: % Protect GUI from user plots, etc: tomwalters@0: set([hfig ud.hax],'handlevis','callback'); tomwalters@0: tomwalters@0: % After GUI has all elements in it, install context help: tomwalters@0: install_context_help(hfig); tomwalters@0: install_context_menus(hfig); tomwalters@0: tomwalters@0: % Populate GUI with data, limits, etc: tomwalters@0: update_gui([],[],hfig); tomwalters@0: tomwalters@0: % Enable general (non-segmenting) mouse functions: tomwalters@0: install_cursorfcns(hfig,'general'); tomwalters@0: set(hfig,'vis','on'); tomwalters@0: tomwalters@0: %%%%%%%%%%%%%%%%%%%%%%%%%% tomwalters@0: % inserted by S.Bleeck tomwalters@0: % switch to modal tomwalters@0: uiwait(hfig); tomwalters@0: %%%%%%%%%%%%%%%%%%%%%%%%%% tomwalters@0: tomwalters@0: tomwalters@0: tomwalters@0: return tomwalters@0: tomwalters@0: % --------------------------------------------------------------- tomwalters@0: % H E L P S Y S T E M tomwalters@0: % -------------------------------------------------------------- tomwalters@0: % tomwalters@0: % General rules: tomwalters@0: % - Context menus that launch the "What's This?" item have their tomwalters@0: % tag set to 'WT?...', where the '...' is the "keyword" for the tomwalters@0: % help lookup system. tomwalters@0: % tomwalters@0: tomwalters@0: %-------------------------------------------------------------- tomwalters@0: function HelpWhatsThisBDown(hco,eventStruct) tomwalters@0: % HelpWhatsThisBDown Button-down function called from either tomwalters@0: % the menu-based "What's This?" function, or the toolbar icon. tomwalters@0: tomwalters@0: hfig = gcbf; tomwalters@0: hOver = gcbo; % overobj('uicontrol'); % handle to object under pointer tomwalters@0: tomwalters@0: % Restore pointer icon quickly: tomwalters@0: setptr(hfig,'arrow'); tomwalters@0: tomwalters@0: % Shut off button-down functions for uicontrols and the figure: tomwalters@0: hChildren = findobj(hfig); tomwalters@0: set(hChildren, 'ButtonDownFcn',''); tomwalters@0: set(hfig,'WindowButtonDownFcn',''); tomwalters@0: tomwalters@0: % Restore GUI pointers, etc: tomwalters@0: wbmotion_general(hfig); tomwalters@0: tomwalters@0: % Dispatch to context help: tomwalters@0: hc = get(hOver,'uicontextmenu'); tomwalters@0: hm = get(hc,'children'); % menu(s) pointed to by context menu tomwalters@0: tomwalters@0: % Multiple entries (children) of context-menu may be present tomwalters@0: % Tag is a string, but we may get a cell-array of strings if tomwalters@0: % multiple context menus are present: tomwalters@0: % Find 'What's This?' help entry tomwalters@0: tag = get(hm,'tag'); tomwalters@0: helpIdx = find(strncmp(tag,'WT?',3)); tomwalters@0: if ~isempty(helpIdx), tomwalters@0: % in case there were accidentally multiple 'WT?' entries, tomwalters@0: % take the first (and hopefully, the only) index: tomwalters@0: if iscell(tag), tomwalters@0: tag = tag{helpIdx(1)}; tomwalters@0: end tomwalters@0: HelpGeneral([],[],tag); tomwalters@0: end tomwalters@0: tomwalters@0: %-------------------------------------------------------------- tomwalters@0: function HelpWhatsThisCB(hco, eventStruct) tomwalters@0: % HelpWhatsThisCB Get "What's This?" help tomwalters@0: % This mimics the context-menu help selection, but allows tomwalters@0: % cursor-selection of the help topic tomwalters@0: tomwalters@0: % NOTE: Enabling context-help "destroys" the enable-state tomwalters@0: % of all uicontrols in the GUI. When the callback completes, tomwalters@0: % we must restore the enable states. tomwalters@0: tomwalters@0: hfig = gcbf; tomwalters@0: tomwalters@0: % Change pointer icon: tomwalters@0: setptr(hfig,'help'); tomwalters@0: tomwalters@0: % Install button-down functions on all uicontrols, tomwalters@0: % plus the figure itself: tomwalters@0: % uicontrol, axes, line, patch, text tomwalters@0: hChildren = findobj(hfig); tomwalters@0: % No need to set enable states, etc. tomwalters@0: set(hChildren, ... tomwalters@0: 'ButtonDownFcn',@HelpWhatsThisBDown); tomwalters@0: set(hfig, ... tomwalters@0: 'WindowButtonMotionFcn','', ... tomwalters@0: 'WindowButtonUpFcn','', ... tomwalters@0: 'WindowButtonDownFcn',''); tomwalters@0: tomwalters@0: %-------------------------------------------------------------- tomwalters@0: function HelpSpecgramdemoCB(hco,eventStruct) tomwalters@0: %HELPSPECGRAMDEMO Get specgramdemo reference-page help tomwalters@0: tomwalters@0: helpwin(mfilename); tomwalters@0: tomwalters@0: %-------------------------------------------------------------- tomwalters@0: function HelpProductCB(hco,eventStruct) tomwalters@0: %HELPRPODUCTCB Opens the Help window with the online doc Roadmap tomwalters@0: % page (a.k.a. "product page") displayed. tomwalters@0: doc signal/ tomwalters@0: tomwalters@0: %-------------------------------------------------------------- tomwalters@0: function HelpDemosCB(hco,eventStruct) tomwalters@0: %HELPDEMOSCB Starts Demo window, with the appropriate product's tomwalters@0: % demo highlighted in the Demo window contents pane. tomwalters@0: demo toolbox signal tomwalters@0: tomwalters@0: %-------------------------------------------------------------- tomwalters@0: function HelpAboutCB(hco,eventStruct) tomwalters@0: %HELPABOUTCB Displays version number of product, and copyright. tomwalters@0: tomwalters@0: aboutsignaltbx; tomwalters@0: tomwalters@0: %-------------------------------------------------------------- tomwalters@0: function HelpGeneral(hco,eventStruct,tag) tomwalters@0: % HelpGeneral Define CSH text for specgramdemo tomwalters@0: tomwalters@0: hfig = gcbf; tomwalters@0: hco = gcbo; tomwalters@0: tomwalters@0: if nargin<3, tomwalters@0: % Testing purposes only: tomwalters@0: tag = get(hco,'tag'); tomwalters@0: end tomwalters@0: tomwalters@0: % Check for legal tag string: tomwalters@0: if ~ischar(tag), tomwalters@0: error('Invalid context-sensitive help tag.'); tomwalters@0: end tomwalters@0: tomwalters@0: % Remove 'WT?' prefix; tomwalters@0: if strncmp(tag,'WT?',3), tomwalters@0: tag(1:3) = []; tomwalters@0: else tomwalters@0: error('Help tag must be a string beginning with "WT?" prefix.'); tomwalters@0: end tomwalters@0: tomwalters@0: ud = get(hfig,'UserData'); tomwalters@0: tomwalters@0: % Define text for CSH system tomwalters@0: title = ['Help: ' tag]; tomwalters@0: msg = ''; tomwalters@0: switch tag tomwalters@0: case '' tomwalters@0: msg = {''; tomwalters@0: 'No help available on selected item.'}; tomwalters@0: tomwalters@0: case 'Spectrogram image' tomwalters@0: msg = {''; tomwalters@0: 'This image displays the spectrogram for the signal currently loaded '; tomwalters@0: 'in the viewer. The spectrogram presents the magnitude of the short-time '; tomwalters@0: 'Fourier transform.'; tomwalters@0: ''; tomwalters@0: 'Calculate the spectrogram as follows:'; tomwalters@0: ''; tomwalters@0: '1. Split the signal into overlapping sections and apply the'; tomwalters@0: 'window specified by the window parameter to each section.'; tomwalters@0: ''; tomwalters@0: '2. Compute the discrete-time Fourier transform of each'; tomwalters@0: 'section with a length Nfft FFT to estimate the short-term '; tomwalters@0: 'frequency content of the signal. These transforms '; tomwalters@0: 'make up the columns of B. The quantity (length(Nwin) - Nlap)' tomwalters@0: 'specifies by how many samples the window will be shifted.'; tomwalters@0: ''; tomwalters@0: '3. For real input, truncate the spectrogram to the'; tomwalters@0: 'first (Nfft/2 + 1) points when Nfft is even and (Nfft + 1)/2 when '; tomwalters@0: 'Nfft is odd.'}; tomwalters@0: tomwalters@0: case 'Zoom Window Panner' tomwalters@0: msg = {''; tomwalters@0: 'Shows a panoramic view of the signal which is loaded in the viewer. '; tomwalters@0: 'When you zoom in the spectrogram, the corresponding time domain '; tomwalters@0: 'portion is highlighed.'; tomwalters@0: ''; tomwalters@0: 'You can zoom the panner by dragging the mouse on the left- and '; tomwalters@0: 'right-hand edges of the highlighted zoom region. Right-click the '; tomwalters@0: 'highlighted zoom area to bring up a menu for focusing in on the zoomed '; tomwalters@0: 'region'}; tomwalters@0: tomwalters@0: case 'Spectrogram Frequency Slice' % Left axes tomwalters@0: if strcmp(ud.plot.left,'spectrogram_freq_slice'), tomwalters@0: msg = {''; tomwalters@0: 'This view displays a frequency slice for the current spectrogram. The '; tomwalters@0: 'view is updated as you move the crosshair cursor along the frequency ' tomwalters@0: 'axes (horizontally).'}; tomwalters@0: else tomwalters@0: % Change the helpwin title for the PSD case. tomwalters@0: title = ['Help: Signal Power Spectral Density']; tomwalters@0: tomwalters@0: msg = {''; tomwalters@0: 'Displays the Power Spectral Density (PSD) estimate calculated '; tomwalters@0: 'using Welch''s averaged modified periodogram method.'}; tomwalters@0: tomwalters@0: end tomwalters@0: tomwalters@0: case 'Spectrogram Time Slice', % Top axes tomwalters@0: msg = {''; tomwalters@0: 'This view displays a time slice for the current spectrogram. The'; tomwalters@0: 'view is updated as you move the crosshair cursor along the time' tomwalters@0: 'axes (vertically).'}; tomwalters@0: tomwalters@0: case 'Colorbar' tomwalters@0: msg = {''; tomwalters@0: 'The colorbar shows the color scale for the current spectrogram.'; tomwalters@0: ''}; tomwalters@0: tomwalters@0: case 'Status Bar', tomwalters@0: msg = {''; tomwalters@0: 'The Status Bar displays information about the state of the '; tomwalters@0: 'Spectrogram Demo, the current operation of the tool, and operation'; tomwalters@0: 'of the crosshair cursor.'}; tomwalters@0: tomwalters@0: case 'Magnitude Readout', tomwalters@0: msg = {''; tomwalters@0: 'Displays the magnitude (in dB) of a spectrogram slice.'; tomwalters@0: ''}; tomwalters@0: tomwalters@0: case 'Frequency Readout', tomwalters@0: msg = {''; tomwalters@0: 'Displays frequency values in Hz.'; tomwalters@0: ''}; tomwalters@0: tomwalters@0: case 'Time Readout', tomwalters@0: msg = {''; tomwalters@0: 'Displays time measurements in seconds for the Time Plot '; tomwalters@0: 'and the Time Slice'}; tomwalters@0: tomwalters@0: case 'Time Plot', % Bottom axes tomwalters@0: msg = {''; tomwalters@0: 'Time Plot displays the original signal in its entirety.'}; tomwalters@0: tomwalters@0: case 'Colorbar Indicator', tomwalters@0: msg = {''; tomwalters@0: 'The colorbar indicator points to the level of the spectrogram.'}; tomwalters@0: tomwalters@0: case 'Frequency Crosshair', tomwalters@0: msg = {''; tomwalters@0: 'Move the frequency crosshair cursor to pin-point a particular '; tomwalters@0: 'frequency location on the spectrogram''s frequency slice axes.'}; tomwalters@0: tomwalters@0: case 'Time Crosshair', tomwalters@0: msg = {''; tomwalters@0: 'Move the time crosshair cursor to pin-point a particular '; tomwalters@0: 'time instance on the spectrogram''s time slice axes.'}; tomwalters@0: tomwalters@0: case 'Spectrogram Demo', tomwalters@0: msg = {''; tomwalters@0: 'This is the Spectrogram Demo which displays a spectrogram, '; tomwalters@0: 'a time plot, and a frequency slice of an input signal'; tomwalters@0: ''; tomwalters@0: 'SPECGRAMDEMO(y,Fs) displays a spectrogram of signal y, assuming a sample '; tomwalters@0: 'rate of Fs Hz. If y is specified but Fs is not, a sample rate of 1 '; tomwalters@0: 'Hz is assumed. If no input arguments are supplied, y and Fs are '; tomwalters@0: 'taken from the default data file "mtlb.mat."'}; tomwalters@0: tomwalters@0: case 'Spectrogram Window Size', tomwalters@0: msg = {''; tomwalters@0: 'Nwin specifies the length of the Periodic Blackman window used in '; tomwalters@0: 'this demo. The default value is 256.'}; tomwalters@0: tomwalters@0: case 'Spectrogram FFT Size', tomwalters@0: msg = {''; tomwalters@0: 'Nfft specifies the FFT length used to calculate the spectrogram. '; tomwalters@0: 'This value determines the frequencies at which the discrete-time '; tomwalters@0: 'Fourier transform is computed. These values are typically powers '; tomwalters@0: 'of two, such as 256 or 512.'}; tomwalters@0: tomwalters@0: case 'Spectrogram Overlap' tomwalters@0: msg = {''; tomwalters@0: 'Use Nlap to specify the number of samples to overlap the windowed sections.'}; tomwalters@0: end tomwalters@0: tomwalters@0: % If no text is defined, simply display the tag. tomwalters@0: if isempty(msg), tomwalters@0: msg = {''; tomwalters@0: ['This is the ' tag '.']}; tomwalters@0: end tomwalters@0: tomwalters@0: % Put up message box for help: tomwalters@0: %hmsg = msgbox(msg,title, 'help','modal'); tomwalters@0: %CenterFigOnFig(hfig, hmsg); tomwalters@0: tomwalters@0: helpwin(char(msg),title); tomwalters@0: tomwalters@0: %-------------------------------------------------------------- tomwalters@0: function CenterFigOnFig(hfig,hmsg) tomwalters@0: % CenterFigOnFig Center hMsg figure on top of hFig figure tomwalters@0: tomwalters@0: set(hfig,'units','pix'); tomwalters@0: figPos = get(hfig,'pos'); tomwalters@0: figCtr = [figPos(1)+figPos(3)/2 figPos(2)+figPos(4)/2]; tomwalters@0: tomwalters@0: set(hmsg,'units','pix'); tomwalters@0: msgPos = get(hmsg,'position'); tomwalters@0: msgCtr = [msgPos(1)+msgPos(3)/2 msgPos(2)+msgPos(4)/2]; tomwalters@0: tomwalters@0: movePos = figCtr - msgCtr; tomwalters@0: tomwalters@0: new_msgPos = msgPos; tomwalters@0: new_msgPos(1:2) = msgPos(1:2) + movePos; tomwalters@0: set(hmsg,'Position',new_msgPos); tomwalters@0: tomwalters@0: return tomwalters@0: tomwalters@0: %-------------------------------------------------------------- tomwalters@0: function install_context_help(hfig) tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: tomwalters@0: main = {'label','&What''s This?', ... tomwalters@0: 'callback',@HelpGeneral, 'parent'}; tomwalters@0: tomwalters@0: setWTC(hfig,main, [ud.himage ud.hax(1)], 'Spectrogram image'); tomwalters@0: setWTC(hfig,main, ud.hthumb, 'Zoom Window Panner'); tomwalters@0: setWTC(hfig,main, [ud.himage_cbar ud.hax(5)], 'Colorbar'); tomwalters@0: setWTC(hfig,main, ud.htext_status, 'Status Bar'); tomwalters@0: setWTC(hfig,main, ud.htext_mag, 'Magnitude Readout'); tomwalters@0: setWTC(hfig,main, ud.htext_freq, 'Frequency Readout'); tomwalters@0: setWTC(hfig,main, ud.htext_time, 'Time Readout'); tomwalters@0: setWTC(hfig,main, [ud.htime_plot ud.hax(2)], 'Time Plot'); tomwalters@0: setWTC(hfig,main, [ud.htslice_line ud.hax(3)], 'Spectrogram Time Slice'); tomwalters@0: setWTC(hfig,main, [ud.hfreq_line ud.hax(4)], 'Spectrogram Frequency Slice'); tomwalters@0: setWTC(hfig,main, [ud.hcmap_arrow ud.hax(6)], 'Colorbar Indicator'); tomwalters@0: tomwalters@0: setWTC(hfig,main, [ud.hfreq_x ud.hspec_x], 'Frequency Crosshair'); tomwalters@0: setWTC(hfig,main, [ud.htime_y ud.htslice_y ud.hspec_y], 'Time Crosshair'); tomwalters@0: setWTC(hfig,main, ud.hfig, 'Spectrogram Demo'); tomwalters@0: tomwalters@0: setWTC(hfig,main, [ud.spect.nwin ud.spect.nwin_text], 'Spectrogram Window Size'); tomwalters@0: setWTC(hfig,main, [ud.spect.nfft ud.spect.nfft_text], 'Spectrogram FFT Size'); tomwalters@0: setWTC(hfig,main, [ud.spect.nlap ud.spect.nlap_text], 'Spectrogram Overlap'); tomwalters@0: tomwalters@0: % xxx set context for: tomwalters@0: % - readout axis tomwalters@0: % - uitoolbar tomwalters@0: tomwalters@0: %-------------------------------------------------------------- tomwalters@0: function setWTC(hfig,main,hItem,tagStr) tomwalters@0: % setWT Set the "What's This?" context menu and callback: tomwalters@0: hc = uicontextmenu('parent',hfig); tomwalters@0: uimenu(main{:},hc, 'tag',['WT?' tagStr]); tomwalters@0: set(hItem,'uicontextmenu',hc); tomwalters@0: tomwalters@0: tomwalters@0: % --------------------------------------------------------------- tomwalters@0: % C O N T E X T M E N U S tomwalters@0: % -------------------------------------------------------------- tomwalters@0: tomwalters@0: %----------------------------------------------------------------- tomwalters@0: function install_context_menus(hfig) tomwalters@0: tomwalters@0: install_specgram_mode_menus(hfig); tomwalters@0: install_colorbar_menus(hfig); tomwalters@0: install_freq_slice_menus(hfig); tomwalters@0: install_time_slice_menus(hfig); tomwalters@0: install_time_panner_menus(hfig); tomwalters@0: tomwalters@0: %----------------------------------------------------------------- tomwalters@0: function install_specgram_mode_menus(hfig) tomwalters@0: tomwalters@0: % Additional menus to prepend to the spectrogram context menu: tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hc = get(ud.himage,'uicontext'); % ud.hax(1) also? tomwalters@0: tomwalters@0: hEntry=[]; % holds handles to each colormap menu item tomwalters@0: opts={hc,'2-D Image',@changeSpecgramMode, 'checked','on'}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: opts={hc,'3-D Magnitude Plot',@changeSpecgramMode}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: % xxx disable last menu until feature implemented: tomwalters@0: set(hEntry(end),'enable','off'); tomwalters@0: opts={hc,'3-D dB Plot',@changeSpecgramMode}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: % xxx disable last menu until feature implemented: tomwalters@0: set(hEntry(end),'enable','off'); tomwalters@0: tomwalters@0: % Give each menu item a vector of handles to all peer menus tomwalters@0: set(hEntry,'userdata',hEntry); tomwalters@0: tomwalters@0: fixup_context_order(hc); tomwalters@0: tomwalters@0: %----------------------------------------------------------------- tomwalters@0: function install_colorbar_menus(hfig) tomwalters@0: % Additional menus to prepend to the colorbar context menu: tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hc = get(ud.himage_cbar,'uicontext'); % ud.hax(1) also? tomwalters@0: tomwalters@0: opts={hc,'Colormap',''}; tomwalters@0: hCmap = createContext(opts); tomwalters@0: tomwalters@0: hEntry=[]; % holds handles to each colormap menu item tomwalters@0: opts={hCmap,'Jet',@changeCMap, 'checked','on'}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: opts={hCmap,'Hot',@changeCMap}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: opts={hCmap,'Gray',@changeCMap}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: opts={hCmap,'Bone',@changeCMap}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: opts={hCmap,'Copper',@changeCMap}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: opts={hCmap,'Pink',@changeCMap}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: tomwalters@0: opts={hc,'Set Limits',@manual_cmap_limits, 'separator','on'}; tomwalters@0: createContext(opts); tomwalters@0: tomwalters@0: opts={hc,'Reset Limits',@reset_cmap_limits}; tomwalters@0: createContext(opts); tomwalters@0: tomwalters@0: % Give each menu item a vector of handles to all peer menus tomwalters@0: set(hEntry,'userdata',hEntry); tomwalters@0: tomwalters@0: fixup_context_order(hc); tomwalters@0: tomwalters@0: %----------------------------------------------------------------- tomwalters@0: function install_freq_slice_menus(hfig) tomwalters@0: tomwalters@0: % Additional menus to prepend to the spectrogram context menu: tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_freq = ud.hax(4); tomwalters@0: hc = get(hax_freq,'uicontext'); % ud.hax(1) also? tomwalters@0: tomwalters@0: hEntry=[]; % holds handles to each colormap menu item tomwalters@0: opts={hc,'Marginal (specgram slice)',@changeFreqSliceMode, 'checked','on'}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: %opts={hc,'Integrated (freq PSD)',@changeFreqSliceMode}; tomwalters@0: opts={hc,'Power Spectral Density',@changeFreqSliceMode}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: set(hEntry(end),'enable','on'); tomwalters@0: tomwalters@0: % Give each menu item a vector of handles to all peer menus tomwalters@0: set(hEntry,'userdata',hEntry); tomwalters@0: tomwalters@0: fixup_context_order(hc); tomwalters@0: tomwalters@0: %----------------------------------------------------------------- tomwalters@0: function install_time_slice_menus(hfig) tomwalters@0: tomwalters@0: % Additional menus to prepend to the spectrogram context menu: tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_tslice = ud.hax(3); tomwalters@0: hc = get(hax_tslice,'uicontext'); % ud.hax(1) also? tomwalters@0: tomwalters@0: hEntry=[]; % holds handles to each colormap menu item tomwalters@0: opts={hc,'Marginal (specgram slice)',@changeTimeSliceMode, 'checked','on'}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: opts={hc,'Integrated (time zoom)',@changeTimeSliceMode}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: tomwalters@0: % disable last menu until feature implemented: tomwalters@0: set(hEntry(end),'enable','off'); tomwalters@0: tomwalters@0: % Give each menu item a vector of handles to all peer menus tomwalters@0: set(hEntry,'userdata',hEntry); tomwalters@0: tomwalters@0: fixup_context_order(hc); tomwalters@0: tomwalters@0: %----------------------------------------------------------------- tomwalters@0: function install_time_panner_menus(hfig) tomwalters@0: tomwalters@0: % Additional menus to prepend to the time-panner context menu: tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hthumb = ud.hthumb; % XXX add to time axis as well? tomwalters@0: hc = get(hthumb, 'uicontext'); tomwalters@0: tomwalters@0: % Update the menu on-the-fly: tomwalters@0: set(hc,'callback', @focus_menu_render_callback); tomwalters@0: tomwalters@0: hEntry=[]; % holds handles to each colormap menu item tomwalters@0: tomwalters@0: opts={hc,'Focus In',@focusTimeIn}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: tomwalters@0: opts={hc,'Previous Focus',@focusTimePrev}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: tomwalters@0: opts={hc,'Reset Focus',@focusTimeReset}; tomwalters@0: hEntry(end+1) = createContext(opts); tomwalters@0: tomwalters@0: % Give each menu item a vector of handles to all peer menus tomwalters@0: set(hEntry,'userdata',hEntry); tomwalters@0: tomwalters@0: fixup_context_order(hc); tomwalters@0: tomwalters@0: update_focus_history_menu(hfig); % pass any focus context menu tomwalters@0: tomwalters@0: %----------------------------------------------------------------- tomwalters@0: function hMenu=createContext(opts) tomwalters@0: % Helper function to append additional context menus tomwalters@0: args = {'parent',opts{1}, 'label',opts{2}, 'callback',opts{3:end}}; tomwalters@0: hMenu=uimenu(args{:}); tomwalters@0: tomwalters@0: %----------------------------------------------------------------- tomwalters@0: function fixup_context_order(hContext) tomwalters@0: % Put the first context menu entry (the "What's This?" entry) tomwalters@0: % last in the context menu list, and turn on the separator tomwalters@0: % for the "What's This?" entry tomwalters@0: childList = get(hContext,'children'); tomwalters@0: childList = childList([end 1:end-1]); tomwalters@0: set(hContext,'children',childList); tomwalters@0: set(childList(1),'separator','on'); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function changeCMap(hco,eventStruct) tomwalters@0: tomwalters@0: hco=gcbo; hfig=gcbf; tomwalters@0: % Reset checks on all colormap menu items: tomwalters@0: set(get(hco,'userdata'),'checked','off'); tomwalters@0: set(hco,'checked','on'); tomwalters@0: tomwalters@0: % Update figure colormap: tomwalters@0: cmapStr = lower(get(hco,'label')); tomwalters@0: cmap = feval(cmapStr); tomwalters@0: set(hfig,'colormap',cmap); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function changeSpecgramMode(hco,eventStruct) tomwalters@0: tomwalters@0: hco=gcbo; hfig=gcbf; tomwalters@0: % Reset checks on all menu items: tomwalters@0: set(get(hco,'userdata'),'checked','off'); tomwalters@0: set(hco,'checked','on'); tomwalters@0: tomwalters@0: % Update userdata cache: tomwalters@0: % Update display: tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function changeFreqSliceMode(hco,eventStruct) tomwalters@0: tomwalters@0: hco=gcbo; hfig=gcbf; tomwalters@0: % Reset checks on all menu items tomwalters@0: set(get(hco,'userdata'),'checked','off'); tomwalters@0: set(hco,'checked','on'); tomwalters@0: tomwalters@0: % Update userdata cache: tomwalters@0: % Update display: tomwalters@0: left_plot_toggle; tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function changeTimeSliceMode(hco,eventStruct) tomwalters@0: tomwalters@0: hco=gcbo; hfig=gcbf; tomwalters@0: % Reset checks on all menu items tomwalters@0: set(get(hco,'userdata'),'checked','off'); tomwalters@0: set(hco,'checked','on'); tomwalters@0: tomwalters@0: % Update userdata cache: tomwalters@0: % Update display: tomwalters@0: tomwalters@0: tomwalters@0: % --------------------------------------------------------------- tomwalters@0: % F O C U S S Y S T E M tomwalters@0: % -------------------------------------------------------------- tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function push_curr_to_focus_history(hfig) tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: tomwalters@0: % focus history is stored in userdata of time-panner axis tomwalters@0: % as either an empty vector or cell, or as tomwalters@0: % a cell-array of 2-element x-lim vector. tomwalters@0: tomwalters@0: % get current time-axis limits tomwalters@0: curr_xlim = get(hax_time,'xlim'); tomwalters@0: tomwalters@0: curr_history = get(hax_time,'userdata'); tomwalters@0: if isempty(curr_history), tomwalters@0: updated_focus_history = {curr_xlim}; tomwalters@0: else tomwalters@0: updated_focus_history = [curr_history {curr_xlim}]; tomwalters@0: end tomwalters@0: set(hax_time,'userdata',updated_focus_history); tomwalters@0: tomwalters@0: update_focus_history_menu(hfig); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function hist_xlim = pop_from_focus_history(hfig) tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: curr_xlim = get(hax_time,'xlim'); % get current time-axis limits tomwalters@0: tomwalters@0: curr_history = get(hax_time,'userdata'); tomwalters@0: if isempty(curr_history), tomwalters@0: % no prev focus info recorded tomwalters@0: warning('Attempt to pop empty focus stack'); tomwalters@0: hist_xlim = curr_xlim; tomwalters@0: tomwalters@0: %im_xdata = get(ud.himage,'xdata'); tomwalters@0: %hist_xlim = [min(im_xdata) max(im_xdata)]; tomwalters@0: else tomwalters@0: % Pop last history xlim tomwalters@0: hist_xlim = curr_history{end}; tomwalters@0: curr_history(end) = []; tomwalters@0: set(hax_time,'userdata',curr_history); tomwalters@0: end tomwalters@0: tomwalters@0: update_focus_history_menu(hfig); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function clear_focus_history(hfig) tomwalters@0: % Remove all previous focus entries tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: set(hax_time,'userdata',[]); tomwalters@0: tomwalters@0: update_focus_history_menu(hfig); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function update_focus_history_menu(hfig) tomwalters@0: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: tomwalters@0: % Update 'Previous Focus' context menu label: tomwalters@0: % tomwalters@0: curr_history = get(hax_time,'userdata'); tomwalters@0: histLen = length(curr_history); tomwalters@0: str = 'Previous Focus'; tomwalters@0: if histLen>0, tomwalters@0: str = [str ' (' num2str(histLen) ')']; tomwalters@0: ena = 'on'; tomwalters@0: else tomwalters@0: ena = 'off'; tomwalters@0: end tomwalters@0: tomwalters@0: % Get panner context menu handle: tomwalters@0: hmenu = findobj( get(get(ud.hthumb, 'uicontext'),'children'),'label','Focus In'); tomwalters@0: hAllMenus = get(hmenu,'userdata'); % vector of handles to context menus tomwalters@0: hFocusPrev = hAllMenus(2); tomwalters@0: set(hFocusPrev, 'label',str); tomwalters@0: set(hAllMenus(2:3), 'enable',ena); % Prev and Reset Focus menus tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function focus_menu_render_callback(hco, eventStruct) tomwalters@0: % Used to update the enable of the "Focus In" menu item tomwalters@0: % Only enabled if thumb_xlim ~= curr_xlim tomwalters@0: tomwalters@0: hfig=gcbf; hparent=gcbo; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hAllMenus = get(hparent,'children'); % vector of handles to context menus tomwalters@0: tomwalters@0: % Enable 'Focus on Window' if zoom window is less than entire panner tomwalters@0: % tomwalters@0: hFocusIn = hAllMenus(end); % 'Focus on Zoom' entry tomwalters@0: hax_time = ud.hax(2); tomwalters@0: curr_xlim = get(hax_time,'xlim'); % get current time-axis limits tomwalters@0: % Get thumbnail xlim vector: tomwalters@0: thumb_xdata = get(ud.hthumb,'xdata'); % current thumbnail patch coords tomwalters@0: thumb_xlim = [min(thumb_xdata) max(thumb_xdata)]; % convert to xlim tomwalters@0: if ~isequal(curr_xlim, thumb_xlim), tomwalters@0: ena='on'; tomwalters@0: else tomwalters@0: ena='off'; tomwalters@0: end tomwalters@0: set(hFocusIn,'enable',ena); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function focusTimeIn(hco,eventStruct) tomwalters@0: tomwalters@0: hfig=gcbf; tomwalters@0: tomwalters@0: % get current time-axis (panner) limits tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: curr_xlim = get(hax_time,'xlim'); tomwalters@0: tomwalters@0: % Get thumbnail xlim vector: tomwalters@0: thumb_xdata = get(ud.hthumb,'xdata'); % current thumbnail patch coords tomwalters@0: thumb_xlim = [min(thumb_xdata) max(thumb_xdata)]; % convert to xlim tomwalters@0: tomwalters@0: if ~isequal(curr_xlim, thumb_xlim), tomwalters@0: push_curr_to_focus_history(hfig); tomwalters@0: tomwalters@0: % Zoom in to thumb limits tomwalters@0: hax_time = ud.hax(2); tomwalters@0: tomwalters@0: if 0 tomwalters@0: xidx = round(1+thumb_xlim*ud.Fs); tomwalters@0: yfocus = ud.y(xidx(1):xidx(2)); tomwalters@0: ylim = [min(yfocus) max(yfocus)]; tomwalters@0: set(hax_time, 'ylim',ylim); tomwalters@0: end tomwalters@0: tomwalters@0: set(hax_time,'xlim', thumb_xlim); tomwalters@0: update_axes_with_eng_units(gcbf); tomwalters@0: end tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function focusTimePrev(hco,eventStruct) tomwalters@0: tomwalters@0: hfig=gcbf; tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: tomwalters@0: % Reset to last focus tomwalters@0: xlim = pop_from_focus_history(hfig); tomwalters@0: tomwalters@0: if 0 tomwalters@0: xidx = round(1+xlim*ud.Fs); tomwalters@0: yfocus = ud.y(xidx(1):xidx(2)); tomwalters@0: ylim = [min(yfocus) max(yfocus)]; tomwalters@0: set(hax_time, 'ylim',ylim); tomwalters@0: end tomwalters@0: tomwalters@0: set(hax_time, 'xlim',xlim); tomwalters@0: update_axes_with_eng_units(gcbf); tomwalters@0: tomwalters@0: %--------------------------------------------------------------- tomwalters@0: function focusTimeReset(hco,eventStruct,hfig) tomwalters@0: % Remove all previous focus entries tomwalters@0: tomwalters@0: if nargin<3, hfig=gcbf; end tomwalters@0: clear_focus_history(hfig); tomwalters@0: tomwalters@0: % Reset focus zoom: tomwalters@0: ud = get(hfig,'userdata'); tomwalters@0: hax_time = ud.hax(2); tomwalters@0: im_xdata = get(ud.himage,'xdata'); tomwalters@0: xlim = [min(im_xdata) max(im_xdata)]; tomwalters@0: tomwalters@0: if 0 tomwalters@0: xidx = round(1+xlim*ud.Fs); tomwalters@0: yfocus = ud.y(xidx(1):xidx(2)); tomwalters@0: ylim = [min(yfocus) max(yfocus)]; tomwalters@0: set(hax_time,'ylim',ylim); tomwalters@0: end tomwalters@0: tomwalters@0: set(hax_time,'xlim',xlim); tomwalters@0: update_axes_with_eng_units(gcbf); tomwalters@0: tomwalters@0: % --------------------------------------------------------------- tomwalters@0: % PARAMETER WINDOW tomwalters@0: % -------------------------------------------------------------- tomwalters@0: % function create_param_gui tomwalters@0: % XXX UNUSED tomwalters@0: tomwalters@0: tomwalters@0: % --------------------------------------------------------------- tomwalters@0: % AXES UPDATE FUNCTIONS tomwalters@0: % -------------------------------------------------------------- tomwalters@0: function update_left_plot(hfig) tomwalters@0: % UPDATE_LEFT_PLOT Updates the frequency plot with the appropriate analysis tomwalters@0: tomwalters@0: ud = get(hfig,'UserData'); tomwalters@0: mode = ud.plot.left; tomwalters@0: if strcmp(mode,'spectrogram_freq_slice'), tomwalters@0: update_freqslice(hfig); tomwalters@0: else tomwalters@0: update_psdplot(hfig); tomwalters@0: end tomwalters@0: tomwalters@0: % -------------------------------------------------------------- tomwalters@0: function update_freqslice(hfig) tomwalters@0: % UPDATE_FREQSLICE Update the Frequency Slice (on the left axes) tomwalters@0: tomwalters@0: ud = get(hfig,'UserData'); tomwalters@0: set(ud.hfreq_line, 'xdata',get_spec_freq(hfig),'ydata',ud.f); tomwalters@0: hax_freq = ud.hax(4); tomwalters@0: tomwalters@0: b = get(ud.himage,'cdata'); tomwalters@0: blim = [min(b(:)) max(b(:))]; tomwalters@0: spec_ylim = [0 max(ud.f)]; tomwalters@0: xlabel('dB'); tomwalters@0: set(hax_freq, ... tomwalters@0: 'YLim',spec_ylim, ... tomwalters@0: 'XLim',blim,... tomwalters@0: 'XtickMode','auto'); tomwalters@0: set(hax_freq, 'Xtick', return2ticks(hax_freq)); tomwalters@0: tomwalters@0: % Update extent of horizontal crosshair: tomwalters@0: set(ud.hfreq_x, 'xdata',blim); tomwalters@0: tomwalters@0: tomwalters@0: % -------------------------------------------------------------- tomwalters@0: function update_psdplot(hfig) tomwalters@0: % UPDATE_PSDPLOT Update the PSD plot (on the left axes) tomwalters@0: tomwalters@0: ud = get(hfig,'UserData'); tomwalters@0: wstate = warning; tomwalters@0: warning off; tomwalters@0: density = 10*log10(ud.Pxx); tomwalters@0: warning(wstate); tomwalters@0: tomwalters@0: hax_freq = ud.hax(4); tomwalters@0: tomwalters@0: % Update the PSD plot with data and limits tomwalters@0: set(ud.hfreq_line,'Xdata',density,'Ydata',ud.w); tomwalters@0: xlim = [min(density(:)) max(density(:))]; tomwalters@0: xlabel('dB/Hz'); tomwalters@0: set(hax_freq, ... tomwalters@0: 'YLim', [0 ud.Fs/2],'XLim',xlim,... tomwalters@0: 'XTickMode','auto'); tomwalters@0: set(hax_freq, 'Xtick', return2ticks(hax_freq)); tomwalters@0: tomwalters@0: % Update extent of horizontal crosshair: tomwalters@0: set(ud.hfreq_x, 'xdata',xlim); tomwalters@0: tomwalters@0: tomwalters@0: % --------------------------------------------------------------- tomwalters@0: % UTILITY FUNCTIONS tomwalters@0: % -------------------------------------------------------------- tomwalters@0: function new_xtick = return2ticks(haxes) tomwalters@0: % RETURN2TICKS Utility to return two tick marks tomwalters@0: x = get(haxes,'Xtick'); tomwalters@0: if length(x)>2, tomwalters@0: new_xtick = [x(1) x(end)]; tomwalters@0: else tomwalters@0: new_xtick = x; tomwalters@0: end tomwalters@0: tomwalters@0: %-------------------------------------------------------------- tomwalters@0: % [EOF] specgramdemo.m