# HG changeset patch # User samer # Date 1355957165 0 # Node ID 289445d368a7914519c423c8fb20c1ed48b5bc64 # Parent 672052bd81f86ac4377112da82e91b82c6e4b469 import. diff -r 672052bd81f8 -r 289445d368a7 signals/@sigarray/sigarray.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigarray/sigarray.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,46 @@ +classdef sigarray < signal + properties (GetAccess=private, SetAccess=immutable) + fs + array + end + methods + function s=sigarray(array,rate) + if nargin<2, rate=nan; end + s.array=array; + s.fs=rate; + end + + function s=tostring(sig) + s=sprintf('sigarray(<%dx%d>)',size(sig.array,1),size(sig.array,2)); + end + + function c=channels(s), c=size(s.array,1); end + function c=rate(s), c=s.fs; end + function s=construct(sig) + array=sig.array; + ch=size(array,1); + length=size(array,2); + pos=0; + + s.start = @nop; + s.stop = @nop; + s.dispose = @nop; + s.reader = @reader; + + function r=reader(n) + r = @next; + CHUNK = 1:uint32(n); + function [x,rem]=next + if pos+n<=length + x=array(:,pos+CHUNK); rem=0; + pos=pos+n; + else + rem=n-(length-pos); + x=[array(:,pos+1:end),zeros(ch,rem)]; + pos=length; + end + end + end + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigbase/sigbase.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigbase/sigbase.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,17 @@ +classdef sigbase < signal + properties (GetAccess=protected, SetAccess=immutable) + chans + fs + end + methods + function s=sigbase(channels,rate) + if nargin<2, rate=nan; end + if nargin<1, channels=nan; end + s.chans=channels; + s.fs=rate; + end + + function c=channels(s), c=s.chans; end + function c=rate(s), c=s.fs; end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigbinop/sigbinop.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigbinop/sigbinop.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,54 @@ +classdef sigbinop < signal + properties (GetAccess=private, SetAccess=immutable) + op + sig1 + sig2 + chans + end + methods + function s=sigbinop(f,sig1,sig2,chf) + if isinf(unify_rates(rate(sig1),rate(sig2))), + error('Sample rate mismatch'); + end + if nargin<4, + chf=@(c1,c2)size(f(zeros(c1,1),zeros(c2,1)),1); + end + s.op=f; + s.sig1=sig1; + s.sig2=sig2; + s.chans=chf(channels(sig1),channels(sig2)); + end + + function c=channels(s), c=s.chans; end + function r=rate(s), r=rate(s.sig1); end + function s=construct(sig) + + s1=construct(sig.sig1); + s2=construct(sig.sig2); + op=sig.op; + + s.start = @start; + s.stop = @stop; + s.dispose = @dispose; + s.reader = @reader; + + function start, s1.start(); s2.start(); end + function stop, s1.stop(); s2.stop(); end + function dispose, s1.dispose(); s2.dispose(); end + function r=reader(n) + r1=s1.reader(n); + r2=s2.reader(n); + r =@next; + function [x,rem]=next + [x1,rem1]=r1(); + [x2,rem2]=r2(); + x=op(x1,x2); + rem=max(rem1,rem2); + end + end + end + function s=tostring(sig) + s=sprintf('(%s <%s> %s)',tostring(sig.sig1),tostring(sig.op),tostring(sig.sig2)); + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigcat/sigcat.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigcat/sigcat.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,52 @@ +classdef sigcat < sigbase + properties (GetAccess=private, SetAccess=immutable) + signals + end + methods + function s=sigcat(varargin) + fs=foldl(@unify_rates,nan,map(@rate,varargin)); + if isinf(fs), error('sampling rate mismatch'); end + ch=foldl(@unify_channels,nan,map(@channels,varargin)); + if isinf(ch), error('channel count mismatch'); end + s=s@sigbase(ch,fs); + s.signals=varargin; + end + + function s=tostring(sig) + n=length(sig.signals); + strx=map(@tostring,sig.signals); + if n==1, s=strx{1}; + elseif n==2, s=sprintf('%s & %s',strx{1},strx{2}); + else s=sprintf('sigcat(%s,...)',strx{1}); + end + end + + function s=construct(sig) + sc=construct(sig.signals{1}); + sx=sig.signals(2:end); + + s.start = @start; + s.stop = @stop; + s.dispose = @dispose; + s.reader = @reader; + + function start, sc.start(); end + function stop, sc.stop(); end + function dispose, sc.dispose(); end + + function r=reader(n) + rc=sc.reader(n); + r = @next; + function [x,rem]=next + [x,rem]=rc(); + while rem>0 && ~isempty(sx) % current signal exhausted, try next + sc.dispose(); + sc=construct(sx{1}); sx=sx(2:end); + [x(:,end-rem+1:end),rem]=sigreadn(sc,rem); + rc=sc.reader(n); + end + end + end + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigconst/sigconst.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigconst/sigconst.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,29 @@ +classdef sigconst < signal + properties (GetAccess=private, SetAccess=immutable) + val + fs + end + methods + function s=sigconst(val,rate) + if nargin<2, rate=nan; end + s.val=reshape(val,size(val,1),1); + s.fs=rate; + end + + function s=tostring(sig), s=sprintf('sigconst(%s)',mat2str(sig.val)); end + function c=channels(s), c=size(s.val,1); end + function c=rate(s), c=s.fs; end + function s=construct(sig) + s.start = @nop; + s.stop = @nop; + s.dispose = @nop; + s.reader = @reader; + + function r=reader(n) + r = @next; + buf=repmat(sig.val,1,double(n)); + function [x,rem]=next, x=buf; rem=0; end + end + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigdrop/sigdrop.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigdrop/sigdrop.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,25 @@ +classdef sigdrop < signal + properties (GetAccess=private, SetAccess=immutable) + todrop % natural + sig % signal(C,R) + end + methods + function s=sigdrop(n,sig) + s.todrop=n; + s.sig=sig; + end + + function s=tostring(sig) + s=sprintf('drop(%d,%s)',sig.todrop,tostring(sig.sig)); + end + + function c=rate(s), c=rate(s.sig); end + function c=channels(s), c=channels(s.sig); end + function s=construct(sig) + s=construct(sig.sig); + s.start(); + sigreadn(s,sig.todrop); + s.stop(); + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigempty/sigempty.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigempty/sigempty.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,22 @@ +classdef sigempty < sigbase + methods + function s=sigempty(channels,rate) + if nargin<2, rate=nan; end + s=s@sigbase(channels,rate); + end + + function s=tostring(sig), s='sigempty'; end + function s=construct(sig) + s.start = @nop; + s.stop = @nop; + s.dispose = @nop; + s.reader = @reader; + + function r=reader(n) + r = @next; + buf=zeros(sig.channels,double(n)); + function [x,rem]=next, x=buf; rem=n; end + end + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigfun/sigfun.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigfun/sigfun.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,36 @@ +classdef sigfun < signal + properties (GetAccess=private, SetAccess=immutable) + fun + fs + end + methods + function s=sigfun(fun,rate) + s.fun=fun; + s.fs=rate; + end + + function s=tostring(sig), s=sprintf('sigfun(%s)',tostring(sig.fun)); end + function c=channels(s), c=size(s.fun(0),1); end + function c=rate(s), c=s.fs; end + + function s=construct(sig) + fun=sig.fun; + t=0; + + s.start = @nop; + s.stop = @nop; + s.dispose = @nop; + s.reader = @reader; + + function r=reader(n) + r = @next; + T=(0:n-1)/sig.fs; + dt=n/sig.fs; + function [x,rem]=next, + x=fun(t+T); rem=0; + t=t+dt; + end + end + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@siglzcat/construct.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@siglzcat/construct.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,35 @@ +function s=construct(sig) + fs=rate(sig.head); + ch=channels(sig.head); + sc=construct(sig.head); + sx=sig.tail; + + s.start = @start; + s.stop = @stop; + s.dispose = @dispose; + s.reader = @reader; + + function start, sc.start(); end + function stop, sc.stop(); end + function dispose, sc.dispose(); end + function r=reader(n) + rc=sc.reader(n); + r = @next; + function [x,rem]=next + [x,rem]=rc(); + while rem>0 && ~isempty(sx) % current signal exhausted, try next + sc.dispose(); + [sig2,sx]=sx(); + + fs=unify_rates(fs,rate(sig2)); + if isinf(fs), error('sigcat:Signal sampling rate mismatch'); end + ch=unify_channels(ch,channels(sig2)); + if isinf(ch), error('sigcat:Signal channels count mismatch'); end + sc=construct(sig2); + + [x(:,end-rem+1:end),rem]=sigreadn(sc,rem); + rc=sc.reader(n); + end + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@siglzcat/siglzcat.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@siglzcat/siglzcat.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,20 @@ +classdef siglzcat < signal + properties (GetAccess=private, SetAccess=immutable) + head + tail + end + methods + function s=siglzcat(head,tail) + if isnan(channels(head)), error('First signal to siglzcat must have determinate channels'); end + s.head=head; + s.tail=tail; + end + + function s=tostring(sig) + s=sprintf('%s > %s',tostring(sig.head),tostring(sig.tail)); + end + + function c=rate(s), c=rate(s.head); end + function c=channels(s), c=channels(s.head); end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigmap/sigmap.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigmap/sigmap.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,40 @@ +classdef sigmap < signal + properties (GetAccess=private, SetAccess=immutable) + fun + sig + chans + end + methods + function s=sigmap(f,sig,chf) + if nargin<3, chf=@(c1)size(f(zeros(c1,1)),1); end + s.fun=f; + s.sig=sig; + s.chans=chf(channels(sig)); + end + + function s=tostring(sig) + s=sprintf('map(%s,%s)',tostring(sig.fun),tostring(sig.sig)); + end + + function c=rate(s), c=rate(s.sig); end + function c=channels(s), c=s.chans; end + + function s=construct(sig) + f=sig.fun; + s1=construct(sig.sig); + s.start = s1.start; + s.stop = s1.stop; + s.dispose = s1.dispose; + s.reader = @reader; + + function r=reader(n) + r1=s1.reader(n); + r =@next; + function [x,rem]=next + [x1,rem]=r1(); + x=f(x1); + end + end + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@signal/gather.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@signal/gather.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,33 @@ +% gather - collect all samples from a finite signal +% gather :: signal(C,R), options -> [[C,N]]. +function x=gather(sig,varargin) + opts=prefs('chunk',256,'init',512,'grow',2,'max',1e9,varargin{:}); + + s=construct(sig); + try % to make sure we dispose of s once opened + chunk=uint32(opts.chunk); + n=uint32(0); CHUNK=1:chunk; + cap=opts.init; % initial capacity of buffer + x=zeros(channels(sig),cap); % buffer + r=s.reader(opts.chunk); + rem=0; + s.start(); + while rem==0 + if n+chunk>cap % need more room + if n>opts.max, error('maximum capacity exceeded'); end + cap=opts.grow*cap; + x=repmat(x,1,opts.grow); + end + [x(:,n+CHUNK),rem]=r(); + n=n+chunk; + end + n=n-rem; % remove rem samples from end + catch ex + s.dispose(); + rethrow(ex); + end + s.stop(); + s.dispose(); + x=x(:,1:n); % grab only valid samples +end + diff -r 672052bd81f8 -r 289445d368a7 signals/@signal/gathern.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@signal/gathern.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,31 @@ +% gathern - Collect exactly n samples from a signal +% +% gathern :: N:natural, signal(C,R), options -> [[C,N]], natural. +function [x,rem]=gathern(m,sig,varargin) + opts=prefs('chunk',256,varargin{:}); + + s=construct(sig); + try % to make sure we dispose of s once opened + chunk=uint32(opts.chunk); + n=uint32(0); CHUNK=1:chunk; + x=zeros(channels(sig),m); + r=s.reader(opts.chunk); + rem=0; + while rem==0 && n+chunk<=m + [x(:,n+CHUNK),rem]=r(); + n=n+chunk; + end + if nopts.max, error('maximum length exceeded'); end + end + n=n-uint64(rem); % remove rem samples from end + catch ex + s.dispose(); + rethrow(ex); + end + s.dispose(); + n=double(n); +end diff -r 672052bd81f8 -r 289445d368a7 signals/@signal/signal.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@signal/signal.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,71 @@ +% signal - Base class for signal +% +% signal :: signal(C:natural,R:nonneg). +% +% The signal(C,R) type denotes the type of a signal with C +% channels and a sampling rate of R. +% +% The base signal class cannot be used without subclassing since +% any attempt to instantiate the live signal generator will throw +% an exception. +% +% METHODS +% channels :: signal(C,R) -> natural. +% rate :: signal(C,R) -> nonneg. +% construct:: signal(C,R) -> livesig(C). +% length :: signal(C,R) -> natural. +% gather :: signal(C,R), options -> [[C,N]]. +% gathern :: N:natural, signal(C,R), options -> [[C,N]], natural. +% +% livesig(C) :== struct { +% start :: void->void; +% stop :: void->void; +% dispose :: void->void; +% reader :: N:natural -> (void->[[C,N]]); +% } + +classdef signal + properties (GetAccess=private, SetAccess=immutable) + end + methods + function s=signal, end + + function s=and(s1,s2), s=sigcat(s1,s2); end + function y=cache(x), y=reclock(rate(x),sigarray(gather(x))); end + function c=channels(s), error('number of channels undefined'); end + function s=construct(sig), error('Cannot construct base signal class'); end + function display(a) + disp(sprintf(' %s :: signal(%s,%s)',tostring(a),fmt(channels(a)),fmt(rate(a)))); + function s=fmt(x), if isnan(x), s='_'; else s=num2str(x); end; end + end + + function y=map(f,x), y=sigmap(f,x); end + function s=mpower(a,b), s=resample(b,a); end + function s=or(s1,s2), s=sigbinop(@vertcat,s1,s2,@plus); end + function r=rate(s), error('sampling rate undefined'); end + function s2=reclock(r,s1), s2=sigreclock(r,s1); end + function y=drop(n,x), y=sigdrop(n,x); end + function y=take(n,x), y=sigtake(n,x); end + + function y=dropt(t,x), + if isnan(rate(x)), error('Cannot dropt without definite sampling rate'); end + y=sigdrop(round(t*rate(x)),x); + end + + function y=taket(t,x), + if isnan(rate(x)), error('Cannot taket without definite sampling rate'); end + y=sigtake(round(t*rate(x)),x); + end + + function y=cycle(x), + y=siglzcat(x,@cyclef); + function [s1,sx]=cyclef, s1=x; sx=@cyclef; end + end + + function s2=resample(f2,s1,varargin) + if isnan(rate(s1)), error('no sample rate set'); end + if rate(s1)==f2, s2=s1; + else, s2=sigresample(f2,s1,varargin{:}); end + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigreclock/sigreclock.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigreclock/sigreclock.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,17 @@ +classdef sigreclock < signal + properties (GetAccess=private, SetAccess=immutable) + fs + sig + end + methods + function s=sigreclock(rate,sig) + s.fs=rate; + s.sig=sig; + end + + function s=tostring(sig), s=sprintf('reclock(%g,%s)',sig.rate,tostring(sig.sig)); end + function s=construct(sig), s=construct(sig.sig); end + function c=channels(s), c=channels(s.sig); end + function c=rate(s), c=s.fs; end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigresample/construct.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigresample/construct.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,88 @@ +function s2=construct(sig) + + fprintf('\nResampling %s to %g Hz...\n',tostring(sig.source),sig.rate); + f1=rate(sig.source); + f2=sig.rate; + c=channels(sig); + + [p,q]=rat(f2/f1,1e-12); + sysobj=design(sig,p,q); + + + delay=(length(sysobj.Numerator)-1)/2; + outdelay = ceil(delay/q); + indelay = ceil(delay/p); + m=max(1,floor(sig.opts.bs/q)); % try to approximate requested input block size + fprintf('Input/output delays are %d and %d.\n',indelay,outdelay); + fprintf('Read block size is %d.\n\n',m*q); + + s1=construct(sig.source & sigarray(zeros(channels(sig.source),indelay))); + r1=s1.reader(m*q); % one and only input reader + chunk=uint32(m*p); % filter output block size + CHUNK=1:chunk; + queue=[]; + + s2.start = s1.start; + s2.stop = s1.stop; + s2.dispose = @dispose; + s2.reader = @reader; + + % drop some samples to account for filter delay + s2.start(); + sigreadn(s2,outdelay); + s2.stop(); + + function dispose, s1.dispose(); release(sysobj); end + function r2=reader(n) + outbuf=zeros(c,n); + r2=@next; + + function [x,rem]=next + % transfer up to n queued samples to outbuf + pos=uint32(size(queue,2)); + if pos>=n % enough samples already waiting + outbuf=queue(:,1:n); + queue=queue(:,n+1:end); + rem=0; + else + if pos==0, toread=n; + else % use up queue + outbuf(:,1:pos)=queue; queue=[]; + toread=n-pos; + end + + % transfer complete chunks + while toread>=chunk + [outbuf(:,pos+CHUNK),rem]=filter_next; + toread=toread-chunk; + pos=pos+chunk; + if rem>0 % we ran out of samples + rem=rem+toread; % account for rest of missing samples (not just this chunk) + toread=0; % causes immediate exit after this + end + end + + % transfer partial chunk if necessary + if toread>0 + [y,rem]=filter_next; + outbuf(:,pos+1:n)=y(:,1:toread); + queue=y(:,toread+1:chunk-rem); + rem=max(0,toread-(chunk-rem)); + end + end + x=outbuf; + end + + % returns the next block of m*p output samples + function [x,rem]=filter_next + [y,rem1]=r1(); + if rem1>0, + y(:,end-rem1+1:end)=zeros(c,rem1); % pad with zeros + rem=uint32(ceil(rem1*p/q)); % round down the number of valid samples + else + rem=rem1; + end + x=step(sysobj,y')'; + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigresample/design.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigresample/design.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,26 @@ +function so=design(sig,p,q) + f1=rate(sig.source); + f2=rate(sig); + if isfield(sig.opts,'passband') + relpass=2*sig.opts.passband/min(f1,f2); + elseif isfield(sig.opts,'relpass') + relpass=sig.opts.relpass; + elseif isfield(sig.opts,'reltrans') + relpass=(1-sig.opts.reltrans); + else + relpass=nan; + end + + if isnan(relpass) && ~isfield(sig.opts,'order') + so=dsp.FIRRateConverter(p,q,mfilt.firsrc(p,q).Numerator); + else + tw = max(0.01,1-relpass)*min(f1,f2)/2; + if isfield(sig.opts,'astop') + fsrc=fdesign.rsrc(p,q,'Nyquist',max(p,q),'TW,Ast',tw,sig.opts.astop,p*f1); + else + if isfield(sig.opts,'order'), order = sig.opts.order; else order = 12; end + fsrc=fdesign.rsrc(p,q,'Nyquist',max(p,q),'N,TW',2*order*max(p,q),tw,p*f1); + end + so=design(fsrc,'kaiserwin','SystemObject',true); + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigresample/sigresample.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigresample/sigresample.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,25 @@ +classdef sigresample < signal + properties (GetAccess=private, SetAccess=immutable) + fs + source + opts + end + methods + function s=sigresample(fs,sig1,varargin) + if fs==rate(sig1), sig2=sig1; + else + opts=prefs('bs',1024,varargin{:}); + s.source=sig1; + s.fs=fs; + s.opts=opts; + end + end + + function s=tostring(sig) + s=sprintf('resample(%g,%s)',sig.rate,tostring(sig.source)); + end + + function c=channels(s), c=channels(s.source); end + function r=rate(s), r=s.fs; end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigtake/construct.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigtake/construct.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,28 @@ + +function s=construct(sig) + sc=construct(sig.sig); + length=uint32(sig.len); + + s.start = sc.start; + s.stop = sc.stop; + s.dispose = sc.dispose; + s.reader = @reader; + + function r=reader(n) + rc=sc.reader(n); + r = @next; + n=uint32(n); + function [x,rem]=next + [x,rem]=rc(); + if length>n + length=length-n; + elseif length>0 + rem=max(rem,n-length); + length=0; + last=x(:,end); + else + rem=n; + end + end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/@sigtake/sigtake.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/@sigtake/sigtake.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,16 @@ +classdef sigtake < signal + properties (GetAccess=private, SetAccess=immutable) + len + sig + end + methods + function s=sigtake(n,sig) + s.len=n; + s.sig=sig; + end + + function s=tostring(sig), s=sprintf('take(%d,%s)',sig.len,tostring(sig.sig)); end + function c=channels(s), c=channels(s.sig); end + function c=rate(s), c=rate(s.sig); end + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/TODO --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/TODO Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,10 @@ +stateful generators: + unfold S -> (X,S) loop(0 -> 1) + scan (Y,X) -> X states(loop(1 -> 0)) + mapaccum (Y,S) -> (X,S) loop(1 -> 1) + zipaccum (Y1,...,S) -> (X,S) loop(N -> 1) + iterate X -> X states(loop(0 -> 0)) + + +signal length? +sndfile from shell pipe diff -r 672052bd81f8 -r 289445d368a7 signals/mixdown.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/mixdown.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,5 @@ +function y=mixdown(x), + cin=channels(x); + y=sigmap(@mix,x,@(c)1); + function z=mix(w), z=sum(w,1)/cin; end +end diff -r 672052bd81f8 -r 289445d368a7 signals/private/unify.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/private/unify.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,9 @@ +% this is weird but it works +% nan means variable, so max(nan,x)=x +% inf means failure so max(inf,x)=inf +function z=unify(x,y) + if ~isfinite(x) || ~isfinite(y), z=max(x,y); + elseif x==y, z=x; + else z=inf; + end +end diff -r 672052bd81f8 -r 289445d368a7 signals/resamplex.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/resamplex.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,37 @@ +function s=resamplex(fs,sigs,varargin) + opts=prefs(varargin{:}); + [s1,sx]=feval(rsx1(sigs{1},sigs(2:end))); + s=siglzcat(s1,sx); + + function f=rsx1(h,t), f=@()rsx3({h},rate(h),t); end + function [s1,sx]=rsx3(heads,fh,tails) + if ~isempty(tails) && rate(tails{1})==fh + [s1,sx]=rsx3([heads,tails(1)],fh,tails(2:end)); + else + s1=resample(fs,sigcat(heads{:}),opts); + if isempty(tails), sx=[]; + else sx=rsx1(tails{1},tails(2:end)); + end + end + end +end + +function s=resamplex1(fs,signals) + s=rsx1(signals); + + function s=rsx1(signals) + s=rsx3(signals(1),rate(signals{1}),signals(2:end)); + end + + function s=rsx3(heads,fh,tails) + if ~isempty(tails) && rate(tails{1})==fh + s=rsx3([heads,tails(1)],fh,tails(2:end)); + else + headsig=resample(fs,sigcat(heads{:}),opts); + if isempty(tails), s=headsig; + else s=siglzcat(headsig, @()deal(rsx1(tails),[])); + end + end + end +end + diff -r 672052bd81f8 -r 289445d368a7 signals/sconst.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/sconst.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,1 @@ +function s=sconst(x), s=sigconst(x(:)); end diff -r 672052bd81f8 -r 289445d368a7 signals/sigcatx.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/sigcatx.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,1 @@ +function s=sigcatx(signals), s=sigcat(signals{:}); diff -r 672052bd81f8 -r 289445d368a7 signals/sigpar.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/sigpar.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,1 @@ +function y=sigpar(x1,x2), y=sigbinop(@vertcat,x1,x2,@plus); diff -r 672052bd81f8 -r 289445d368a7 signals/sigreadn.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/sigreadn.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,3 @@ +function [x,rem]=sigread1(src,n) + r=src.reader(n); + [x,rem]=r(); diff -r 672052bd81f8 -r 289445d368a7 signals/sigrep.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/sigrep.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,3 @@ +function s=sigrep(n,x) + %s=sigarray(repmat(x,1,n)); + s=take(n,sigconst(x)); diff -r 672052bd81f8 -r 289445d368a7 signals/sigsel.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/sigsel.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,2 @@ +function y=sigsel(chans,x) + y=sigmap(@(t)t(chans,:),x,@(c)length(chans)); diff -r 672052bd81f8 -r 289445d368a7 signals/snull.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/snull.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,1 @@ +function s=snull, s=sigconst([]); diff -r 672052bd81f8 -r 289445d368a7 signals/sones.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/sones.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,1 @@ +function s=sones(n,m), s=sigarray(ones(n,m)); diff -r 672052bd81f8 -r 289445d368a7 signals/szeros.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/szeros.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,1 @@ +function s=szeros(n,m), s=sigarray(zeros(n,m)); diff -r 672052bd81f8 -r 289445d368a7 signals/transfer.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/transfer.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,41 @@ +% transfer - Transfer samples from a signal to a sink +% +% transfer :: signal(C,R), sink(C,R) -> action natural. +% +% Returns the number of samples transfered. +function n=transfer(sig,sink,varargin) + opts=prefs('chunk',512,varargin{:}); + chunk=uint32(opts.chunk); + + u=construct(sink); + try + write=u.writer(chunk); + s=construct(sig); + try % to make sure we dispose of s once opened + n=uint32(0); CHUNK=1:chunk; + x=zeros(channels(sig),chunk); % buffer + r=s.reader(opts.chunk); + rem=0; + s.start(); + u.start(); + while rem==0 + [x,rem]=r(); + if rem==0, rem=write(x); + else rem=rem+write(x(:,1:end-rem)); + end + n=n+(chunk-rem); + end + u.stop(); + s.stop(); + catch ex + s.dispose(); + rethrow(ex); + end + catch ex + u.dispose(); + rethrow(ex); + end + + s.dispose(); + u.dispose(); +end diff -r 672052bd81f8 -r 289445d368a7 signals/unify_channels.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/unify_channels.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,2 @@ +function z=unify_channels(x,y), z=unify(x,y); end + diff -r 672052bd81f8 -r 289445d368a7 signals/unify_rates.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/signals/unify_rates.m Wed Dec 19 22:46:05 2012 +0000 @@ -0,0 +1,5 @@ +% this is weird but it works +% nan means variable, so max(nan,x)=x +% inf means failure so max(inf,x)=inf +function z=unify_rate(x,y), z=unify(x,y); end +