function saite(action)

%Programm zur Simulation einer Saitenschwingung durch Modalsynthese 
%bzw. nach d'Alembert
%
%Thomas Neukirchner   September 1999
%

play= 1;
stop=-1;

if nargin<1,
   action='initialize';
end;

if strcmp(action,'initialize'),
   	   
   
   
   figNumber=figure( ...
      'Name','Simulation einer  schwingenden Saite', ...
      'NumberTitle','off', ...
      'Visible','off', ...  
      'DoubleBuffer','on', ...
      'BackingStore','off',...
      'units','normalized',...
      'position',[0.1 0.1 0.8 0.8]);
   
   colormap(hot);  
   
   axes( ...
      'Units','normalized', ...
      'Position',[0.05 0.05 0.65 0.90], ...
      'Visible','off', ...
      'NextPlot','add');
   
   str(1)={'\bf Simulation der Schwingungsgleichung'};
   str(2)={''};
   str(3)={'{\partial^{2}u }/{\partialt^{2}} = c^{2} {\partial^{2}u }/{\partialx^{2}}'};
   str(4)={''};
   str(5)={'  1) Bernoulli (Modalsynthese)         '};
   str(6)={'  2) d^{,}Alembert (digital Waveguides)'};
   texHndl=text(0.5,0.5,str, ...
      'HorizontalAlignment','center',...
      'FontSize',15);
		  	   	   
   %===================================
   % Information für alle Schaltflächen
   labelColor=[0.8 0.8 0.8];
   yInitPos=0.90;
   xPos=0.75;
   btnWid=0.20;
   btnHt=0.10;
   % Abstand zwischen Schaltfläche und Text 
   spacing=0.05;
   
   %====================================
   % Ramen der Konsole
   frmBorder=0.02;
   yPos=0.05-frmBorder;
   frmPos=[xPos-frmBorder yPos btnWid+2*frmBorder 0.9+2*frmBorder];
   h=uicontrol( ...
      'Style','frame', ...
      'Units','normalized', ...
      'Position',frmPos, ...
      'BackgroundColor',[0.5 0.5 0.5]);
   
   %====================================
   % "Start"
   btnNumber=1;
   yPos=0.90-(btnNumber-1)*(btnHt+spacing);
   labelStr='Start';
   callbackStr='saite(''start'');';
   
   % Erzeugung der Schaltfläche
   btnPos=[xPos yPos-spacing btnWid btnHt];
   startHndl=uicontrol( ...
      'Style','pushbutton', ...
      'Units','normalized', ...
      'Position',btnPos, ...
      'String',labelStr, ...
      'Interruptible','on', ...
      'Callback',callbackStr);
   
   %====================================
   % "Stopp"
   btnNumber=2;
   yPos=0.90-(btnNumber-1)*(btnHt+spacing);
   labelStr='Stopp';
   % Bei 'userdata = -1' (=stop) wird das Demo gestoppt.
   callbackStr='set(gca,''Userdata'',-1)';
   
   % Erzeugung der Schaltfläche
   btnPos=[xPos yPos-spacing btnWid btnHt];
   stopHndl=uicontrol( ...
      'Style','pushbutton', ...
      'Units','normalized', ...
      'Position',btnPos, ...
      'Enable','off', ...
      'String',labelStr, ...
      'Callback',callbackStr);

   %====================================
   % "Modus"
   btnNumber=3;
   yPos=0.90-(btnNumber-1)*(btnHt+spacing);
   textStr='Algorithmus';
   popupStr={' Bernoulli/Fourier ';...
         	' d"Alembert ';...
         	' Stehende Welle ';...
         	' Saite und Spektren '};
   
   % Erzeugung der Schaltfläche
   btnPos1=[xPos yPos-spacing+btnHt/2 btnWid btnHt/2];
   btnPos2=[xPos yPos-spacing btnWid btnHt/2];
   popupHndl=uicontrol( ...
      'Style','text', ...
      'Units','normalized', ...
      'Position',btnPos1, ...
      'String',textStr);
   btnPos=[xPos yPos-spacing btnWid btnHt/2];
   popupHndl=uicontrol( ...
      'Style','popup', ...
      'Units','normalized', ...
      'Position',btnPos2, ...
      'String',popupStr);
   
   %====================================
   % "Zupfstelle"

   btnNumber=4;
   yPos=0.90-(btnNumber-1)*(btnHt+spacing);
   textStr=' "Zupfstelle" ';
   
   % Erzeugung der Schaltfläche
   btnPos1=[xPos yPos-spacing+btnHt/2 btnWid btnHt/2];
   btnPos2=[xPos yPos-spacing btnWid btnHt/2];
   IniHndl=uicontrol( ...
      'Style','text', ...
      'Units','normalized', ...
      'Position',btnPos1, ...
      'String',textStr);
   btnPos=[xPos yPos-spacing btnWid btnHt/2];
   IniHndl=uicontrol( ...
      'Style','slider', ...
      'Units','normalized', ...
      'Position',btnPos2,...
      'min',0.05,...
      'max',0.95,...
      'value',0.5);
 	
   %====================================
   % "Geschwindigkeit"

   btnNumber=5;
   yPos=0.90-(btnNumber-1)*(btnHt+spacing);
   textStr='Geschwindigkeit';
   
   % Erzeugung der Schaltfläche
   btnPos1=[xPos yPos-spacing+btnHt/2 btnWid btnHt/2];
   btnPos2=[xPos yPos-spacing btnWid btnHt/2];
   SpHndl=uicontrol( ...
      'Style','text', ...
      'Units','normalized', ...
      'Position',btnPos1, ...
      'String',textStr);
   btnPos=[xPos yPos-spacing btnWid btnHt/2];
   SpHndl=uicontrol( ...
      'Style','slider', ...
      'Units','normalized', ...
      'Position',btnPos2,...
      'min',100,...
      'max',400,...
      'value',250);

   	   
   %====================================
   % "Schließen"
   labelStr='Schließen';
   callbackStr='close(gcf)';
   closeHndl=uicontrol( ...
      'Style','push', ...
      'Units','normalized', ...
      'Position',[xPos 0.05 btnWid 0.10], ...
      'String',labelStr, ...
      'Callback',callbackStr);
   
   % 'figur' sichtbar machen
   hndlList=[startHndl stopHndl popupHndl IniHndl SpHndl closeHndl];
   set(figNumber,'Visible','on', ...
      'UserData',hndlList);
   
   figure(figNumber);
   
elseif strcmp(action,'start'),
   axHndl=gca;
   figNumber=gcf;
   hndlList=get(figNumber,'UserData');
   startHndl=hndlList(1);
   stopHndl=hndlList(2);
   popupHndl=hndlList(3);
   IniHndl=hndlList(4);
   SpHndl=hndlList(5);
   closeHndl=hndlList(6);
   set([startHndl closeHndl IniHndl SpHndl],'Enable','off');
   set(stopHndl,'Enable','on');
   set(axHndl,'visible','on');		
   set(axHndl,'visible','off');
   
   
   
   % ==============
   % Start des Demo
   % ==============
   
   set(axHndl,'Userdata',play);  
   axis([-0.2 1.2 -1.2 1.2]);
   cla;
   set(gca,'Drawmode','Fast');    
   p=get(IniHndl,'value');
   rate=fix(get(SpHndl,'Value'));
   
    % Spektren
    
     f=(1:20);
      for k=1:20,
         a1(k)=2*sin(k*pi*p)/(k^2*pi^2*p*(1-p));
         c1(k)=abs(a1(k));
			a2(k)=sin(2*pi*k*p)/(pi*k*p*(1-p));
   		b2(k)=(1-cos(2*pi*k*p))/(pi*k*p*(1-p));
         c2(k)=sqrt(a2(k)^2+b2(k)^2);
      end
     
     
     t1='Spektrum der Saitenschwingung';
     t2='Spektrum der Stegkräfte';
      ax1=axes( ...
      'Units','normalized', ...
      'Position',[0.05 0.05 0.3 0.25],...
      'visible','off',...
       'xtick',[],...
      'ytick',[]);
   	title(t1);
   
   l1=line(f,c1,'linestyle','none',...
      'visible','off',...
      'marker','o',...
      'markersize',5,...
      'markerfacecolor',[0 0 1]);
   
   	 ax2=axes( ...
      'Units','normalized', ...
      'Position',[0.4 0.05 0.3 0.25],...
      'visible','off',...
      'xtick',[],...
      'ytick',[]);
   title(t2);
   
   l2=line(f,c2,'linestyle','none',...
      'visible','off',...
      'marker','o',...
      'markersize',5,...
      'markerfacecolor',[0 0 1]);
      
      set(gcf,'currentaxes',axHndl);

   
   % ================ 
   % Bernoulli-Lösung   
   % ================
   if get(popupHndl,'value')==1, 
      set(axHndl,'Position',[0.05 0.05 0.65 0.90]);

      n=30;
   	cm=colormap;
   	numframes=rate*3;
	   for k=7:-1:1
   	   h(k)=line(0,0,'color',cm(7*k,:),'linewidth',1.5);
		end
   
   	x=linspace(0,1,n);
	
      
   	% Zeichne schwarze Saitenhalter
   	d=0.5;
   	patch([-0.2 0 0 -0.2],[-0.2 -0.15 0.15 0.2],[d d d+0.2]);
   	patch([1.2 1 1 1.2],[-0.2 -0.15 0.15 0.2],[d d d+0.2]);
   
   
   	t=linspace(0,2*pi,numframes+1);
   
   
   	while get(axHndl,'Userdata')==play,
      	for count=1:numframes,
         	if get(axHndl,'Userdata')~=play, break; end;
         	y=zeros(size(x));	
         	for k=1:6
            	ak=2*sin(k*pi*p)*cos(k*t(count))/(k^2*pi^2*p*(1-p));
   				yk=+ak*sin(k*pi*x);
			   	y=y+yk;
            
            	set(h(k+1),'xdata',x,'ydata',yk);
				end
         
         	for k=7:15
           		ak=2*sin(k*pi*p)*cos(k*t(count))/(k^2*pi^2*p*(1-p));
   				yk=+ak*sin(k*pi*x);
			   	y=y+yk;
				end
					set(h(1),'xdata',x,'ydata',y);
					drawnow;
            end; 	
         end;    	
      end
      
      % ===============
      % Alembert-Lösung
      % ===============
 if get(popupHndl,'value')==2,
      set(axHndl,'Position',[0.05 0.05 0.65 0.90]);

      n=2*rate;
      x=0;
      xx=0;
      wave=0;
      x=linspace(0,1,n+1);
      xx=linspace(-0.5,1.5,2*n+1);
      r=fix(n*p)+1;
      wave(1:r) = 1/2*x(1:r)/p;
      wave(r+1:n+1) = 1/2*(ones(size(x(r+1:n+1)))-x(r+1:n+1))/(1-p);
	   wave=[-wave(n/2:-1:2)  wave  -wave(n:-1:n/2+1)];
      
      
		h(2)=line(0,0,'color',[0.8 0.2 0],'linewidth',1.5);
		h(3)=line(0,0,'color',[0 0.8 0.3],'linewidth',1.5);
		h(1)=line(0,0,'color',[0 0 0],'linewidth',1.5);
      
      % Zeichne Saitenhalter
	   d=0.5;
   	patch([-0.2 0 0 -0.2],[-0.2 -0.15 0.15 0.2],[d d d+0.2]);
   	patch([1.2 1 1 1.2],[-0.2 -0.15 0.15 0.2],[d d d+0.2]);

      while get(axHndl,'Userdata')==play,
         y1=wave;
         y2=wave;
         
         for count=1:2*n
         	if get(axHndl,'Userdata')~=play, break; end;
            
            y1=[y1(2:2*n) y1(1)];
         	y2=[y2(2*n) y2(1:2*n-1)];
				y=y1+y2;
         
         	
            set(h(2),'xdata',xx(1:2*n),'ydata',y1);
				set(h(3),'xdata',xx(1:2*n),'ydata',y2);
            set(h(1),'xdata',x,'ydata',y(n/2:n/2+n));
            drawnow;
         end;    	
      end;  	   
    end  	    


% ==============
% stehende Welle
% ==============

if get(popupHndl,'value')==3, 
      set(axHndl,'Position',[0.05 0.05 0.65 0.90]);

      n=2*rate;
      x=0;
      xx=0;
      wave=0;
      x=linspace(0,1,n+1);
      xx=linspace(-0.5,1.5,2*n+1);
      wave(1:n+1) = 1/2*sin(3*pi*x);
	   wave=[-wave(n/2:-1:2)  wave  -wave(n:-1:n/2+1)];
      
      
		h(2)=line(0,0,'color',[0.8 0.2 0],'linewidth',1.5);
		h(3)=line(0,0,'color',[0 .8 0.3],'linewidth',1.5);
		h(1)=line(0,0,'color',[0 0 0],'linewidth',1.5);
      
      line(1/3,0,'marker','o',...
         'markerfacecolor',[1 1 1],...
         'markeredgecolor',[0 0 0],...
         'markersize',10);
      line(2/3,0,'marker','o',...
         'markerfacecolor',[1 1 1],...
         'markeredgecolor',[0 0 0],...
         'markersize',10);

      
      % Zeichne Saitenhalter
	   d=0.5;
   	patch([-0.2 0 0 -0.2],[-0.2 -0.15 0.15 0.2],[d d d+0.2]);
   	patch([1.2 1 1 1.2],[-0.2 -0.15 0.15 0.2],[d d d+0.2]);
      	
      
      while get(axHndl,'Userdata')==play,
         y1=wave;
         y2=wave;
         
         for count=1:2*n
         	if get(axHndl,'Userdata')~=play, break; end;
            
            y1=[y1(2:2*n) y1(1)];
         	y2=[y2(2*n) y2(1:2*n-1)];
				y=y1+y2;
         
         	
            set(h(2),'xdata',xx(1:2*n),'ydata',y1);
				set(h(3),'xdata',xx(1:2*n),'ydata',y2);
            set(h(1),'xdata',x,'ydata',y(n/2:n/2+n));
            drawnow;
         end;    	
      end;  	   
    end  	    

% ==================
% Saite und Spektren
% ==================

if get(popupHndl,'value')==4, 
      set(axHndl,'Position',[0.05 0.35 0.65 0.65]);
      
      n=2*rate;
      x=0;
      xx=0;
      wave=0;
      x=linspace(0,1,n+1);
      xx=linspace(-0.5,1.5,2*n+1);
      r=fix(n*p)+1;
      wave(1:r) = 1/2*x(1:r)/p;
      wave(r+1:n+1) = 1/2*(ones(size(x(r+1:n+1)))-x(r+1:n+1))/(1-p);
	   wave=[-wave(n/2:-1:2)  wave  -wave(n:-1:n/2+1)];
      
     	      
		h(1)=line(0,0,'color',[0 0 0],'linewidth',1.5);
      line([1 1.5],[0 0],'color',[0 0 0],'linewidth',1.5);
      	      
      % Zeichne Saitenhalter
	   d=0.5;
   	patch([-0.2 0 0 -0.2],[-0.2 -0.15 0.15 0.2],[d d d]);
      patch([1 1.05 0.95],[0 -0.2 -0.2],[d d d]);

		set([ax1 ax2 l1 l2],'visible','on');

      while get(axHndl,'Userdata')==play,
         y1=wave;
         y2=wave;
         
         for count=1:2*n
         	if get(axHndl,'Userdata')~=play, break; end;
            
            y1=[y1(2:2*n) y1(1)];
         	y2=[y2(2*n) y2(1:2*n-1)];
				y=y1+y2;
            
            set(h(1),'xdata',x,'ydata',y(n/2:n/2+n));
            drawnow;
         end;    	
      end;  	   
    end  	    

      
      
% ==============
% Ende des Demos
% ==============

	set([startHndl closeHndl IniHndl SpHndl],'Enable','on');
   set(stopHndl,'Enable','off');
   delete(ax1);
   delete(ax2);
	   
end;    	
