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

    function stochofn(action)
	if nargin < 1
		action='init';
	end

	% Modularize
	% Percent overlap working?
	% Add composing in progress dialog

	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'
			% Load in image data
			[x, cmap] = imread('stocho_gradient.jpg');
			h_axis=axes('pos',[0 0 1 1]);
			image(x);
			colormap(cmap);
			set(h_axis,'TickDir', 'out')
			% Strange hack
			set(handles.s1_vol,'BackgroundColor',get(handles.s1_start,'BackgroundColor'))
			handles.Fs = 44100;
			setdefaults;
		case 'compose'
			section = handles.section;
			signal = synthesize(handles,section);
			eval(['handles.signal_' num2str(section) ' = signal;']);
			eval(['set(handles.s' num2str(section) '_mix,''Value'',1);']);
			set(f,'UserData',handles);
			stochofn 'plot'
		case 'play'
			if (handles.section == 0)
				handles.signal_0 = mixsections(handles);
			end
			playsound(handles);
		case 'spectrum'
			if (handles.section == 0)
				handles.signal_0 = mixsections(handles);
			end
			specsound(handles);
		case 'plot'
			if (handles.section == 0)
				handles.signal_0 = mixsections(handles);
			end
			plotsound(handles);
		case 'load_settings'
			handles = load_settings(handles);
		case 'save_settings'
			save_settings(handles);
		case 'write_soundfile'
			write_soundfile(handles);
		case 'vol_edit'
			section = handles.section;
			eval(['val = str2double(get(handles.s' num2str(section) '_vol,''String''));']);
			if (val > 1)
				eval(['set(handles.s' num2str(section) '_vol,''String'',''1.0'');']);
				val = 1;
			elseif (val < 0)
				eval(['set(handles.s' num2str(section) '_vol,''String'',''0.0'');']);
				val = 0;
			end
			eval(['set(handles.s' num2str(section) '_volslider,''Value'', val);']);
		case 'vol_slider'
			section = handles.section;
			eval(['set(handles.s' num2str(section) '_vol,''String'',num2str(get(handles.s' num2str(section) '_volslider,''Value''),2));']);
		case 'close'
			close_figure(f,figname(1:end-4));
            return;
	end
	set(f,'UserData',handles);
	
% --------------------------------------------------------------------
% This function taken from DSPFirst
function y = mattostr(x,style)
	%MATTOSTR
	%-------
	%   usage:  mattostr(X,STYLE)
	%   convert an entire matrix X to formatted numbers,
	%       using a C format in STYLE, e.g., '%3.f'

	%  version 4.x only....v4 handles NaN in printf
	[N,M] = size(x);
	tt = sprintf(style,x.');
	Lt = length(tt);
	y = reshape( tt, Lt/N, N ).';

% Compute random number between matrix numbers
function [num] = getrand(var)
	if (size(var,2) > 1)
		num = var(1) + rand*(var(2)-var(1));
	else
		num = var;
	end

% --------------------------------------------------------------------
function env = getampenv(section, handles)
	eval(['contents = get(handles.s' num2str(section) '_ampenv,''String'');']);
	eval(['value = contents{get(handles.s' num2str(section) '_ampenv,''Value'')};']);
	env = [0 1 1 1];
	switch lower(value)
		case 'flat'
			env = [0 1 1 1];
		case 'percussive'
			env = [0 0 0.02 1 1 0];
		case 'sustained'
			env = [0 0 0.2 1 0.7 1 1 0];
		case 'wedge'
			env = [0 0 1 1];
		case 'invwedge'
			env = [0 1 1 0];
		case 'triangle'
			env = [0 0 0.5 1 1 0];
		case 'random'
			segments = floor(10*rand)+1;
			env = zeros(1,segments*2);
			time = cumsum([0 rand(1,segments-1)]);
			time = time./max(time);
			val = rand(1,segments);
			val = val./max(val);
			for i=1:segments,
				env(2*i-1) =  time(i);
				env(2*i) =  val(i);
			end
		case 'create'
	end

% --------------------------------------------------------------------
function env = getfreqenv(section, handles)
	eval(['contents = get(handles.s' num2str(section) '_freqenv,''String'');']);
	eval(['value = contents{get(handles.s' num2str(section) '_freqenv,''Value'')};']);
	env = [0 1 1 1];
	switch lower(value)
		case 'flat'
			env = [0 0 1 0];
		case 'upsweep'
			env = [0 0 1 1];
		case 'downsweep'
			env = [0 1 1 0];
		case 'triangle'
			env = [0 0 0.5 1 1 0];
		case 'random'
			segments = floor(10*rand)+1;
			env = zeros(1,segments*2);
			time = cumsum([0 rand(1,segments-1)]);
			time = time./max(time);
			val = rand(1,segments);
			val = val./max(val);
			for i=1:segments,
				env(2*i-1) =  time(i);
				env(2*i) =  val(i);
			end
		case 'create'
	end

function specsound(handles)
	Fs = handles.Fs;
	section = handles.section;
	eval(['signal = handles.signal_' num2str(section) ';']);
	if (max(signal) > 1.0)
		signal = normalize(signal);
	end
	audiodata.data = signal';
	audiodata.Fs = 44100;
	sonoexpogui(audiodata);

% --------------------------------------------------------------------
% Fix this so that the proper button is relabeled 'Stop'
% --------------------------------------------------------------------
function playsound(handles)
	Fs = handles.Fs;
	section = handles.section;
	eval(['signal = handles.signal_' num2str(section) ';']);
	if (section ~= 0)
		eval(['vol = str2double(get(handles.s' num2str(section) '_vol,''String''));']);
	else
		vol = 1.0;
	end
	eval(['hObject = handles.s'  num2str(section) '_play;']);
	%eval(['buttonstring = get(handles.s' num2str(section) '_play,''String'');']);
	buttonstring = get(hObject,'String');
	if (strncmp(buttonstring,'Play',4))
		signal = signal.*vol;
		if (max(signal) > 1.0)
			signal = signal./(max(signal) + 0.2);
		end
		ud.hButton = hObject;
		if (isunix)
			signal(length(signal):length(signal)+Fs) = 0;
		end
		handles.p = handle(com.mathworks.toolbox.audio.JavaAudioPlayer(signal,Fs,16));
		set(handles.p, 'UserData', ud);
		set(handles.p, 'StopFcn', @play_Ended);
		handles.p.play;
		if (section ~= 0)
			set(ud.hButton,'String','Stop');
		else
			set(ud.hButton,'String','Stop All');
		end
	else
		if (~isunix)
			handles.p.stop;
		end
	end

function play_Ended(hObject, event)
	ud = get(hObject, 'UserData');
	set(ud(1).hButton,'String','Play');

% --------------------------------------------------------------------
function getSpectrum(hObject, eventdata, handles)
	global Fs;
	path(path,'/home/bob/gibson');
	section = handles.section;
	eval(['signal = handles.signal_' num2str(section) ';']);
	sonoexpo2(signal, Fs);

% --------------------------------------------------------------------
function plotsound(handles)
	section = handles.section;
	Fs = handles.Fs;
	eval(['signal = handles.signal_' num2str(section) ';']);
	if (section ~= 0)
		eval(['vol = str2double(get(handles.s' num2str(section) '_vol,''String''));']);
	else
		vol = 1;
	end
	if (exist('signal'))
		signal = signal.*vol;
		sig_plot = figure;
		% We need to create a new figure and store the audio data in it!
		t = (0:length(signal)-1)./Fs;
		han = plot(t,signal);
		%set(han, 'XLim', [0 max(t)]);
		eval(['title(''Section' num2str(section) ''');']);
		xlabel('Time');
		plotplay = uicontrol('String','Play',...
			'Position',[5 40 40 20],...
			'Callback','stochofn play');
		posplay = get(plotplay,'Position');
		plotspec = uicontrol('String','Spectrum',...
			'Position',posplay + [0 -25 20 0],...
			'Callback','stochofn spectrum');
		handles.hObject = plotplay;
		set(han,'UserData',handles);
	else
		% Error popup;
	end

function signal = mixsections(handles)
	Fs = handles.Fs;
	mix = [];
	samples = 0;
	if (get(handles.s1_mix,'Value'))
		volume = str2double(get(handles.s1_vol,'String'));
		signal_1 = handles.signal_1.*volume;
		start_1 = str2double(get(handles.s1_start,'String'));
		mix = [mix 1];
		samples = max(samples,start_1*Fs+length(signal_1)+1);
	end
	if (get(handles.s2_mix,'Value'))
		volume = str2double(get(handles.s2_vol,'String'));
		signal_2 = handles.signal_2.*volume;
		start_2 = str2double(get(handles.s2_start,'String'));
		mix = [mix 2];
		samples = max(samples,start_2*Fs+length(signal_2)+1);
	end
	if (get(handles.s3_mix,'Value'))
		volume = str2double(get(handles.s3_vol,'String'));
		signal_3 = handles.signal_3.*volume;
		start_3 = str2double(get(handles.s3_start,'String'));
		mix = [mix 3];
		samples = max(samples,start_3*Fs+length(signal_3)+1);
	end
	if (samples == 0)
		return
	end

	signal = zeros(1,samples);
	for i=mix,
		eval(['starti = start_' num2str(i) '*Fs+1;']);
		eval(['lengthi = length(signal_' num2str(i) ');']);
		eval(['tempsig = signal_' num2str(i) ';']);
		signal(starti:lengthi+starti-1)=signal(starti:lengthi+starti-1)+tempsig;
	end

% --------------------------------------------------------------------
function signal = synthesize(handles,section)
	Fs = 44100;
	channels = 1;

	numnotes = str2double(eval(['get(handles.s' num2str(section) '_numnotes,''String'')']));
	percent_overlap = str2double(eval(['get(handles.s' num2str(section) '_overlap,''String'')']));

	start_string = eval(['get(handles.s' num2str(section) '_start,''String'')']);
	if (strncmp(start_string,'0 (',3))
		start_string = '0';
	end
	start = eval(['[' start_string ']']);

	npartials_string = eval(['get(handles.s' num2str(section) '_npartials,''String'')']);
	if (strncmp(npartials_string,'min',3))
		npartials_string = '1 3';
	end
	num_partials = eval(['[' npartials_string ']']);

	partials_string = eval(['get(handles.s' num2str(section) '_partials,''String'')']);
	if (strncmp(partials_string,'mul',3))
		partials_string = '1 1 2.05 0.5 3.2 0.2';
	end
	partials = eval(['[' partials_string ']']);

	durs_string = eval(['get(handles.s' num2str(section) '_durs,''String'')']);
	if (strncmp(durs_string,'min',3))
		durs_string = '0.1 1';
	end
	durs = eval(['[' durs_string ']']);

	amps_string = eval(['get(handles.s' num2str(section) '_amps,''String'')']);
	if (strncmp(amps_string,'min',3))
		amps_string = '0.0 1';
	end
	amps = eval(['[' amps_string ']']);

	freqs_string = eval(['get(handles.s' num2str(section) '_freqs,''String'')']);
	if (strncmp(freqs_string,'min',3))
		freqs_string = '100 1000';
	end
	freqs = eval(['[' freqs_string ']']);

	fskews_string = eval(['get(handles.s' num2str(section) '_fskews,''String'')']);
	if (strncmp(fskews_string,'min',3))
		fskews_string = '0.2 0.9';
	end
	fskews = eval(['[' fskews_string ']']);

	matstring = mattostr(num_partials, '%d ');
	eval(['set(handles.s' num2str(section) '_npartials,''String'',''' matstring ''')']);
	matstring = mattostr(partials, '%2.2f ');
	eval(['set(handles.s' num2str(section) '_partials,''String'',''' matstring ''')']);
	matstring = mattostr(durs, '%2.2f ');
	eval(['set(handles.s' num2str(section) '_durs,''String'',''' matstring ''')']);
	matstring = mattostr(amps, '%2.2f ');
	eval(['set(handles.s' num2str(section) '_amps,''String'',''' matstring ''')']);
	matstring = mattostr(freqs, '%2.2f ');
	eval(['set(handles.s' num2str(section) '_freqs,''String'',''' matstring ''')']);
	matstring = mattostr(fskews, '%2.2f ');
	eval(['set(handles.s' num2str(section) '_fskews,''String'',''' matstring ''')']);
	eval(['set(handles.s' num2str(section) '_start,''String'',''' num2str(start) ''')']);

	% Get envelopes
	eval(['contents = get(handles.s' num2str(section) '_ampenv,''String'');']);
	eval(['avalue = contents{get(handles.s' num2str(section) '_ampenv,''Value'')};']);
	eval(['contents = get(handles.s' num2str(section) '_freqenv,''String'');']);
	eval(['fvalue = contents{get(handles.s' num2str(section) '_freqenv,''Value'')};']);
	ampenv = getampenv(section, handles);
	freqenv = getfreqenv(section, handles);

	pscore = cell(numnotes,8);
	begin = 0;
	dur = 0;
	for i=1:numnotes,
		begin = begin + dur*(1 - percent_overlap/100);
		amp = getrand(amps);
		num_p = floor(getrand(num_partials));
		if (num_p > length(partials)/2);
			partamps = rand(1,num_p).*exp(-(1:num_p)/5);
			partfs = cumsum([1 rand(1,num_p-1)]);
			for j=1:num_p,
				parts(2*j-1) = partfs(j);
				parts(2*j) = partamps(j);
			end
		else
			parts = partials(1:2*num_p);
		end
		dur = getrand(durs);
		freq = getrand(freqs);
		fskew = getrand(fskews)*freq;
		if (strcmp(lower(avalue),'random'))
			ampenv = getampenv(section, handles);
		end
		if (strcmp(lower(fvalue),'random'))
			freqenv = getfreqenv(section, handles);
		end
		pscore(i,:) = {begin dur freq fskew amp freqenv ampenv parts};
	end
	signal = synth(pscore, Fs,'add');


% --------------------------------------------------------------------
function handles = load_settings(handles)
	[file, path] = uigetfile({'*.mat','MATLAB datafile'}, 'Open');
	load([path file]);
	% Set text entry items
	hs = {'start', 'numnotes', 'overlap', 'npartials'...
		'partials', 'durs', 'amps', 'freqs', 'fskews', 'vol'};
	for j=1:size(hs,2),
		for i=1:3,
			eval(['set(handles.s' num2str(i) '_' hs{j} ',''String'', s'...
				num2str(i) '_' hs{j} ')']);
		end
	end
	% Set remaining items
	hs = {'ampenv','freqenv','mix'};
	for j=1:size(hs,2),
		for i=1:3,
			eval(['set(handles.s' num2str(i) '_' hs{j} ',''Value'', s'...
				 num2str(i) '_' hs{j} ')']);
	   end
	end
	set(handles.s1_volslider,'Value',str2double(get(handles.s1_vol,'String')));
	set(handles.s2_volslider,'Value',str2double(get(handles.s2_vol,'String')));
	set(handles.s3_volslider,'Value',str2double(get(handles.s3_vol,'String')));
	handles.signal_1 = signal_1;
	handles.signal_2 = signal_2;
	handles.signal_3 = signal_3;

function save_settings(handles)
	[file, path] = uiputfile({'*.mat','MATLAB datafile'}, 'Save as');
	% Save these variables
	savestring = [];
	% Take care of single values
	hs = {'start', 'numnotes', 'overlap', 'npartials'...
		'partials', 'durs', 'amps', 'freqs', 'fskews', 'vol'};
	for j=1:size(hs,2),
		for i=1:3,
			eval(['s' num2str(i) '_' hs{j} '= get(handles.s'...
				 num2str(i) '_' hs{j} ',''String'');']);
			savestring = [savestring '''s' num2str(i) '_' hs{j} ''','];
		end
	end
	% Take care of popup menu items
	hs = {'ampenv','freqenv','mix'};
	for j=1:size(hs,2),
		for i=1:3,
			eval(['s' num2str(i) '_' hs{j} '= get(handles.s'...
				 num2str(i) '_' hs{j} ',''Value'');']);
			savestring = [savestring '''s' num2str(i) '_' hs{j} ''','];
		end
	end
	% Remove last comma
	savestring = savestring(1:end-1);

	% Save sound data too?
	signal_1 = handles.signal_1;
	signal_2 = handles.signal_2;
	signal_3 = handles.signal_3;
	savestring = [savestring ', ''signal_1'', ''signal_2'', ''signal_3'''];

	% Check vaidity of savestring
	%['save([path file],' savestring ')']
	eval(['save([path file],' savestring ');']);

function write_soundfile(handles)
	Fs = handles.Fs;
	signal = mixsections(handles);
	if (max(abs(signal)) > 1)
		signal = signal./(max(signal)+0.1);
	end

	[file, path] = uiputfile({'*.wav','WAV'}, 'Save as');
	wavwrite(signal,Fs,16,[path file]);