function map=specbasis(edges,M)
% specbasis - Create frequency mapping matrix
%
% as_fmap ::
%    [[L-1]]    ~ 'array of L-1 bin edge frequencies, in FT bins',
%    M:natural  ~ 'number of bins in linear-freq spectrum'
% ->
%    [[L,M]]    ~ 'L-by-M sparse array'.
% 
% Converts a filterbank specification into a sparse matrix for
% mutliplying with a linear-frequency spectrogram.
%
% Note, frequencies must measured in bins of the target spectrum,
% Also, the first and last of the L bands are catch-alls which
% get all energy below the bottom edge and above the top edge
% respectively. If, eg, the bottom edge is 0, then the bottom
% band will be empty.

E=repmat([0; edges(:); M-1],1,M);
I=repmat(0:M-1,length(edges)+1,1);
map=sparse(phi(E(2:end,:)-I)-phi(E(1:end-1,:)-I));
map=map.*(map>8e-15); % squeeze out more small values
map(:,2:end-1)=map(:,2:end-1)/2; % make up for top and bottom bins

%                                     ____
% this is piecewise linear ramp : ___/
% It models the response of an FFT bin to a band edge as the edge 
% moves across the frequency range. The response of a bin to a
% band is computed as the sum of responses due to the left and
% right edges, ie, for the ith FT bin, 
%    response=phi(e1-i)-phi(e2-i)
% where e1 and e2 are the lower and upper edges of the band
function y=phi(x), y=abs(x+0.5)-abs(x-0.5);

