www.gusucode.com > 声音的处理有:LPC,FFT,共振峰,频谱源码程序 > siganlandsystemusingMatlab/SSUM/physmodel/string/stringexpofn.m

    function stringexpofn(action, datastruct)

    if nargin < 1
        action='init';
    end

	name = mfilename;
	figname = [name(1:end-2) '_fig'];
	f=findobj('Tag',figname);
    handles = get(f,'UserData');

    switch action
		case 'help'
			display_help(figname);
        case 'init'
            setdefaults;
            set(handles.loss,'Enable','inactive');
            movegui(f,'center');
            handles.excite_position = 0.5;
            handles.pickup_position = 0.25;
            handles.excite_amplitude = 1.0;
            handles.pickupdata = [0 0];
            handles.N = 1024*4;
            handles.l = linspace(0,1,handles.N);
            handles.y = zeros(1,handles.N);
            handles.drawpoints = [0.5 0];
            handles = initstring(handles);
            handles = plotstring(handles);
            axes(handles.pickupplot);
            handles.pickupdataplot = plot(handles.pickupdata);
            grid on;
            axis([0 100 -1.1 1.1]);
            set(handles.pickupplot,'XTickLabel',[]);
        case 'move_setup'
            contents = get(handles.excite_menu,'String');
            switch contents{get(handles.excite_menu,'Value')}
                case {'Pluck','Strike','Draw'}
                    set(gcf,'WindowButtonMotionFcn','stringexpofn movepoint');
                    set(gcf,'WindowButtonUpFcn','stringexpofn release');
            end
        case 'move_pickup_setup'
            set(gcf,'WindowButtonMotionFcn','stringexpofn movepickup');
            set(gcf,'WindowButtonUpFcn','stringexpofn release');
        case 'movepoint'
            handles = movepoint(handles);
            handles = initstring(handles);
            handles = plotstring(handles);
        case 'movepickup'
            handles = movepickup(handles);
            set(handles.pickup,'XData', handles.pickup_position);
            handles.pickupindex = floor(handles.N*handles.pickup_position);
            set(handles.pickup,'YData', ...
                handles.udl(handles.pickupindex) + ...
                handles.ldl(handles.pickupindex));

        case 'release'
            set(gcf,'WindowButtonMotionFcn','');
            set(gcf,'WindowButtonUpFcn','');
        case 'resize'
            movegui(f,'onscreen');
        case 'reset'      
            if ~strcmp(get(handles.play,'String'),'Stop')
                set(handles.play,'String','Play');
                set(handles.excite_menu,'Enable','on');
                drawnow;
            end
            handles = initstring(handles);
            handles = plotstring(handles);
            axes(handles.pickupplot);
            handles.pickupdata = [0 0];
            handles.pickupdataplot = plot(handles.pickupdata);
            grid on;
            axis([0 100 -1 1]);
            set(handles.pickupplot,'XTickLabel',[]);
        case 'excitetype'
            contents = get(handles.excite_menu,'String');
            switch contents{get(handles.excite_menu,'Value')}
                case 'Draw'
                    % Set windowdownfcn
                    handles = initstring(handles);
                    handles = plotstring(handles);
                otherwise
                    handles = initstring(handles);
                    handles = plotstring(handles);  
						end
				case 'play'
						if (strcmp(get(handles.play,'String'),'Play'))
                set(handles.play,'String','Stop');
            else
                set(handles.play,'String','Play');
            end
            set(handles.tip,'Visible','off');
            clear handles.tip;
            
            
            timestep = str2num(get(handles.timestep,'String'));
            % Disable GUI elements
            set(handles.excite_amplitude_slider,'Enable','off');
            set(handles.excite_menu,'Enable','off');
            set(handles.model_menu,'Enable','off');
            
            loss = 1.0 - str2num(get(handles.loss,'String'));
						ex_contents = get(handles.excite_menu,'String');
    
						contents = get(handles.model_menu,'String');
						switch contents{get(handles.model_menu,'Value')}
								case {'Ideal','Lossy'}
										while (strcmp(get(handles.play,'String'),'Stop'))
												% Move last timestep sample from udl into last sample of ldl

												tempvals = handles.ldl(1:timestep);
												handles.ldl = [handles.ldl(timestep+1:end) ...
														-loss*fliplr(handles.udl(end-timestep+1:end))];
												handles.udl = [-loss.*fliplr(tempvals) handles.udl(1:end-timestep)];
												updatestring(handles);

												switch ex_contents{get(handles.excite_menu,'Value')}
													case 'Strike'
														% Fill up pickupdata
														handles.pickupdata = [handles.pickupdata; ...
																handles.udl(handles.pickupindex) + handles.ldl(handles.pickupindex) + ...
																0.99*handles.pickupdata(end,1) ...
																handles.pickupdata(end,2)+1];
													otherwise
														% Fill up pickupdata
														handles.pickupdata = [handles.pickupdata; ...
																handles.udl(handles.pickupindex) + handles.ldl(handles.pickupindex) ...
																handles.pickupdata(end,2)+1];
												end

												drawnow;

												updatepickupplot(handles);
										end
								case 'Loss(f)'
										N = 33;
										if timestep < 3*N
												N = floor(timestep/3);
										end
										num = ones(1,N)./N;
										while (strcmp(get(handles.play,'String'),'Stop'))
												tempvals_ldl = [handles.ldl(1:timestep)];
												tempvals_udl = [handles.udl(end-timestep+1:end)];
												tempvals_ldl = filtfilt(num,1,tempvals_ldl);
												tempvals_udl = filtfilt(num,1,tempvals_udl);
												handles.ldl = [handles.ldl(timestep+1:end) ...
														-loss*fliplr(tempvals_udl(1:timestep))];
												handles.udl = [-loss.*fliplr(tempvals_ldl(1:timestep)) ...
														handles.udl(1:end-timestep)];
												updatestring(handles);
												% Update pickupdata info
%                         if size(handles.pickupdata,1) > 100
%                             handles.pickupdata = [handles.pickupdata(2:end,:); ...
%                                 handles.udl(handles.pickupindex) + ...
%                                    handles.ldl(handles.pickupindex) ...
%                                 handles.pickupdata(end,2)+1];
%                         else
														% Fill up pickupdata
												switch ex_contents{get(handles.excite_menu,'Value')}
													case 'Strike'
														% Fill up pickupdata
														handles.pickupdata = [handles.pickupdata; ...
																handles.udl(handles.pickupindex) + handles.ldl(handles.pickupindex) + ...
																0.99*handles.pickupdata(end,1) ...
																handles.pickupdata(end,2)+1];
													otherwise
														% Fill up pickupdata
														handles.pickupdata = [handles.pickupdata; ...
																handles.udl(handles.pickupindex) + handles.ldl(handles.pickupindex) ...
																handles.pickupdata(end,2)+1];
												end
												
%                         end
												updatepickupplot(handles);
												drawnow;
										end
						end
            
            set(handles.model_menu,'Enable','on');
            set(handles.excite_menu,'Enable','on');
            set(handles.excite_amplitude_slider,'Enable','on');
		    set(handles.play,'String','Play');
		case 'print'
			print_figure(f);
		case 'close'
			close_figure(f,figname(1:end-4));
			return;
	end
	set(f,'UserData',handles);

% --------------------------------------------------------------------

function ud = initstring(ud)
   
    pos = ud.excite_position;
    pupos = ud.pickup_position;
    amp = get(ud.excite_amplitude_slider,'Value');
    
    samplepos = floor(ud.N*pos);
    ud.pickupindex = floor(ud.N*pupos);
    y = zeros(1,ud.N);
    contents = get(ud.excite_menu,'String');
    
    switch contents{get(ud.excite_menu,'Value')}
        case 'Pluck'
            y(1:samplepos) = amp/pos*ud.l(1:samplepos);
            y(samplepos+1:end) = -amp/(1-pos)*(ud.l(samplepos+1:end)-pos)+amp;
        case 'Strike'
            hammerl = floor(ud.N/50);
            if samplepos+hammerl > ud.N,
                samplepos = ud.N-hammerl-1;
            end
            y(samplepos:samplepos+hammerl) = amp;
        case 'Random'
            sig = 0.5 - rand(1,ud.N-2);
            % lowpass filter
            [N, Wn] = ellipord(0.05,0.075,1,40);
            [B,A] = ellip(N,1,40,Wn,'low');
            sig = filter(B,A,sig);
            sig = amp*sig./max(sig);
            y(1,2:end-1) = sig;
        case 'Draw'
            for i=1:size(ud.drawpoints,1)
                pos = ud.drawpoints(i,1);
                amp = ud.drawpoints(i,2);

                samplepos = floor(ud.N*pos);
                y(1:samplepos) = amp/pos*ud.l(1:samplepos);
                y(samplepos+1:end) = -amp/(1-pos)*(ud.l(samplepos+1:end)-pos)+amp;
            end
    end
    ud.tippos = [samplepos/ud.N, y(samplepos)];
    ud.pickuppos = [ud.pickupindex/ud.N y(ud.pickupindex)];
    ud.udl = y/2;
    ud.ldl = y/2;
    ud.y = y;

function ud = plotstring(ud)
    axes(ud.stringplot);
    ud.sumplot = plot(ud.l,ud.y);
    hold on;
    ud.udlplot = plot(ud.l,ud.udl,'r');
    ud.ldlplot = plot(ud.l,ud.ldl,'r');
    
    contents = get(ud.excite_menu,'String');
    
    switch contents{get(ud.excite_menu,'Value')}
        case 'Random'
            ud.tip = plot(ud.tippos(1),ud.tippos(2));
        otherwise
            ud.tip = plot(ud.tippos(1),ud.tippos(2),'o');
            set(ud.tip, 'ButtonDownFcn','stringexpofn move_setup');
    end
    
    ud.pickup = stem(ud.pickuppos(1),ud.pickuppos(2),'k');
    set(ud.pickup,'ShowBaseline','off','MarkerFaceColor','black','MarkerSize',8)
    set(ud.pickup, 'ButtonDownFcn','stringexpofn move_pickup_setup');
    grid on;
    hold off;
    set(ud.sumplot,'LineWidth',2);  
    set(ud.stringplot,'XTickLabel',[],'YTickLabel',[]);
    axis([0 1 -1.05 1.05]);
    
function updatestring(ud)
    axes(ud.stringplot);
    set(ud.sumplot,'YData',ud.udl+ud.ldl);
    set(ud.udlplot,'YData',ud.udl);
    set(ud.ldlplot,'YData',ud.ldl);
    set(ud.pickup,'YData',ud.udl(ud.pickupindex)+ud.ldl(ud.pickupindex));
    
function updatepickupplot(ud)
    axes(ud.pickupplot);
    set(ud.pickupdataplot,'YData',ud.pickupdata(:,1));
    set(ud.pickupdataplot,'XData',ud.pickupdata(:,2));
    axispos = get(ud.pickupplot,'XLim');
    if (ud.pickupdata(end,2) > axispos)
        set(ud.pickupplot,'XLim',[axispos(1) axispos(2)+50])
    end

function ud = movepoint(ud)
    currentPoint=get(gca,'CurrentPoint');
    
    xnew = currentPoint(1,1);
    ynew = currentPoint(1,2);
    
    if xnew < 0.01
        xnew = 0.01;
    elseif xnew > 0.99
        xnew = 0.99;
    end
    
    if ynew < -1
        ynew = -1;
    elseif ynew > 1
        ynew = 1;
    end
    
    ud.excite_position = xnew;
    ud.excite_amplitude = ynew;
    set(ud.excite_amplitude_slider,'Value',ynew);
    
function ud = movepickup(ud)
    currentPoint=get(gca,'CurrentPoint');
    
    xnew = currentPoint(1,1);
  
    if xnew < 0.01
        xnew = 0.01;
    elseif xnew > 0.99
        xnew = 0.99;
    end
    
    ud.pickup_position = xnew;