Mercurial > hg > ishara
changeset 42:ae596261e75f
Various fixes and development to audio handling
line wrap: on
line diff
--- a/TODO Tue Jan 29 17:22:52 2013 +0000 +++ b/TODO Tue Dec 02 14:51:13 2014 +0000 @@ -13,3 +13,10 @@ actions and functions analogues of arrow combinators + +Rationalise buffering + +small to large by stacking along some dimension +large to small: slices of along some dimension +arbitrary rebuffering along some dimension +
--- a/arrows/@asampler/asampler.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/@asampler/asampler.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,4 +1,4 @@ -% asampler - sampling arrow +% asampler - random sampling arrow % % asampler :: % (E -> [E->A]) ~'function to generate sample array of given size',
--- a/arrows/@asink/construct.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/@asink/construct.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,9 +1,13 @@ function u=construct(s,sizes_in) u=mkunit(s); - if sizes_in{1}(1)~=channels(s.sink) - error('Number of rows in input does not match channels in sink'); + if ~isa(s.sink,'sink') + snk=construct(s.sink(sizes_in{1}(1))); + else + if sizes_in{1}(1)~=channels(s.sink) + error('Number of rows in input does not match channels in sink'); + end + snk=construct(s.sink); end - snk=construct(s.sink); if isempty(s.window), write=snk.writer(sizes_in{1}(2));
--- a/arrows/@unfolder/unfolder.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/@unfolder/unfolder.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,4 +1,4 @@ -% unfolder - unfolding arrow +% unfolder - arrow to generate sequence by unfolding state % % unfolder :: % (S -> B, S) ~'function to state to output and next state',
--- a/arrows/alatch.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/alatch.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,4 +1,4 @@ -% alatch - Arrow which produced the value in the last event received. +% alatch - Arrow which produces the value in the last event received. % % alatch :: A -> arrow( {box(A)}, {A}, A). function o=alatch(x0)
--- a/arrows/alinein.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/alinein.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,6 +1,6 @@ -% linein - Audio input arrow +% alinein - arrow to input audio as overlapped frames % -% linein :: +% alinein :: % nonneg ~'sampling rate', % N:natural ~'block size', % M:natural ~'hop size',
--- a/arrows/anull.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/anull.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,4 +1,4 @@ -% asink - Do nothing absorbing arrow +% anull - arrow to absorb given number of inputs % % asink :: N:natural -> arrow(_@typelist(N),{},empty). function a=asink(nin)
--- a/arrows/audio_bench.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/audio_bench.m Tue Dec 02 14:51:13 2014 +0000 @@ -73,12 +73,19 @@ 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, + 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
--- a/arrows/azeromean.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/azeromean.m Tue Dec 02 14:51:13 2014 +0000 @@ -24,7 +24,9 @@ nans=isnan(offset); offset(nans)=x(nans); y = x-repmat(offset,1,size(x,2)); - offset = offset + rate*sum(score(y),2); + delta = rate*sum(score(y),2); + delta(~isfinite(delta))=0; + offset = offset + delta; end function [y,offset]=update_t(x,offset) @@ -34,7 +36,9 @@ y = x; for i=1:w y(:,i)=y(:,i)-offset; - offset = offset + rate*(score(y(:,i))+reg(offset)); + delta = rate*(score(y(:,i))+reg(offset)); + delta(~isfinite(delta))=0; + offset = offset + delta; end end
--- a/arrows/dsp/adct.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/dsp/adct.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,13 +1,16 @@ % adct - arrow for DCT % % adct :: M:natural -> arrow({[[N]]}, {[[M]]}, empty). +% +% Produces only the first M DCT coefficients function o=adct(M) + I=1:M; o=arrf(@mkdct,1,1); function f=mkdct(sizes_in) % take DCT size from size(1) of first input - W=row(dct(eye(sizes_in{1}(1))),M); - f=@(x)W*x; + %W=row(dct(eye(sizes_in{1}(1))),M); + f=@(x)row(dct(x),I); end end
--- a/arrows/stats/accumstats.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/stats/accumstats.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,4 +1,4 @@ -% accumstats - arrow that collects 1st and 2nd order statistics (struct version) +% accumstats - Arrow that collects 1st and 2nd order statistics (struct version) % % accumstats :: arrow({[[N]]},{stats_struct(N)},stats_struct(N)). % accumstats :: nonneg -> arrow({[[N]]},{stats_struct(N)},stats_struct(N)).
--- a/arrows/stats/stats_pca.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/stats/stats_pca.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,29 +1,20 @@ -function o=astats_pca(I) - %GMM=gmm('full'); - %m0=GMM.blank(1,N); - o=arr(@stats_pca); - function pca=stats_pca(stats) - if isstruct(stats) - m1=mstep(stats); - [V,D]=eig(m1.cov); - J=(1+size(D,1))-I; - pca.eigvecs=V(:,J); - pca.eigvals=diag(D); - pca.eigvals=max(0,pca.eigvals(J)); - pca.mean=m1.mu; - else - pca.dummy=1; - end - end - function M=mstep(S) - M.mu=S.amu/S.ag; - M.cov=msym(S.aco/S.ag - M.mu*M.mu'); - end +function pca=stats_pca(stats,I) + m1=mstep(stats); + [V,D]=eig(m1.cov); + J=(1+size(D,1))-I; + pca.eigvecs=V(:,J); + pca.eigvals=diag(D); + pca.eigvals=max(0,pca.eigvals(J)); + pca.mean=m1.mu; +end +function M=mstep(S) + M.mu=S.amu/S.ag; + M.cov=msym(S.aco/S.ag - M.mu*M.mu'); +end - function M=mstep_z(S) - M.mu=zeros(size(S.aco,1),1); - M.cov=S.aco/S.ag; - end +%function M=mstep_z(S) +% M.mu=zeros(size(S.aco,1),1); +% M.cov=S.aco/S.ag; +%end - function A=msym(X), A=(X+X')/2; end -end +function A=msym(X), A=(X+X')/2; end
--- a/arrows/ugather.m Tue Jan 29 17:22:52 2013 +0000 +++ b/arrows/ugather.m Tue Dec 02 14:51:13 2014 +0000 @@ -19,15 +19,30 @@ function X=ugather(u,its,varargin) opts=options('expand',1,varargin{:}); - if opts.expand && isinf(its) - X=zeros(u.sizes_out{1}(1),32); % initial size is arbitrarily 32 - done=uiter(u,its,@gatherxx,[],'label','ugather',opts); - if done<size(X,2), X=X(:,1:done); end + szout = u.sizes_out{1}; + + if szout(2)==1 + if opts.expand && isinf(its) + X=zeros(szout(1),32); % initial size is arbitrarily 32 + done=uiter(u,its,@gatherxx,[],'label','ugather',opts); + if done<size(X,2), X=X(:,1:done); end + else + if ~isinf(its), X=zeros(szout(1),its); end + + done=uiter(u,its,@gatherx,[],'label','ugather',opts); + if done<its, X=X(:,1:done); end + end else - if ~isinf(its), X=zeros(u.sizes_out{1}(1),its); end + if opts.expand && isinf(its) + X=zeros(szout(1),32); % initial size is arbitrarily 32 + done=szout(2)*uiter(u,its,@gatherxxw,[],'label','ugather',opts); + if done<size(X,2), X=X(:,1:done); end + else + if ~isinf(its), X=zeros(szout(1),its*szout(2)); end - done=uiter(u,its,@gatherx,[],'label','ugather',opts); - if done<its, X=X(:,1:done); end + done=szout(2)*uiter(u,its,@gatherxw,[],'label','ugather',opts); + if done<its, X=X(:,1:done); end + end end function s=gatherx(i,s), X(:,i)=u.process(); end @@ -38,6 +53,21 @@ end X(:,i)=u.process(); end + + function s=gatherxw(i,s), + i1=1+(i-1)*szout(2); + i2=i*szout(2); + X(:,i1:i2)=u.process(); + end + function s=gatherxxw(i,s), + i1=1+(i-1)*szout(2); + i2=i*szout(2); + if i2>size(X,2), + %fprintf('ugather: expanding at %d.\n',size(X,2)); + X=[X,zeros(size(X))]; % double size + end + X(:,i1:i2)=u.process(); + end end
--- a/audio/@linein/linein.m Tue Jan 29 17:22:52 2013 +0000 +++ b/audio/@linein/linein.m Tue Dec 02 14:51:13 2014 +0000 @@ -14,7 +14,7 @@ methods function s=linein(channels,rate,varargin) s=s@sigbase(channels,rate); - s.opts = options('bufsize',0,'bits',16,varargin{:}); + s.opts = options('bufsize',0,'bits',16,'quiet',0,varargin{:}); end function c=tostring(sig), c='linein'; end @@ -24,8 +24,10 @@ src=LineSource(audio_format(sig.channels,sig.rate,sig.opts.bits),sig.opts.bufsize); ref=disposables('reg',src); - fprintf('\nOpened audio input device:\n %s\n',char(src.toString)); - fprintf(' Actual buffer size is %d.\n',src.getLine.getBufferSize); + if ~sig.opts.quiet + fprintf('\nOpened audio input device:\n %s\n',char(src.toString)); + fprintf(' Actual buffer size is %d.\n',src.getLine.getBufferSize); + end s.stop = @stop; s.start = @start;
--- a/audio/@lineout/lineout.m Tue Jan 29 17:22:52 2013 +0000 +++ b/audio/@lineout/lineout.m Tue Dec 02 14:51:13 2014 +0000 @@ -15,7 +15,7 @@ end methods function s=lineout(channels,rate,varargin) - s.opts = options('bufsize',0,'bits',16,'pad',0,varargin{:}); + s.opts = options('bufsize',0,'bits',16,'pad',0,'quiet',0,varargin{:}); s.chans=channels; s.fs=rate; end @@ -30,8 +30,10 @@ snk.setScale(0.999); line=snk.getLine(); ref=disposables('reg',snk); - fprintf('\nOpened audio output device:\n %s\n',char(snk.toString)); - fprintf(' Actual buffer size is %d.\n',snk.getLine.getBufferSize); + if ~sig.opts.quiet + fprintf('\nOpened audio output device:\n %s\n',char(snk.toString)); + fprintf(' Actual buffer size is %d.\n',snk.getLine.getBufferSize); + end if sig.opts.pad>0, fprintf(' Padding start and stop with %d samples.\n',sig.opts.pad);
--- a/audio/mp3file.m Tue Jan 29 17:22:52 2013 +0000 +++ b/audio/mp3file.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,4 +1,9 @@ function s=mp3dec(file,varargin) - s=sndpipe(sprintf('mpg123 --au - "%s"',file),'stringfn',@()sprintf('mp3file(''%s'')',file),varargin{:}); + % NB: mpg123 was sometimes putting the wrong sampling rate in the header (expecting to seek + % back and fix it after writing) but mpg321 seems to get it right first time. + + % mpg321 broken in Macports, 17th Nov 2014 + % s=sndpipe(sprintf('mpg321 --au - "%s"',file),'stringfn',@()sprintf('mp3file(''%s'')',file),varargin{:}); + s=sndpipe(sprintf('sox -t mp3 "%s" -t au -',file),'stringfn',@()sprintf('mp3file(''%s'')',file),varargin{:}); end
--- a/audio/private/pipein.m Tue Jan 29 17:22:52 2013 +0000 +++ b/audio/private/pipein.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,7 +1,32 @@ function [str,cleanup]=pipein(cmd,q) + import java.io.*; + if nargin<2, q=false; end if ~q, fprintf('Starting sub-process: %s\n',cmd); end - process=java.lang.Runtime.getRuntime().exec({'bash','-c',cmd}); + + % OK, here's the deal: the line below doesn't work if Matlab and + % Java do not agree about their default character encoding, which + % can happen if you change Matlab's character encoding with, eg + % >> feature('DefaultCharacterSet','UTF-8') + % As far as a I can tell, you cannot change the character encoding + % using by Runtime.exec() for command line arguments once the JVM + % has been started, and, somewhat perversely, Matlab ingores the + % value of the LANG environment variable on startup, preferring to + % us the encoding specified in $MATLAB_ROOT/bin/lcdata.xml + + % NOT GOOD: + % process=java.lang.Runtime.getRuntime().exec({'bash','-c',cmd}); + + % this is what we're going to do instead: start bash with no + % arguments to make it read from standard input, then write cmd + % with proper encoding to that stream. + + % BETTER: + cs=feature('DefaultCharacterSet'), + process=java.lang.Runtime.getRuntime().exec('bash'); + writer=OutputStreamWriter(process.getOutputStream(),cs); + writer.write(cmd); writer.close(); + str=process.getInputStream(); cleanup=@dispose;
--- a/audio/sndfile.m Tue Jan 29 17:22:52 2013 +0000 +++ b/audio/sndfile.m Tue Dec 02 14:51:13 2014 +0000 @@ -16,9 +16,15 @@ % Javazoom MP3 decoder does not get the length of the signal right. % Would be better to use mpg123 on a pipe in this case. function s=sndfile(file,varargin) + if iscell(file) + s=taket(file{2}-file{1},dropt(file{1},sndfile(file{3}))) + return + end string=sprintf('sndfile(''%s'')',file); if endswith(file,'mp3') || endswith(file,'MP3') s=mp3file(file,'stringfn',@()string,varargin{:}); % Java version doesn't remove padding correctly + elseif endswith(file,'m4a') + s=aacfile(file,'stringfn',@()string,varargin{:}); else s=sndstream(@filestream,'stringfn',@()string,varargin{:}); end
--- a/dsp/specgrm.m Tue Jan 29 17:22:52 2013 +0000 +++ b/dsp/specgrm.m Tue Dec 02 14:51:13 2014 +0000 @@ -5,7 +5,8 @@ % N:natural | H:[[N]] ~'window length or window', % M:natural ~'hop size', % options { -% fs :: nonneg/1 ~'sampling rate' +% fs :: nonneg/1 ~'sampling rate'; +% range:: [[2]] ~'range for tfdimage' % } % -> [[1+N/2,floor(T/M)]] ~'sequence of short term spectra'. % @@ -26,7 +27,9 @@ % Make Spectrogram Display if no arg out if nargout==0 - tfdimage(y,n,m,getparam(options(varargin{:}),'fs',1)); + opts=options('fs',1,'range',13.5,varargin{:}); + + tfdimage(y,n,m,opts.fs,opts.range); clear y; end
--- a/dsp/synth/@sine/block.m Tue Jan 29 17:22:52 2013 +0000 +++ b/dsp/synth/@sine/block.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,5 +1,13 @@ function [y,phi]=block(o,phi,n,f) -% block - generate sine wave +% block - generate block of sine wave samples +% +% sine/block :: +% sine ~'sine generator object', +% real ~'phase at start of block', +% N:natural ~'number of samples to generate', +% real ~'frequence in cycles per sample' +% -> [[1,N]] ~'block of output samples', +% real ~'phase at end of block'. w=2*pi*f; y=sin(2*pi*phi + w*(0:n-1));
--- a/dsp/synth/@sine/block_sr.m Tue Jan 29 17:22:52 2013 +0000 +++ b/dsp/synth/@sine/block_sr.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,5 +1,13 @@ function [y,phi]=block(o,phi,f) -% block_sr - generate sine wave +% block_sr - generate block of sine wave samples with signal rate control +% +% sine/block :: +% sine ~'sine generator object', +% real ~'phase at start of block', +% [[1,N]] ~'frequency at signal rate', +% -> [[1,N]] ~'block of output samples', +% real ~'phase at end of block'. + u=cumsum([phi,f],2); y=sin(2*pi*u(1:end-1));
--- a/general/disposables.m Tue Jan 29 17:22:52 2013 +0000 +++ b/general/disposables.m Tue Dec 02 14:51:13 2014 +0000 @@ -23,8 +23,10 @@ varargout{1}=obj; case 'dereg', obj=varargin{1}; - idx=find(registry==obj); - registry=registry([1:idx-1,idx+1:length(registry)]); + if ~isempty(registry) + idx=find(registry==obj); + registry=registry([1:idx-1,idx+1:length(registry)]); + end case 'get' varargout{1}=registry; case 'dispose'
--- a/general/funutils/@function_handle/and.m Tue Jan 29 17:22:52 2013 +0000 +++ b/general/funutils/@function_handle/and.m Tue Dec 02 14:51:13 2014 +0000 @@ -18,7 +18,7 @@ if nargin<4, nout=nargout(g); end if nargin<3, nin=nargin(g); end fns = { @q11, @q1n; @qn1, @qnn }; - h=fns{acount(nin,1),acount(nout,1)}; + h=fns{acount(nin,1,1),acount(nout,1,1)}; function y=q11(x), f(x); y=g(x); end function y=qn1(varargin), f(varargin{:}); y=g(varargin{:}); end function varargout=q1n(x), f(x); [varargout{1:nargout}]=g(x); end
--- a/general/funutils/@function_handle/private/acount.m Tue Jan 29 17:22:52 2013 +0000 +++ b/general/funutils/@function_handle/private/acount.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,1 +1,3 @@ -function n=acount(m,k), if m<0 || m>k, n=k+1; else n=m; end; end +function n=acount(m,k,j), + if nargin<3, j=0; end + if m<j || m>k, n=k+1; else n=m; end; end
--- a/general/funutils/@function_handle/table.m Tue Jan 29 17:22:52 2013 +0000 +++ b/general/funutils/@function_handle/table.m Tue Dec 02 14:51:13 2014 +0000 @@ -25,15 +25,14 @@ end function varargout=lookup(varargin) - matches=select(@(r)isequal(varargin,r(1:nin)),slices(Table,1)); - if isempty(matches) - [varargout{1:nout}]=f(varargin{:}); - Table=vertcat(Table,[varargin,varargout]); - else - varargout=col(head(matches),nin+(1:nout)); + for i=1:size(Table,1) + if isequal(varargin,Table(i,1:nin)), + varargout=Table(i,nin+(1:nout)); + return; + end end + [varargout{1:nout}]=f(varargin{:}); + Table=vertcat(Table,[varargin,varargout]); end end - -
--- a/general/funutils/README.txt Tue Jan 29 17:22:52 2013 +0000 +++ b/general/funutils/README.txt Tue Dec 02 14:51:13 2014 +0000 @@ -23,20 +23,18 @@ <= le - select input args from cell array ' ctranspose - flip 1st and 2nd args - [f1,f2,...,fn] == f1|f2|...|fn - [f1;f2;...;fn] == f1&f2&...&fn - f/x/y^z == f.^{x,y,z} + Unused operators: .' .* ~ unary + unary - - Unused operators: .* -Old functions (some not functional algebraic) - bind1 - partial application, arbitrary arity - flip - apply - compose +Old functions + + bind1 - same as rdivide or ./ + flip - same as ctranspose or ' + apply - samer as mpower or .^ + compose - same as ctranspose(@mtimes) doreturn(f,x,y,...) == feval([f<[];@deal],x,y,...) nthret(I,f,x,y,...) == feval(f>I,x,y,...)
--- a/general/tostring.m Tue Jan 29 17:22:52 2013 +0000 +++ b/general/tostring.m Tue Dec 02 14:51:13 2014 +0000 @@ -13,7 +13,7 @@ if ischar(x), s=x; elseif isnumeric(x), sz=size(x); - if prod(sz)<16, s=mat2str(x); + if prod(sz)<16, s=mat2str(x,5); else s=sprintf('%s[%s]',class(x),mat2str(sz)); end elseif isa(x,'function_handle'), s=func2str(x); if s(1)~='@', s=['@' s]; end
--- a/sequences/+seq/unfold_finite.m Tue Jan 29 17:22:52 2013 +0000 +++ b/sequences/+seq/unfold_finite.m Tue Dec 02 14:51:13 2014 +0000 @@ -1,7 +1,7 @@ % unfold_finite - sequence obtained by iterating fn over state % % unfold_finite :: -% (S->A,S) ~'unfolding function', +% (S->pair(A,S)) ~'unfolding function', % S ~ initial state, % -> unfold_finite(S,A) < seq(A). % @@ -19,7 +19,7 @@ methods (Static) function d=make(f,s0) xs=f(s0); - if isempty(xs), d=nil; else d=unfold_finite(f,xs{2},xs{1}); end + if isempty(xs), d=nil; else d=seq.unfold_finite(f,xs{2},xs{1}); end end end methods
--- a/sequences/framedata.m Tue Jan 29 17:22:52 2013 +0000 +++ b/sequences/framedata.m Tue Dec 02 14:51:13 2014 +0000 @@ -25,7 +25,7 @@ [span,jump]=windowparams(size(signal),frame,hop,width,opts); if isempty(opts.random), - wd=windowdata(signal,span,jump,'wrap',opts.wrap,'dim',opts.dim); + wd=window(signal,span,jump,'wrap',opts.wrap,'dim',opts.dim); else wd=rndwindow(signal,span,opts.dim); end
--- a/sinks/@sinkarray/sinkarray.m Tue Jan 29 17:22:52 2013 +0000 +++ b/sinks/@sinkarray/sinkarray.m Tue Dec 02 14:51:13 2014 +0000 @@ -15,9 +15,9 @@ methods function s=sinkarray(cont,ch,len,rate) if nargin<4, rate=nan; end + s=s@sinkbase(ch,rate); s.length=len; s.cont=cont; - s=s@sinkbase(ch,rate); end function s=tostring(sig), @@ -25,15 +25,20 @@ end function s=construct(sig) - length=sig.length; - ch=channels(sig); - array=zeros(ch,length); - pos=0; - s.start = @nop; s.stop = @nop; - s.dispose = @dispose; - s.writer = @writer; + if isfinite(sig.length) + length=sig.length; + array=zeros(channels(sig),length); + pos=0; + + s.dispose = @dispose; + s.writer = @writer; + else + gg=gatherer([channels(sig),1]); + s.dispose = @dispose_gatherer; + s.writer = @writer_gatherer; + end function dispose, sig.cont(array(:,1:pos)); end @@ -52,6 +57,16 @@ end end end + + function dispose_gatherer, sig.cont(gg.collect()); end + function r=writer_gatherer(n) + r = @next; + function rem=next(x) + n=size(x,2); + for i=1:n, gg.append(x(:,i)); end + rem=0; + end + end end end end