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;