Mercurial > hg > ishara
view audio/playaudio_unfold.m @ 61:eff6bddf82e3 tip
Finally implemented perceptual brightness thing.
author | samer |
---|---|
date | Sun, 11 Oct 2015 10:20:42 +0100 |
parents | beb8a3f4a345 |
children |
line wrap: on
line source
function [Sched,GetData]=playaudio_unfold(buflen,unfold_fn,S,Snk,varargin) % playaudio_async - Play stream of audio data asynchronously % % playaudio :: % N:natural ~'buflen', % (S->[[C,N]],S) ~'unfolding function', % sink(C,R) ~'sink for C channels', % options { % maxbuf :: natural/2*max(size(X)) ~'maximum buffer size'; % hook :: (iterator(S)->iterator(T)) ~'fn to build iterator'; % onstart :: A -> action ~'called BEFORE timer starts'; % onstop :: A -> action ~'called AFTER timer stops'; % onfinish:: A -> action ~'called when end of signal reached'; % defer :: bool / 0 ~'if 1, don't start the timer' % } % -> sched(S) ~'scheduler api functions', % (S -> [[N]]) ~'function to recover audio from iterator state'. % % iterator(S) ::= cell {(S->action S)~'state transformer', S~'initial state'}. % % sched(S) ::= struct { % dispose :: unit -> action unit; % isrunning :: unit -> action bool; % startat :: real -> action unit; % start :: unit -> action unit; % stop :: unit -> action unit; % rewind :: unit -> action unit; % getstate :: unit -> action S; % setstate :: S -> action unit % }. % % The 'hook' option gives the caller an opportunity to elaborate on the % 'iterator' used to drive the audio playback. The 'iterator' is a cell % array contain a state transformer function and initial state. The caller % can use this to build a more complex iterator the does other things % for each buffer of samples. % % The third return value is a function which can be used in a state % transformer function to recover a buffer of audio samples from the % current state. % % NB: all the audio buffers must be the same size for this to work. % NB: the rewind function should only be called when the timer is stopped. N=buflen; opts=options('onstop',@nop,'onstart',@nop,'onfinish',@nop, ... 'period_adjust',0.9,'preload',2,'sched',@iterate_timed,varargin{:}); it=feval(getparam(opts,'hook',@id),{@playbuf,S}); maxbuf=getparam(opts,'maxbuf',2*N); sync_delta=getparam(opts,'sync_delta',0.02); sync_offset=getparam(opts,'sync_offset',0); L=construct(Snk); write=L.writer(maxbuf); period=(N/rate(Snk))*opts.period_adjust; Sched=opts.sched(it{1},it{2},period, ... 'exec_mode','fixedRate', 'busy_mode','drop', opts, ... 'onstart',@onstart,'onstop',@onstop); getstate=Sched.getstate; odispose=Sched.dispose; Sched.atend=@()isempty(getstate()); Sched.dispose=@dispose; Sched.setGain=L.setGain; GetData=@head; function dispose odispose(); L.dispose(); end function onstart(S), opts.onstart(S); L.start(); for i=1:opts.preload write(zeros(maxbuf,1)); end end function onstop(S), write(zeros(maxbuf,1)); L.stop(); opts.onstop(S); end function S=playbuf(S) [y,S]=unfold_fn(S); n=size(y,2); if n>0, write(y); end end end