view arrows/audio_bench.m @ 61:eff6bddf82e3 tip

Finally implemented perceptual brightness thing.
author samer
date Sun, 11 Oct 2015 10:20:42 +0100
parents ae596261e75f
children
line wrap: on
line source
% audio_bench - put given arrow between audio input and output
%
% audio_bench :: 
%    N:natural  ~'audio frame size',
%    M:natural  ~'audio hop size',
%    list(string) ~'list of audio file names',
%    arrow({[[N,W]]}, {[[N,W]]}, S) ~'arrow to process audio buffers',
%    options {
%       fs      :: nonneg/22050 ~'audio sampling rate';
%       scope   :: natural/0    ~'figure for waveform plot, 0 to disable';
%       batch   :: natural/1 ~'width of buffers';
%       state   :: S/[]      ~'initialise with this state';
%       outbuf  :: natural/2 ~'increase audio output buffer by this many frames';
%       run     :: bool/0    ~'if true, run the arrow in arrow_sched';
%       start   :: bool/1    ~'if running and true, start immediately';
%       period  :: nonneg/0.003 ~'if running timer period in seconds';
%       liveaudio :: bool/0 ~'if true, ignore files and use live audio input';
%    }
% -> arrow( {}, {}, T) ~'arrow describing whole system',
%    [[1,P]->[2]}      ~'path to state S in overall state T',
%    T,                ~'final state if returned from repl'.
%
% This provides an environment for running an audio processing arrow.
% Audio is provided in NxW buffers where N is the frame length and W is determined
% by the batch options. Hop size is M. Audio is obtained from the given list of files.
%
% The processing arrow is initially run as fast as possible, but if the value in the
% 'output select' is changed from 1 to 2, output is played on audio output device.
% If it is set to 3, the original audio input is played unmodified.
%
% If the 'liveaudio' option is set, then the list of files is ignored and live audio
% input used instead.
%
% If 'run' is false, the arrow describing the system is returned, but if true, the
% system is instantiated using arrow_sched and the user dropped into the 'with_sched>>'
% interactive interpreter loop. The loop can be exitted by typing 'return' or 'ret(...)'.
% If 'ret(..)' is used, then the value supplied is returned as the second return value
% from audio_bench.

function [o,path,r]=audio_bench(N,M,filelist,a,varargin)
	opts=options('fs',22050,'period',0.003,'outbuf',3,'run',0,'start',1,'output',1, ...
					'scope',0,'state',[],'batch',1,'liveaudio',0,'playthru',0,'draw',1,varargin{:});

	if opts.scope>0
		scope_sink=plotter('fig',opts.scope,'ylim',[-1,1]);
		if 0
			if opts.batch>1
				scope1=obs_with(arr(@(t)t(:,1))*scope_sink);
			else
				scope1=obs_with(scope_sink);
			end
		else
			%scope=@(a)a*arr(@(x1,x2)deal(x1,x2,[x1(:,1),x2(1:M,1)]),'nargout',3)*(aid+aid+scope_sink);
			scope=@(a)a*arr(@scope_join)*(aid+aid+scope_sink);
		end
	else 
		scope=@id;
	end

	fprintf('Creating audio source with %d files.\n',length(filelist));
	if opts.liveaudio
		src=linein(1,opts.fs,'bufsize',4*N);
	else
		src=resamplex(opts.fs,map(@monofile,filelist),'bs',2^nextpow2(M*opts.batch));
	end
	aout=abufsink(lineout(1,opts.fs,'bufsize',(opts.outbuf+opts.batch)*M),1:M);

	o= (	abufsig(src,N,M,opts.batch) ...
		*  dup * scope(a + aid)...
		*  (aid + aid + esender('init',num2str(opts.output),'fig',29,'name','output select')*arr(@selout))...
		*	aswitch(unbox(selout({opts.output}))) ...
		);

	path=[1,1,2,1]; % path to state of a in state of o 
	if ~isempty(opts.state), o=o^opts.state; disp('Initialising...'); end
	if opts.run==1, 
		r=arrow_sched(o,opts.period,'start',opts.start); 
	elseif opts.run==2
		r=with_arrow(o,@run,{});
	else
		r=[];
	end

	function r=run(unit)
		uiterate(unit,inf,'draw',1,'chunk',100);
		r=0;
	end

	function [x1,x2,x3]=scope_join(x1,x2)
		x3=[x1(1:M,1),x2(1:M,1)];
	end

	function o=selout(cn)
		if ~iscell(cn) || isempty(cn), o={};
		else
			switch cn{1}
				case 1, o={anull+anull};
				case 2, o={aout+anull};
				case 3, o={anull+aout};
				otherwise, o={};
			end
		end
	end
end
function x=unbox(y), x=y{1}; end