function [edges,map]=as_cqmap(parms,range,res)
% as_cqmap - Audio Spectrum linear to log frequency map
% 
% Converts a constant-Q filterbank specification into a sparse matrix
% which can be multiplied by a STFT power spectrogram to get a 
% constant-Q spectrogram. Note that though the logarithmic frequency 
% sampling grid has an adjustable spacing (the resolution parameter),
% its origin is FIXED at 1kHz. 
%
% as_cqmap ::
%    struct {
%       fs:real          ~ 'sampling rate',
%       FFTsize:natural  ~ 'FFT frame size to be used to get STFT'
%    }        ~'framing parameter structure (see h_fparms)',
%    [[2]]    ~ 'requested lower and upper cut-off frequencies',
%    real|nan ~ 'resolution in octaves, or return one band if nan'
% ->
%    [[L-1]]  ~ 'frequency bin edges, excluding 0 and fs/2',
%    [[L,M]]  ~ 'L by M sparse array'.

% If resolution is nan, we just use the two edges unmodified
% as per MPEG-7 spec (except we're using nan instead of the 
% magic '8'). Obviously, we can't even quantise the band edges 
% without a valid resolution.
if isnan(res),
	edges=min(range/parms.fs,0.5);
else
	F0=1000; % MAGIC number - origin of frequnecy grid is 1kHz
	edges=as_cqedges(parms.fs,range,res,F0);

	% remove edges from bottom end until each band can be resolved
	e = 0.5+edges*parms.FFTsize;   % band edges relative to FT bin edges
	k = find(diff(e)<1);           % find bands narrower than one bin
	k = k(ceil(e(k))==1+floor(e(k+1))); % filter out bands spanning >1 bin
	% if any bands remaining, then remove these from main edges list
	if ~isempty(k), edges=edges(1+max(k):end); end
end

% build sparse matrix of standard size if requested
if nargout>1,
	map = specbasis(parms.FFTsize*edges,dftbins(parms.FFTsize));
end
