function [out, f] = staticmix( in, ds)
% Return a static mix of various filter types
%
%  Usage: 
%    [out,f] = staticmix( in, ds);
%
%  Inputs:
%    in: NxM matrix, containing one source in every row
%    ds: NxN description matrix
%
%  Outputs:
%    out: If there is only one output it returns the mixing
%         filters in an NxN FIR matrix structure,
%         otherwise an NxM matrix containing the mixtures
%    f: Contains the mixing filters in an NxN FIR matrix structure
%
%  Notes:
%    The description matrix data to describe each filter.  It is 
%    a cell matrix with each cell containing a structure with the
%    elements s, o, n and m.  Each of those elements takes on the
%    value same-named variable from the mfilter function.  So an
%    input like:
%
%        st.s = 'sparse';
%        st.o = 128;
%        st.n = 1;
%        st.m = 10;
%        ds{1,1} = st;
%        ds{1,2} = st;
%        ds{2,1} = st;
%        ds{2,2} = st;
%
%    Would make a 2x2 FIR mixing matrix with filters generated from
%    the command mfilter( 'sparse', 128, 1, 10);  See mfilter for 
%    description of that command.

% Default case
if nargin == 1
	st.s = 'sparse';
	st.o = 128;
	st.n = 1;
	st.m = 10;
	ds{1,1} = st;
	ds{1,2} = st;
	ds{2,1} = st;
	ds{2,2} = st;
end

[r,c] = size( in);

% Make filters
for i = 1:r
	for j = 1:r
		if strcmp( ds{i,j}.s, 'dense')
			f{i,j} = mfilter( ds{i,j}.o, ds{i,j}.s, ds{i,j}.n);
		elseif strcmp( ds{i,j}.s, 'sparse')
			f{i,j} = mfilter( ds{i,j}.o, ds{i,j}.s, ds{i,j}.n, ds{i,j}.m);
		elseif strcmp( ds{i,j}.s, 'delay')
			f{i,j} = mfilter( ds{i,j}.o, ds{i,j}.s);
		else
			error( 'Unknown filter type');
		end		
	end
end

% Plot them
p = 1;
for i = 1:r
	for j = 1:r
		subplot( r, r, p)
		bar( f{j,i})
		grid on
		p = p + 1;
	end
end

% Make mix if needed
if nargout == 2
	out = zeros( size( in));
	for i = 1:r
		for j = 1:r
			out(i,:) = out(i,:) + fftfilt( f{i,j}, in(j,:));
		end
	end
end

% Return just the filters
if nargout == 1
	out = f;
end
