function fourierworkshop(action,in1,in2); % FOURIERWORKSHOP: Self-contained module that puts up a window. Try it! % Version 1.2 (Dec 97). See file "fourierworkshop.m" for more info. % Author: % Alexander Russell Perlis % SouthWest Regional Institute in the Mathematical Sciences % c/o Department of Mathematics % The University of Arizona % Tucson, AZ 85721 % (520) 621-2137 % aprl@math.arizona.edu % % Obtain the latest version of this software from: % http://www.math.arizona.edu/~rims/workshops/fourier/softwareMATLAB % % Bugs/problems/ideas: % None. % % Change history: % May 1997 1.0 Original version, for Matlab4 % Oct 1997 1.1 Modified to run under Matlab5 % Dec 1997 1.2 Runs under either Matlab4 or Matlab5 %---------------------------------------------------------------------------- % Possible actions: % 'initialize' : this is the default when fourierworkshop is called % with no argument % % 'record_popup' : item in this popup was clicked % 'revert_button' : puts orig sample back in top plot, resets period to full % 'load_popup' % 'selection_changed' | 'top_plot_changed' % 'edit_popup' % 'top_play_popup' % % 'top_plot_click' % % 'info_button' % 'close_button' % % % 'down' % 'move' % 'up' % 'redraw' % 'done' % 'setfreq' % 'setwindow' % 'showwind' % Choice of colors can be changed: periodColor = 'yellow'; % Period start bar, end bar, period edit text sampleColor = 'magenta'; fourierColor = 'red'; cosineColor = 'cyan'; sineColor = 'green'; if nargin<1, action='initialize'; end; global FWGD; % This is a vector of global data; entries defined below. global FWmatlabVersion; % First number of matlab version number global FWdepth; global FWorig; % The original sampled data (may be different from what % is currently being viewed and played with) %% List of handles to make visible/invisible depending on spectrum: global FWharm_vis; global FWharm0; % The constant term Fourier coefficient a_0 global FWharm; % Matrix (2 x max_harmonic) of Fourier coefficients % [ a_1 a_2 a_3 a_4 ... ] % [ b_1 b_2 b_3 b_4 ... ] max_harmonic = 50; % Max number of harmonics (Fourier coefficients) that % will be computed. % FWGD is a vector. Here are the entries: main_fig = 1; load_popup = 2; record_popup = 3; generate_popup = 4; period_start_field = 5; period_end_field = 6; top_axes = 7; mid_axes = 8; bot_axes = 9; top_plot = 10; period_start_line = 11; period_end_line = 12; mid_plot = 13; mid_fourier = 14; spectrum_checkbox = 15; period_popup = 16; drag_anchor = 17; FWGD_size = 17; %% Need to keep: % Original data % Clipped data % From clipped data and period obtain period data % From period data, repeat it 2 or 3 times, if strcmp(action,'initialize'), % Initialize global variable FWmatlabVersion=version; FWmatlabVersion=str2num(FWmatlabVersion(1)); if (FWmatlabVersion < 4) | (FWmatlabVersion > 5), disp('FOURIERWORKSHOP is unfamiliar with this version of MATLAB.') return end FWGD = zeros(size(1:FWGD_size)); FWharm_vis = []; FWorig = 0; % Create a new figure window FWGD(main_fig) = ... figure('BackingStore','off','Units','normalized','Visible','off',... 'NumberTitle','off','Resize','on',... 'Name','SWRIMS Fourier Workshop'); set(gcf,'Position',[0.025,0.2,0.95,0.7]); % set(gcf,'Position',[0.025,0.45,0.5,0.5]); set(gcf,'Visible','on'); set(gcf,'Pointer','watch'); %---------------------------------------------------------- % Define "load_popup_names" and "load_popup_values" now % to avoid cluttering the code later on. % % Matlab only supports 10 names per list --- STUPID! sampleList=str2mat('Bird chirps','Chinese Gong','Hallelujah',... 'Dropping Egg','Train Whistle','Laughter'); toneList1=str2mat(... 'Touchtone 1','Touchtone 2','Touchtone 3',... 'Touchtone 4','Touchtone 5','Touchtone 6',... 'Touchtone 7','Touchtone 8','Touchtone 9'); toneList2=str2mat(..., 'Touchtone *','Touchtone 0','Touchtone #','Dialtone'); load_popup_names=str2mat('Load sound sample',... sampleList,toneList1,toneList2); sampleList=str2mat('file:chirp','file:gong','file:handel',... 'file:splat','file:train','file:laughter'); toneList1=str2mat(... 'tones:1','tones:2','tones:3',... 'tones:4','tones:5','tones:6',... 'tones:7','tones:8','tones:9'); toneList2=str2mat(... 'tones:10','tones:11','tones:12','tones:13'); load_popup_values=str2mat(' ',... sampleList,toneList1,toneList2); %==================================== % Information for all buttons %% Following are adjustable: outSpc=0.05; %% Spacing between window and frames and axes inSpc=0.015; %% Spacing between buttons in frame btnWd=0.1; %% Width of buttons btnHt=0.035; %% Height of buttons btnClr=0.75*[1 1 1]; %% Color of buttons frmClr=0.5*[1 1 1]; %% Color of frame (behind buttons) %% Following are automatically calculated: dblBtnWd=2*btnWd+inSpc; frmWd=dblBtnWd+2*inSpc; frmLt=1.0-outSpc-frmWd; axesHt=(1.0-4*outSpc)/3; axesWd=1.0-3*outSpc-frmWd; btnPos=[0 0 btnWd btnHt]; % First two entries fixed later btnGoDn=[0 -(inSpc+btnHt) 0 0]; btnGoRt=[inSpc+btnWd 0 0 0]; btnGoWd=[0 0 inSpc+btnWd 0]; % Defaults for stuff to come: set(gcf,'DefaultAxesFontSize',9); set(gcf,'DefaultUIControlBackgroundColor',btnClr); %==================================== % The TOP frame frmPos=[frmLt 1.0-outSpc-axesHt-btnHt-inSpc frmWd axesHt+btnHt+inSpc]; uicontrol('Style','frame','Units','normalized','Position',frmPos, ... 'BackgroundColor',frmClr); btnPos(1:2)=[frmPos(1)+inSpc frmPos(2)+frmPos(4)]; % The RECORD popup btnPos=btnPos+btnGoDn; callbackString='fourierworkshop(''record_popup'')'; nameList=str2mat('Rec 0.5s','Rec 1.0s',... 'Rec 1.5s','Rec 2.0s',... 'Rec 2.5s','Rec 3.0s','Rec 3.5s','Rec 4.0s','Rec 4.5s','Rec 5.0s'); FWGD(record_popup) = ... uicontrol('Style','popupmenu','Units','normalized','Position',btnPos,... 'String',nameList,'HorizontalAlignment','left',... 'Callback',callbackString); % The GENERATE popup btnPos=btnPos+btnGoRt; callbackString='fourierworkshop(''generate_popup'')'; nameList=str2mat('Generate',... 'Square Wave',... 'Triangle Wave',... 'Mystery Function'); FWGD(generate_popup) = ... uicontrol('Style','popupmenu','Units','normalized','Position',btnPos,... 'String',nameList,'HorizontalAlignment','left',... 'Callback',callbackString); % The LOAD SOUND popup button btnPos=btnPos+btnGoDn-btnGoRt+btnGoWd; callbackString='fourierworkshop(''load_popup'');'; % Variables "load_popup_names" and "load_popup_values" were % defined earlier. FWGD(load_popup) = ... uicontrol('Style','popupmenu','Units','normalized',... 'Position',btnPos, ... 'String',load_popup_names,'HorizontalAlignment','left',... 'Callback',callbackString, ... 'UserData',load_popup_values); % The EDIT popup btnPos=btnPos+btnGoDn-btnGoWd; callbackString = 'fourierworkshop(''edit_popup'')'; nameList = str2mat('Edit','Keep Selection','Delete Selection',... 'Scale Signal',... 'Clip 5% Noise','Clip 10% Noise','Clip 15% Noise','Clip 20% Noise',... 'Clip 25% Noise','Clip 30% Noise','Clip 35% Noise'); uicontrol('Style','popupmenu','Units','normalized',... 'Position',btnPos, ... 'String',nameList,'HorizontalAlignment','left',... 'Callback',callbackString); % The REVERT button btnPos=btnPos+btnGoRt; callbackString='fourierworkshop(''revert_button'')'; uicontrol('Style','pushbutton','Units','normalized','Position',btnPos,... 'String','Revert',... 'Callback',callbackString); % The PERIOD START and PERIOD END strings btnPos=btnPos-btnGoRt+btnGoDn; uicontrol('Style','text','Units','normalized','Position',btnPos,... 'BackgroundColor',frmClr,'ForegroundColor',periodColor, ... 'HorizontalAlignment','right','String','Period start:'); btnPos=btnPos+btnGoDn; uicontrol('Style','text','Units','normalized','Position',btnPos,... 'BackgroundColor',frmClr,'ForegroundColor',periodColor, ... 'HorizontalAlignment','right','String','Period end:'); % The PERIOD START and PERIOD END editable text boxes btnPos=btnPos-btnGoDn+btnGoRt; callbackString = 'fourierworkshop(''selection_changed'')'; FWGD(period_start_field) = ... uicontrol('Style','edit','Units','normalized','Position',btnPos, ... 'String','0',... 'CallBack',callbackString); btnPos=btnPos+btnGoDn; FWGD(period_end_field) = ... uicontrol('Style','edit','Units','normalized','Position',btnPos,... 'String','0',... 'CallBack',callbackString); % The PLAY button btnPos=btnPos+btnGoDn-btnGoRt+btnGoWd; callbackString = 'fourierworkshop(''top_play_popup'')'; nameList = str2mat('Play Original','Play Visible','Play Selection'); uicontrol('Style','popup','Units','normalized','Position',btnPos,... 'String',nameList,'HorizontalAlignment','left',... 'Callback',callbackString); btnPos=btnPos-btnGoWd; %==================================== % The MIDDLE frame frmPos=[frmLt 2*outSpc+axesHt frmWd axesHt-btnHt-inSpc]; uicontrol('Style','frame','Units','normalized','Position',frmPos, ... 'BackgroundColor',frmClr); btnPos(1:2)=[frmPos(1)+inSpc frmPos(2)+frmPos(4)]; % % DEPTH SLIDER % btnPos=btnPos+btnGoDn+btnGoWd; % callbackString='fourierworkshop(''depth_slider'')'; % FWGD(depth_slider) = ... % uicontrol('Style','slider','Units','normalized',... % 'Position',btnPos,'String','Slide it baby',... % 'Callback',callbackString,'Min',1,'Max',25,'Value',3); % The PERIOD popup btnPos=btnPos+btnGoDn+btnGoWd; callbackString='fourierworkshop(''period_popup'')'; nameList = str2mat('Show 1 Period','Show 2 Periods','Show 3 Periods'); FWGD(period_popup) = ... uicontrol('Style','popupmenu','Units','normalized',... 'Position',btnPos,'String',nameList,'HorizontalAlignment','left',... 'Callback',callbackString); % ORIGINAL text btnPos=btnPos+btnGoDn-btnGoWd; uicontrol('Style','text','Units','normalized','Position',btnPos,... 'BackgroundColor',frmClr,'ForegroundColor',sampleColor,... 'HorizontalAlignment','right','String','Original:'); % The PLAYORIG popup btnPos=btnPos+btnGoRt; callbackString='fourierworkshop(''play_orig_popup'')'; nameList = str2mat('Play 1 Period','Play 5 Periods',... 'Play 10 Periods','Play 50 Periods'); uicontrol('Style','popupmenu','Units','normalized',... 'Position',btnPos,'String',nameList,'HorizontalAlignment','left',... 'Callback',callbackString); % FOURIER text btnPos=btnPos+btnGoDn-btnGoRt; h=uicontrol('Style','text','Units','normalized','Position',btnPos,... 'BackgroundColor',frmClr,'ForegroundColor',fourierColor,... 'HorizontalAlignment','right','String','Fourier:','Visible','off'); FWharm_vis = [FWharm_vis,h]; % PLAYFOURIER popup btnPos=btnPos+btnGoRt; callbackString='fourierworkshop(''play_fourier_popup'')'; nameList = str2mat('Play 1 Period','Play 5 Periods',... 'Play 10 Periods','Play 50 Periods'); h=uicontrol('Style','popupmenu','Units','normalized',... 'Position',btnPos,'String',nameList,'HorizontalAlignment','left',... 'Callback',callbackString,'Visible','off'); FWharm_vis = [FWharm_vis,h]; % return btnPos btnPos=btnPos-btnGoRt; %==================================== % The BOTTOM frame frmPos=[frmLt outSpc frmWd axesHt]; uicontrol('Style','frame','Units','normalized','Position',frmPos, ... 'BackgroundColor',frmClr); btnPos(1:2)=[frmPos(1)+inSpc frmPos(2)+frmPos(4)]; % COMPUTE HARMONICS checkbox btnPos=btnPos+btnGoDn+btnGoWd; callbackString='fourierworkshop(''spectrum_checkbox'')'; FWGD(spectrum_checkbox) = ... uicontrol('Style','checkbox','Units','normalized','Position',btnPos,... 'String','Compute the spectrum','HorizontalAlignment','left',... 'Callback',callbackString); % TURN ON ALL HARMONICS popup btnPos=btnPos+btnGoDn; callbackString='fourierworkshop(''full_depth_popup'')'; nameList = str2mat('Turn on all harmonics',... 'Turn on all harmonics (animate)'); % Made pushbutton for now h=uicontrol('Style','pushbutton','Units','normalized','Position',btnPos,... 'String','Turn on all harmonics','Visible','off',... 'Callback',callbackString); FWharm_vis = [FWharm_vis,h]; % TURN OFF ALL HARMONICS popup btnPos=btnPos+btnGoDn; callbackString='fourierworkshop(''no_depth_popup'')'; nameList = str2mat('Turn off all harmonics',... 'Turn off all harmonics (animate)'); % Made pushbutton for now h=uicontrol('Style','pushbutton','Units','normalized','Position',btnPos,... 'String','Turn off all harmonics','Visible','off',... 'Callback',callbackString); FWharm_vis = [FWharm_vis,h]; % SINE and COSINE text btnPos=btnPos+btnGoDn-btnGoWd; h=uicontrol('Style','text','Units','normalized','Position',btnPos,... 'String','Cosine','BackgroundColor',frmClr,... 'ForegroundColor',cosineColor,'Visible','off'); FWharm_vis = [FWharm_vis,h]; btnPos=btnPos+btnGoDn; h=uicontrol('Style','text','Units','normalized','Position',btnPos,... 'String','Sine','BackgroundColor',frmClr,... 'ForegroundColor',sineColor,'Visible','off'); FWharm_vis = [FWharm_vis,h]; % The INFO button btnPos=btnPos+btnGoRt-btnGoDn; callbackString='fourierworkshop(''info_button'')'; uicontrol('Style','pushbutton','Units','normalized','Position',btnPos,... 'String','Info', ... 'Callback',callbackString); % The CLOSE button btnPos=btnPos+btnGoDn; callbackString='fourierworkshop(''close_button'')'; uicontrol('Style','pushbutton','Units','normalized','Position',btnPos,... 'Callback',callbackString,'String','Close'); %==================================== % The TOP axes axesPos=[outSpc 1.0-outSpc-axesHt axesWd axesHt]; callbackString='fourierworkshop(''top_plot_click'')'; FWGD(top_axes) = ... axes('Position',axesPos,'DrawMode','normal','YLim',[-1 1],... 'ButtonDownFcn',callbackString,'DefaultLineButtonDownFcn',callbackString); hold on; grid on; FWGD(top_plot) = plot(0,0,sampleColor); % FWGD(top_period_plot) = ... % plot(0); FWGD(period_start_line) = ... line('Xdata',[1 1],'Ydata',[-1 1],'Zdata',[1 1],... 'EraseMode','xor','Color',periodColor,'LineWidth',1,... 'ButtonDownFcn',callbackString); FWGD(period_end_line) = ... line('Xdata',[1 1],'Ydata',[-1 1],'Zdata',[1 1],... 'EraseMode','xor','Color',periodColor,'LineWidth',1,... 'ButtonDownFcn',callbackString); %==================================== % The MIDDLE axes axesPos=[outSpc 2*outSpc+axesHt axesWd axesHt]; FWGD(mid_axes) = ... axes('Position',axesPos,'YLim',[-1 1]); hold on; grid on; FWGD(mid_plot) = plot(0,0,sampleColor); set(gca,'DefaultLineEraseMode','xor'); %'DefaultLineLineWidth',2); FWGD(mid_fourier) = plot(0,0,fourierColor); set(gca,'DefaultLineEraseMode','remove','DefaultLineLineWidth','remove'); %==================================== % The BOTTOM axes axesPos=[outSpc outSpc axesWd axesHt]; callbackStr = 'fourierworkshop(''bot_plot_click'')'; FWGD(bot_axes) = ... axes('Position',axesPos,'YGrid','on',... 'XLim',[1 max_harmonic],'XTick',1:2:max_harmonic,... 'DefaultLineButtonDownFcn',callbackStr); hold on; FWdepth = zeros(max_harmonic,1); fourierworkshop('create_depth_marks'); %------------------------------------ currentpath = pwd; cd ~/matlab; FWorig = 0; fp = fopen('welcomeToFourier.au', 'r'); if (fp >= 0), %% if the file exists, close it and load the sound fclose(fp); FWorig = auread('welcomeToFourier.au'); end; cd(currentpath); fourierworkshop('revert_button'); drawnow; set(gcf,'Pointer','arrow'); % fourierworkshop('top_play_popup'); elseif strcmp(action,'generate_popup'), value=get(FWGD(generate_popup),'Value'); if value>1, set(FWGD(load_popup),'Value',1); if value==2, FWorig = 0.75 * [ones(40,1);-1*ones(40,1)]; FWorig = [FWorig;FWorig;FWorig;FWorig;FWorig]; elseif value==3, FWorig = [1:400,399:-1:-400,-399:0]; FWorig = FWorig'; FWorig = 0.75 * FWorig / max(abs(FWorig)); FWorig = [FWorig;FWorig;FWorig;FWorig;FWorig]; elseif value==4, %% Mystery Function is really the following: x = [-pi:0.1:pi]'; %x = [0:0.1:2*pi]'; FWorig = 5.123 * ones(length(x),1); FWorig = FWorig - 45.34*cos(x) + 3.489*sin(x); FWorig = FWorig + 15.23*cos(2*x) - 12.375*sin(2*x); FWorig = FWorig / 100; %FWorig = [FWorig;FWorig;FWorig;]; end fourierworkshop('revert_button'); end elseif strcmp(action,'load_popup'), value=get(FWGD(load_popup),'Value'); names=get(FWGD(load_popup),'UserData'); choice=names(value,:); if value==1, oldpath = pwd; cd ~/sounds; [filename, pathname] = uigetfile('*.au','Pick a sound...'); cd(oldpath); FWorig=auread([pathname,filename]); FWorig=FWorig/max(abs(FWorig)); fourierworkshop('revert_button'); elseif value>1, set(FWGD(generate_popup),'Value',1); if strcmp(choice(1:4),'file'), s=size(choice(:),1); filename=choice(6:s); filename(filename==' ')=[]; %% strip blanks load(filename); % Sets Fs to the freq (usu.8000) and y to snd vector %Normalize: y=y/max(abs(y)); FWorig=y; elseif strcmp(choice(1:5),'tones'), s=size(choice(:),1); n=str2num(choice(7:s)); switch FWmatlabVersion case 4, load tones, FWorig=tones(:,n); case 5, load ptones, FWorig=tones1(:,n); end end fourierworkshop('revert_button'); end elseif strcmp(action,'record_popup'), set(FWGD(load_popup),'Value',1); set(FWGD(generate_popup),'Value',1); duration=4096*get(FWGD(record_popup),'Value'); FWorig=record(duration); % FWorig=FWorig/max(abs(FWorig)); fourierworkshop('revert_button'); elseif strcmp(action,'revert_button'), set(FWGD(top_plot),'Xdata',1:length(FWorig),'Ydata',FWorig); % set(FWGD(period_start_field),'String','1'); % set(FWGD(period_end_field),'String',num2str(length(FWorig))); fourierworkshop('top_plot_changed'); elseif strcmp(action,'top_plot_changed') | strcmp(action,'selection_changed'), pstart=str2num(get(FWGD(period_start_field),'String')); pend=str2num(get(FWGD(period_end_field),'String')); xdatasize=length(get(FWGD(top_plot),'Xdata')); if pstart<1 | pstart>=xdatasize, pstart=1; set(FWGD(period_start_field),'String',num2str(pstart)); end if pend<1 | pend>xdatasize, pend=xdatasize; set(FWGD(period_end_field),'String',num2str(pend)); end if pend 400, set(FWGD(spectrum_checkbox),'Value',0); end %% Calling "spectrum_checkbox" does any necessary hiding %% or showing of controls, and then calculates the spectrum. fourierworkshop('spectrum_checkbox'); elseif strcmp(action,'spectrum_checkbox'), %% Since this is called even when there is no mouseclick, %% we cannot use "gco" below. if get(FWGD(spectrum_checkbox),'Value')==0, for k=FWharm_vis, set(k,'Visible','off'); end else for k=FWharm_vis, set(k,'Visible','on'); end end fourierworkshop('calc_spectrum'); elseif strcmp(action,'calc_spectrum'), %% Only calculate it if that is enabled if get(FWGD(spectrum_checkbox),'Value')==1, set(gcf,'Pointer','watch'); pstart=str2num(get(FWGD(period_start_field),'String')); pend=str2num(get(FWGD(period_end_field),'String')); p = pend-pstart+1; x = pstart:pend; y = get(FWGD(top_plot),'Ydata'); y = y(pstart:pend); FWharm0 = sum(y)/p; FWharm = zeros(2,max_harmonic); x=2*pi/p*x; for k=1:max_harmonic, FWharm(1,k) = cos(k*x)*y'; FWharm(2,k) = sin(k*x)*y'; end FWharm = 2/p * FWharm; set(gcf,'Pointer','arrow'); end fourierworkshop('redraw_spectrum'); % Now move the data from top plot to middle plot: fourierworkshop('num_periods_changed'); elseif strcmp(action,'redraw_spectrum'), axes(FWGD(bot_axes)); for k=get(gca,'Children'), delete(k); end if get(FWGD(spectrum_checkbox),'Value')==1, axes(FWGD(bot_axes)); set(gca,'YLimMode','auto'); set(gca,'DefaultLineMarkerSize',2); xx = [1:max_harmonic;1:max_harmonic;nan*ones(1,max_harmonic)]; yy = [zeros(1,max_harmonic);FWharm(1,:);nan*ones(1,max_harmonic)]; plot(1:max_harmonic,FWharm(1,:),'co',xx,yy,cosineColor); xx = [1:max_harmonic;1:max_harmonic;nan*ones(1,max_harmonic)]; yy = [zeros(1,max_harmonic);FWharm(2,:);nan*ones(1,max_harmonic)]; plot(1:max_harmonic,FWharm(2,:),'go',xx,yy,sineColor); ylim = get(gca,'YLim'); m = max(abs(ylim)); ylim = [-m m]; set(gca,'YLim',ylim); % Create the depth marks fourierworkshop('create_depth_marks'); end drawnow; elseif strcmp(action,'num_periods_changed') | strcmp(action,'period_popup'), pstart=str2num(get(FWGD(period_start_field),'String')); pend=str2num(get(FWGD(period_end_field),'String')); n = get(FWGD(period_popup),'Value'); y = get(FWGD(top_plot),'Ydata'); x = pstart:pstart+n*(pend-pstart+1)-1; y = y(pstart:pend); if n==2, y = [y y]; elseif n==3, y = [y y y]; end % Now redraw the middle plot: set(FWGD(mid_plot),'Xdata',x,'Ydata',y); fourierworkshop('depth_changed'); elseif strcmp(action,'create_depth_marks'), axes(FWGD(bot_axes)); for k=1:max_harmonic, if FWdepth(k)==1, line('Xdata',k,'Ydata',0,'Zdata',1,'EraseMode','xor',... 'Color',fourierColor,'MarkerSize',7,'LineWidth',2,... 'LineStyle','+','UserData',k); end end elseif strcmp(action,'bot_plot_click'), axes(FWGD(bot_axes)); pt=get(gca,'currentpoint'); x=round(pt(1,1)); if 1<=x & x<=max_harmonic, fourierworkshop('flip_depth',x); fourierworkshop('depth_changed'); end elseif strcmp(action,'flip_depth'), %% fourierworkshop('flip_depth',5) turns harmonic 5 on or off %% It is the caller's responsibility to call 'depth_changed' FWdepth(in1) = 1-FWdepth(in1); if FWdepth(in1)==1, %% Now on, so create it! axes(FWGD(bot_axes)); line('Xdata',in1,'Ydata',0,'Zdata',1,'EraseMode','xor',... 'Color',fourierColor,'MarkerSize',7,'LineWidth',2,... 'LineStyle','+','UserData',in1); else %% Now off, so remove it! h = findobj(FWGD(bot_axes),'Type','line','UserData',in1); delete(h); end elseif strcmp(action,'full_depth_popup'), animation = get(gco,'Value'); if animation==2, for k=1:max_harmonic, if FWdepth(k)==0, fourierworkshop('flip_depth',k); fourierworkshop('depth_changed'); end end else FWdepth = ones(max_harmonic,1); fourierworkshop('redraw_spectrum'); fourierworkshop('depth_changed'); end elseif strcmp(action,'no_depth_popup'), animation = get(gco,'Value'); if animation==2, for k=max_harmonic:-1:1, if FWdepth(k)==1, fourierworkshop('flip_depth',k); fourierworkshop('depth_changed'); end end else FWdepth = zeros(max_harmonic,1); fourierworkshop('redraw_spectrum'); fourierworkshop('depth_changed'); end elseif strcmp(action,'depth_changed'), if get(FWGD(spectrum_checkbox),'Value')==1, set(gcf,'Pointer','watch'); x = get(FWGD(mid_plot),'Xdata'); p = length(x(:)) / get(FWGD(period_popup),'Value'); y = FWharm0*ones(size(x)); for k=1:max_harmonic, if FWdepth(k)==1, y = y + FWharm(1,k)*cos(2*k*pi/p*x); y = y + FWharm(2,k)*sin(2*k*pi/p*x); end end set(gcf,'Pointer','arrow'); else x=NaN; y=NaN; end set(FWGD(mid_fourier),'Xdata',x,'Ydata',y); elseif strcmp(action,'play_orig_popup'), % Grab 1 period of the y data y = get(FWGD(mid_plot),'Ydata'); p = length(y(:)) / get(FWGD(period_popup),'Value'); y = y(1:p); % Now repeat it if necessary if get(gco,'Value')>1, y = [y y y y y]; end if get(gco,'Value')>2, y = [y y]; end if get(gco,'Value')>3, y = [y y y y y]; end sound(y); elseif strcmp(action,'play_fourier_popup') % Grab 1 period of the y data y = get(FWGD(mid_fourier),'Ydata'); p = length(y(:)) / get(FWGD(period_popup),'Value'); y = y(1:p); % Now repeat it if necessary if get(gco,'Value')>1, y = [y y y y y]; end if get(gco,'Value')>2, y = [y y]; end if get(gco,'Value')>3, y = [y y y y y]; end sound(y); elseif strcmp(action,'edit_popup'), value=get(gco,'Value'); set(gco,'Value',1); if value>1, y=get(FWGD(top_plot),'Ydata'); if value==2 | value==3, pstart=str2num(get(FWGD(period_start_field),'String')); pend=str2num(get(FWGD(period_end_field),'String')); xdatasize=length(get(FWGD(top_plot),'Xdata')); if pstart<=pend, if value==2, y=y(pstart:pend); elseif value==3, y(pstart:pend)=[]; end set(FWGD(period_start_field),'String','0'); set(FWGD(period_end_field),'String','0'); end elseif value==4, y = y / max(abs(y)); else % Strip noise in 5% increments, depending on menu choice y=stripnoise(y,(value-4)*0.05); end set(FWGD(top_plot),'Xdata',1:length(y(:)),'Ydata',y); fourierworkshop('top_plot_changed'); end elseif strcmp(action,'top_play_popup'), value=get(gco,'Value'); if value==1, sound(FWorig); else data=get(FWGD(top_plot),'Ydata'); if value==3, pstart=str2num(get(FWGD(period_start_field),'String')); pend=str2num(get(FWGD(period_end_field),'String')); data = data(pstart:pend); end sound(data); end elseif strcmp(action,'top_plot_click') axes(FWGD(top_axes)); pstart=str2num(get(FWGD(period_start_field),'String')); pend=str2num(get(FWGD(period_end_field),'String')); pt=get(gca,'currentpoint'); xdatasize=length(get(FWGD(top_plot),'Xdata')); x=round(pt(1,1)); tol=round(0.08*xdatasize); if 1<=x & x<=xdatasize, if abs(x-pstart) < abs(x-pend) & abs(x-pstart) < tol, FWGD(drag_anchor) = pend; elseif abs(x-pstart) >= abs(x-pend) & abs(x-pend) < tol, FWGD(drag_anchor) = pstart; else FWGD(drag_anchor) = x; end set(gcf,'WindowButtonMotionFcn','fourierworkshop(''top_mouse_move'')'); set(gcf,'WindowButtonUpFcn','fourierworkshop(''top_mouse_up'')'); fourierworkshop('top_mouse_move'); end elseif strcmp(action,'top_mouse_move'), xdatasize=length(get(FWGD(top_plot),'Xdata')); axes(FWGD(top_axes)); pt=get(gca,'currentpoint'); x=round(pt(1,1)); if x<1, x=1; end if x>xdatasize, x=xdatasize; end if x