% abufsig - Arrow which produces multiple buffered frames from a signal
%
% abufsig :: 
%    signal(C,R),
%    N:natural ~'block size',
%    M:natural ~'hop size',
%    L:natural ~'buffer width'
% -> arrow({},{[[N*C,L]]}).
%
% abufsig :: 
%    signal(C,R),
%    N:natural ~'block size',
%    M:natural ~'hop size'
% -> arrow({},{[[N*C,1]]]}).
%
% abufsig :: 
%    signal(C,R),
%    N:natural ~'block size',
% -> arrow({},{[[C*N,1]]]}).
%
% If hop size is omitted, it defaults to the block size.
% If buffer width is omitted, it defaults to 1.

function o=abufsig(source,block,hop,width)
	if nargin<4, width=1; end
	if nargin<3, hop=block; end

	ch=channels(source);
	if (mod(block,ch)>0 || mod(hop,ch))
		error('Block size and hop must be a multiple of channel count'); 
	end

	if width==1,
		o=asignal(source,block/ch,hop/ch)*arr(@flt);
	else
		olap = block-hop;
		span = (hop*(width-1)+block);	
		jump = (hop*width);
		o=asignal(source,span/ch,jump/ch)*arr(@buf);
	end

	function y=flt(x), y=x(:); end
	function y=buf(x), y=buffer(x(:),block,olap,'nodelay'); end
end

