function varargout = mirspectrum(orig,varargin)
% s = mirspectrum(x) computes the spectrum of the audio signal x, showing
% the distribution of the energy along the frequencies.
% (x can be the name of an audio file as well.)
% Optional argument:
% mirspectrum(...,'Frame',l,h) computes spectrogram, using frames of
% length l seconds and a hop rate h.
% Default values: l = .05 s, h = .5.
% mirspectrum(...,'Min',mi) indicates the lowest frequency taken into
% consideration, expressed in Hz.
% Default value: 0 Hz.
% mirspectrum(...,'Max',ma) indicates the highest frequency taken into
% consideration, expressed in Hz.
% Default value: the maximal possible frequency, corresponding to
% the sampling rate of x divided by 2.
% mirspectrum(...,'Window',w): windowing method:
% either w = 0 (no windowing) or any windowing function proposed
% in the Signal Processing Toolbox (help window).
% default value: w = 'hamming'
%
% mirspectrum(...,'Cents'): decomposes the energy in cents.
% mirspectrum(...,'Collapsed'): collapses the spectrum into one
% octave divided into 1200 cents.
% Redistribution of the frequencies into bands:
% mirspectrum(...,'Mel'): Mel bands.
% (Requires the Auditory Toolbox.)
% If the audio signal was frame decomposed, the output s is a
% band-decomposed spectrogram. It is then possible to compute
% the spectrum of the temporal signal in each band,
% using the following syntax:
% mirspectrum(s,'AlongBands')
% This corresponds to fluctuation (cf. mirfluctuation).
% mirspectrum(...,'Normal'): normalizes with respect to energy.
% mirspectrum(...,'NormalLength'): normalizes with respect to input length.
% mirspectrum(...,'NormalInput'): input signal is normalized from 0 to 1.
% mirspectrum(...,'Power'): squares the energy.
% mirspectrum(...,'dB'): represents the spectrum energy in decibel scale.
% mirspectrum(...,'dB',th): keeps only the highest energy over a
% range of th dB.
% mirspectrum(...,'Resonance',r): multiplies the spectrum with a
% resonance curve. Possible value for r:
% 'ToiviainenSnyder': highlights best perceived meter
% (Toiviainen & Snyder 2003)
% (default value for spectrum of envelopes)
% 'Fluctuation': fluctuation strength (Fastl 1982)
% (default value for spectrum of band channels)
% mirspectrum(...,'Prod',m): Enhances components that have harmonics
% located at multiples of range(s) m of the signal's fundamental
% frequency. Computed by compressing the signal by the list of
% factors m, and by multiplying all the results with the original
% signa (Alonso et al, 2003).
% mirspectrum(...,'Sum',s): Similar option using summation instead of
% product.
%
% mirspectrum(...,'MinRes',mr): Indicates a minimal accepted
% frequency resolution, in Hz. The audio signal is zero-padded in
% order to reach the desired resolution.
% If the 'Mel' option is toggled on, 'MinRes' is set by default
% to 66 Hz.
% mirspectrum(...,'MinRes',mr,'OctaveRatio',tol): Indicates the
% minimal accepted resolution in terms of number of divisions of
% the octave. Low frequencies are ignored in order to reach the
% desired resolution.
% The corresponding required frequency resolution is equal to
% the difference between the first frequency bins, multiplied
% by the constraining multiplicative factor tol (set by
% default to .75).
% mirspectrum(...,'Res',r): Indicates the required precise frequency
% resolution, in Hz. The audio signal is zero-padded in order to
% reach the desired resolution.
% mirspectrum(...,'Length',l): Specifies the length of the FFT,
% overriding the FFT length initially planned.
% mirspectrum(...,'ZeroPad',s): Zero-padding of s samples.
% mirspectrum(...,'WarningRes',s): Indicates a required frequency
% resolution, in Hz, for the input signal. If the resolution does
% not reach that prerequisite, a warning is displayed.
% mirspectrum(...,'ConstantQ',nb): Carries out a Constant Q Transform
% instead of a FFT, with a number of bins per octave fixed to nb.
% Default value for nb: 12 bins per octave.
%
% mirspectrum(...,'Smooth',o): smooths the envelope using a movering
% average of order o.
% Default value when the option is toggled on: o=10
% mirspectrum(...,'Gauss',o): smooths the envelope using a gaussian
% of standard deviation o samples.
% Default value when the option is toggled on: o=10
% mirspectrum(...,'Phase',0): do not compute the FFT phase.
win.key = 'Window';
win.type = 'String';
win.default = 'hamming';
option.win = win;
min.key = 'Min';
min.type = 'Integer';
min.default = 0;
option.min = min;
max.key = 'Max';
max.type = 'Integer';
max.default = Inf;
option.max = max;
mr.key = 'MinRes';
mr.type = 'Integer';
mr.default = 0;
option.mr = mr;
res.key = 'Res';
res.type = 'Integer';
res.default = NaN;
option.res = res;
length.key = 'Length';
length.type = 'Integer';
length.default = NaN;
option.length = length;
zp.key = 'ZeroPad';
zp.type = 'Integer';
zp.default = 0;
zp.keydefault = Inf;
option.zp = zp;
wr.key = 'WarningRes';
wr.type = 'Integer';
wr.default = 0;
option.wr = wr;
octave.key = 'OctaveRatio';
octave.type = 'Boolean';
octave.default = 0;
option.octave = octave;
constq.key = 'ConstantQ';
constq.type = 'Integer';
constq.default = 0;
constq.keydefault = 12;
option.constq = constq;
alongbands.key = 'AlongBands';
alongbands.type = 'Boolean';
alongbands.default = 0;
option.alongbands = alongbands;
ni.key = 'NormalInput';
ni.type = 'Boolean';
ni.default = 0;
option.ni = ni;
nl.key = 'NormalLength';
nl.type = 'Boolean';
nl.default = 0;
nl.when = 'After';
option.nl = nl;
norm.key = 'Normal';
norm.type = 'Integer';
norm.default = 0;
norm.keydefault = 1;
norm.when = 'After';
option.norm = norm;
band.type = 'String';
band.choice = {'Freq','Mel','Bark','Cents'};
band.default = 'Freq';
band.when = 'Both';
option.band = band;
nbbands.key = 'Bands';
nbbands.type = 'Integer';
nbbands.default = 0;
nbbands.when = 'After';
option.nbbands = nbbands;
mprod.key = 'Prod';
mprod.type = 'Integers';
mprod.default = [];
mprod.keydefault = 2:6;
mprod.when = 'After';
option.mprod = mprod;
msum.key = 'Sum';
msum.type = 'Integers';
msum.default = [];
msum.keydefault = 2:6;
msum.when = 'After';
option.msum = msum;
reso.key = 'Resonance';
reso.type = 'String';
reso.choice = {'ToiviainenSnyder','Fluctuation','Meter',0,'no','off'};
reso.default = 0;
reso.when = 'After';
option.reso = reso;
log.key = 'log';
log.type = 'Boolean';
log.default = 0;
log.when = 'After';
option.log = log;
db.key = 'dB';
db.type = 'Integer';
db.default = 0;
db.keydefault = Inf;
db.when = 'After';
option.db = db;
pow.key = 'Power';
pow.type = 'Boolean';
pow.default = 0;
pow.when = 'After';
option.pow = pow;
terhardt.key = 'Terhardt';
terhardt.type = 'Boolean';
terhardt.default = 0;
terhardt.when = 'After';
option.terhardt = terhardt;
mask.key = 'Mask';
mask.type = 'Boolean';
mask.default = 0;
mask.when = 'After';
option.mask = mask;
% e.key = 'Enhanced';
% e.type = 'Integer';
% e.default = [];
% e.keydefault = 2:10;
% e.when = 'After';
%option.e = e;
collapsed.key = 'Collapsed';
collapsed.type = 'Boolean';
collapsed.default = 0;
collapsed.when = 'Both';
option.collapsed = collapsed;
aver.key = 'Smooth';
aver.type = 'Integer';
aver.default = 0;
aver.keydefault = 10;
aver.when = 'After';
option.aver = aver;
gauss.key = 'Gauss';
gauss.type = 'Integer';
gauss.default = 0;
gauss.keydefault = 10;
gauss.when = 'After';
option.gauss = gauss;
rapid.key = 'Rapid';
rapid.type = 'Boolean';
rapid.default = 0;
option.rapid = rapid;
phase.key = 'Phase';
phase.type = 'Boolean';
phase.default = 1;
option.phase = phase;
specif.option = option;
specif.defaultframelength = 0.05;
specif.defaultframehop = 0.5;
specif.eachchunk = @eachchunk;
specif.combinechunk = @combinechunk;
if isamir(orig,'mirscalar') || isamir(orig,'mirenvelope')
specif.nochunk = 1;
end
varargout = mirfunction(@mirspectrum,orig,varargin,nargout,specif,@init,@main);
function [x type] = init(x,option)
type = 'mirspectrum';
function s = main(orig,option,postoption)
if isstruct(option)
if option.collapsed
option.band = 'Cents';
end
if isnan(option.res) && strcmpi(option.band,'Cents') && option.min
option.res = option.min *(2^(1/1200)-1)*.9;
end
end
if not(isempty(postoption))
if not(strcmpi(postoption.band,'Freq') && isempty(postoption.msum) ...
|| isempty(postoption.mprod)) || postoption.log || postoption.db ...
|| postoption.pow || postoption.mask || postoption.collapsed ...
|| postoption.aver || postoption.gauss
option.phase = 0;
end
end
if iscell(orig)
orig = orig{1};
end
if isa(orig,'mirspectrum') && ...
not(isfield(option,'alongbands') && option.alongbands)
s = orig;
if isfield(option,'min') && ...
(option.min || iscell(option.max) || option.max < Inf)
magn = get(s,'Magnitude');
freq = get(s,'Frequency');
for k = 1:length(magn)
m = magn{k};
f = freq{k};
if iscell(option.max)
mi = option.min{k};
ma = option.max{k};
else
mi = option.min;
ma = option.max;
end
if not(iscell(m))
m = {m};
f = {f};
end
for l = 1:length(m)
range = find(and(f{l}(:,1) >= mi,f{l}(:,1) <= ma));
m{l} = m{l}(range,:,:);
f{l} = f{l}(range,:,:);
end
magn{k} = m;
freq{k} = f;
end
s = set(s,'Magnitude',magn,'Frequency',freq);
end
if not(isempty(postoption)) && not(isequal(postoption,0))
s = post(s,postoption);
end
elseif ischar(orig)
s = mirspectrum(miraudio(orig),option,postoption);
else
if nargin == 0
orig = [];
end
s.phase = [];
s.log = 0;
s.xscale = 'Freq';
s.pow = 1;
s = class(s,'mirspectrum',mirdata(orig));
s = purgedata(s);
s = set(s,'Title','Spectrum','Abs','frequency (Hz)','Ord','magnitude');
%disp('Computing spectrum...')
sig = get(orig,'Data');
t = get(orig,'Pos');
if isempty(t)
t = get(orig,'FramePos');
for k = 1:length(sig)
for l = 1:length(sig{k})
sig{k}{l} = sig{k}{l}';
t{k}{l} = t{k}{l}(1,:,:)';
end
end
end
fs = get(orig,'Sampling');
fp = get(orig,'FramePos');
m = cell(1,length(sig));
p = cell(1,length(sig));
f = cell(1,length(sig));
for i = 1:length(sig)
d = sig{i};
fpi = fp{i};
if not(iscell(d))
d = {d};
end
if option.alongbands
fsi = 1 / (fpi{1}(1,2) - fpi{1}(1,1));
else
fsi = fs{i};
end
mi = cell(1,length(d));
phi = cell(1,length(d));
fi = cell(1,length(d));
for J = 1:length(d)
dj = d{J};
if option.ni
mxdj = repmat(max(dj),[size(dj,1),1,1]);
mndj = repmat(min(dj),[size(dj,1),1,1]);
dj = (dj-mndj)./(mxdj-mndj);
end
if option.alongbands
if size(dj,1)>1
error('ERROR IN MIRSPECTRUM: ''AlongBands'' is restricted to spectrum decomposed into bands, such as ''Mel'' and ''Bark''.')
end
dj = reshape(dj,[size(dj,2),1,size(dj,3)]);
fp{i}{J} = fp{i}{J}([1;end]);
end
if option.constq
% Constant Q Transform
r = 2^(1/option.constq);
Q = 1 / (r - 1);
f_max = min(fsi/2,option.max);
f_min = option.min;
if not(f_min)
f_min = 16.3516;
end
B = floor(log(f_max/f_min) / log(r)); % number of bins
N0 = round(Q*fsi/f_min); % maximum Nkcq
j2piQn = -j*2*pi*Q*(0:N0-1)';
fj = f_min * r.^(0:B-1)';
transf = NaN(B,size(dj,2),size(dj,3));
for kcq = 1:B
Nkcq = round(Q*fsi/fj(kcq));
win = mirwindow(dj,option.win,Nkcq);
exq = repmat(exp(j2piQn(1:Nkcq)/Nkcq),...
[1,size(win,2),size(win,3)]);
transf(kcq,:) = sum(win.* exq) / Nkcq;
end
else
% FFT
dj = mirwindow(dj,option.win);
if option.zp
if option.zp < Inf
dj = [dj;zeros(option.zp,size(dj,2),size(dj,3))];
else
dj = [dj;zeros(size(dj))];
end
end
if isstruct(postoption)
if strcmpi(postoption.band,'Mel') && ...
(not(option.mr) || option.mr > 66)
option.mr = 66;
end
else
%warning('WARNING in MIRSPECTRUM (for debugging purposes): By default, minimum resolution specified.')
if not(option.mr)
option.mr = 66;
end
end
if option.octave
N = size(dj,1);
res = (2.^(1/option.mr)-1)*option.octave;
% Minimal freq ratio between 2 first bins.
% freq resolution should be > option.min * res
Nrec = fsi/(option.min*res);
% Recommended minimal sample length.
if Nrec > N
% If actual sample length is too small.
option.min = fsi/N / res;
warning('WARNING IN MIRSPECTRUM: The input signal is too short to obtain the desired octave resolution. Lowest frequencies will be ignored.');
display(['(The recommended minimal input signal length would be ' num2str(Nrec/fsi) ' s.)']);
display(['New low frequency range: ' num2str(option.min) ' Hz.']);
end
N = 2^nextpow2(N);
elseif isnan(option.length)
if isnan(option.res)
N = size(dj,1);
if option.mr && N < fsi/option.mr
if option.wr && N < fsi/option.wr
warning('WARNING IN MIRSPECTRUM: The input signal is too short to obtain the desired frequency resolution. Performed zero-padding will not guarantee the quality of the results.');
end
N = max(N,fsi/option.mr);
end
N = 2^nextpow2(N);
else
N = ceil(fsi/option.res);
end
else
N = option.length;
end
% Here is the spectrum computation itself
transf = fft(dj,N);
len = floor(N/2+1);
fj = fsi/2 * linspace(0,1,len)';
if option.max
maxf = find(fj>=option.max,1);
if isempty(maxf)
maxf = len;
end
else
maxf = len;
end
if option.min
minf = find(fj>=option.min,1);
if isempty(minf)
maxf = len;
end
else
minf = 1;
end
transf = transf(minf:maxf,:,:);
fj = fj(minf:maxf);
end
mi{J} = abs(transf);
if option.phase
phi{J} = angle(transf);
end
fi{J} = repmat(fj,[1,size(transf,2),size(transf,3)]);
end
if iscell(sig{i})
m{i} = mi;
p{i} = phi;
f{i} = fi;
else
m{i} = mi{1};
p{i} = phi{1};
f{i} = fi{1};
end
end
s = set(s,'Frequency',f,'Magnitude',m,'Phase',p,'FramePos',fp);
if not(isempty(postoption)) && isstruct(postoption)
s = post(s,postoption);
end
end
function s = post(s,option)
if option.collapsed
option.band = 'Cents';
end
m = get(s,'Magnitude');
f = get(s,'Frequency');
for k = 1:length(m)
if not(iscell(m{k}))
m{k} = {m{k}};
f{k} = {f{k}};
end
end
if get(s,'Power') == 1 && ...
(option.pow || any(option.mprod) || any(option.msum))
for h = 1:length(m)
for l = 1:length(m{k})
m{h}{l} = m{h}{l}.^2;
end
end
s = set(s,'Power',2,'Title',['Power ',get(s,'Title')],'Phase',[]);
end
if any(option.mprod)
for h = 1:length(m)
for l = 1:length(m{k})
z0 = m{h}{l};
z1 = z0;
for k = 1:length(option.mprod)
mpr = option.mprod(k);
if mpr
zi = ones(size(z0));
zi(1:floor(end/mpr),:,:) = z0(mpr:mpr:end,:,:);
z1 = z1.*zi;
end
end
m{h}{l} = z1;
end
end
s = set(s,'Title','Spectral product');
end
if any(option.msum)
for h = 1:length(m)
for l = 1:length(m{k})
z0 = m{h}{l};
z1 = z0;
for k = 1:length(option.msum)
mpr = option.msum(k);
if mpr
zi = ones(size(z0));
zi(1:floor(end/mpr),:,:) = z0(mpr:mpr:end,:,:);
z1 = z1+zi;
end
end
m{h}{l} = z1;
end
end
s = set(s,'Title','Spectral sum');
end
if option.norm
for k = 1:length(m)
for l = 1:length(m{k})
mkl = m{k}{l};
nkl = zeros(1,size(mkl,2),size(mkl,3));
for kk = 1:size(mkl,2)
for ll = 1:size(mkl,3)
nkl(1,kk,l) = norm(mkl(:,kk,ll));
end
end
m{k}{l} = mkl./repmat(nkl,[size(m{k}{k},1),1,1]);
end
end
end
if option.nl
lg = get(s,'Length');
for k = 1:length(m)
for l = 1:length(m{k})
m{k}{l} = m{k}{l}/lg{k}{l};
end
end
end
if option.terhardt && not(isempty(find(f{1}{1}))) % This excludes the case where spectrum already along bands
warning('WARNING IN MIRSPECTRUM: ''Terhardt'' option is available in MIRtoolbox Complete version only.')
disp('MIRtoolbox Complete version is available from the official MIRtoolbox website.')
disp('''Terhardt'' option ignored.')
end
if option.reso
if not(ischar(option.reso))
if strcmp(get(orig,'XScale'),'Mel')
option.reso = 'Fluctuation';
else
option.reso = 'ToiviainenSnyder';
end
end
for k = 1:length(m)
for l = 1:length(m{k})
if strcmpi(option.reso,'ToiviainenSnyder') || strcmpi(option.reso,'Meter')
w = max(0,...
1 - 0.25*(log2(max(1./max(f{k}{l},1e-12),1e-12)/0.5)).^2);
elseif strcmpi(option.reso,'Fluctuation')
w1 = f{k}{l} / 4; % ascending part of the fluctuation curve;
w2 = 1 - 0.3 * (f{k}{l} - 4)/6; % descending part;
w = min(w1,w2);
end
if max(w) == 0
warning('The resonance curve, not defined for this range of delays, will not be applied.')
else
m{k}{l} = m{k}{l}.* w;
end
end
end
end
if strcmp(s.xscale,'Freq')
if strcmpi(option.band,'Bark') || strcmpi(option.band, 'Mel')
%web('http://www.jyu.fi/hum/laitokset/musiikki/en/research/coe/materials/mirtoolbox')
error('SORRY! For legal reasons, ''Mel'' and ''Bark'' options are not included in MIRtoolbox Matlab Central Version. MIRtoolbox Complete version is freely available from the official MIRtoolbox website.')
elseif strcmpi(option.band,'Cents') || option.collapsed
for h = 1:length(m)
for i = 1:length(m{h})
mi = m{h}{i};
fi = f{h}{i};
isgood = fi(:,1,1)*(2^(1/1200)-1) >= fi(2,1,1)-fi(1,1,1);
good = find(isgood);
if isempty(good)
mirerror('mirspectrum',...
'The frequency resolution of the spectrum is too low to be decomposed into cents.');
display('Hint: if you specify a minimum value for the frequency range (''Min'' option)');
display(' and if you do not specify any frequency resolution (''Res'' option), ');
display(' the correct frequency resolution will be automatically chosen.');
end
if good>1
warning(['MIRSPECTRUM: Frequency resolution in cent is achieved for frequencies over ',...
num2str(floor(fi(good(1)))),' Hz. Lower frequencies are ignored.'])
display('Hint: if you specify a minimum value for the frequency range (''Min'' option)');
display(' and if you do not specify any frequency resolution (''Res'' option), ');
display(' the correct frequency resolution will be automatically chosen.');
end
fi = fi(good,:,:);
mi = mi(good,:,:);
f2cents = 440*2.^(1/1200*(-1200*10:1200*10-1)');
% The frequencies corresponding to the cent range
cents = repmat((0:1199)',[20,size(fi,2),size(fi,3)]);
% The cent range is for the moment centered to A440
octaves = ones(1200,1)*(-10:10);
octaves = repmat(octaves(:),[1,size(fi,2),size(fi,3)]);
select = find(f2cents>fi(1) & f2cents<fi(end));
% Cent range actually used in the current spectrum
f2cents = repmat(f2cents(select),[1,size(fi,2),size(fi,3)]);
cents = repmat(cents(select),[1,size(fi,2),size(fi,3)]);
octaves = repmat(octaves(select),[1,size(fi,2),size(fi,3)]);
m{h}{i} = interp1(fi(:,1,1),mi,f2cents(:,1,1));
f{h}{i} = octaves*1200+cents + 6900;
% Now the cent range is expressed in midicent
end
end
s = set(s,'Abs','pitch (in midicents)','XScale','Cents','Phase',[]);
end
end
if option.mask
warning('WARNING IN MIRSPECTRUM: ''Mask'' option is available in MIRtoolbox Complete version only.')
disp('MIRtoolbox Complete version is available from the official MIRtoolbox website.')
disp('''Mask'' option ignored.')
end
if option.collapsed
for h = 1:length(m)
for i = 1:length(m{h})
mi = m{h}{i};
fi = f{h}{i};
centclass = rem(fi(:,1,1),1200);
%neg = find(centclass<0);
%centclass(neg) = 1200 + centclass(neg);
m{h}{i} = NaN(1200,size(mi,2),size(mi,3));
for k = 0:1199
m{h}{i}(k+1,:,:) = sum(mi(find(centclass==k),:,:),1);
end
f{h}{i} = repmat((0:1199)',[1,size(fi,2),size(fi,3)]);
end
end
s = set(s,'Abs','Cents','XScale','Cents(Collapsed)');
end
if option.log || option.db
if not(isa(s,'mirspectrum') && s.log)
for k = 1:length(m)
if not(iscell(m{k}))
m{k} = {m{k}};
f{k} = {f{k}};
end
for l = 1:length(m{k})
m{k}{l} = log10(m{k}{l}+1e-16);
if option.db
m{k}{l} = 10*m{k}{l};
if get(s,'Power') == 1
m{k}{l} = m{k}{l}*2;
end
end
end
end
elseif isa(s,'mirspectrum') && option.db && s.log<10
for k = 1:length(m)
for l = 1:length(m{k})
m{k}{l} = 10*m{k}{l};
if get(s,'Power') == 1
m{k}{l} = m{k}{l}*2;
end
end
end
end
if option.db
s = set(s,'log',10);
s = set(s,'Power',2);
else
s = set(s,'log',1);
end
if option.db>0 && option.db < Inf
for k = 1:length(m)
for l = 1:length(m{k})
m{k}{l} = m{k}{l}-repmat(max(m{k}{l}),[size(m{k}{l},1) 1 1]);
m{k}{l} = option.db + max(-option.db,m{k}{l});
end
end
end
s = set(s,'Phase',[]);
end
if option.aver
for k = 1:length(m)
for i = 1:length(m{k})
m{k}{i} = filter(ones(1,option.aver)/option.aver,1,m{k}{i});
end
end
s = set(s,'Phase',[]);
end
if option.gauss
for k = 1:length(m)
for i = 1:length(m{k})
sigma = option.gauss;
gauss = 1/sigma/2/pi...
*exp(- (-4*sigma:4*sigma).^2 /2/sigma^2);
y = filter(gauss,1,[m{k}{i};zeros(4*sigma,1)]);
y = y(4*sigma:end,:,:);
m{k}{i} = y(1:size(m{k}{i},1),:,:);
end
end
s = set(s,'Phase',[]);
end
s = set(s,'Magnitude',m,'Frequency',f);
function dj = mirwindow(dj,win,N)
if nargin<3
N = size(dj,1);
elseif size(dj,1)<N
dj(N,1,1) = 0;
end
if not(win == 0)
winf = str2func(win);
try
w = window(winf,N);
catch
if strcmpi(win,'hamming')
disp('Signal Processing Toolbox does not seem to be installed. Recompute the hamming window manually.');
w = 0.54 - 0.46 * cos(2*pi*(0:N-1)'/(N-1));
else
error(['ERROR in MIRSPECTRUM: Unknown windowing function ',win,' (maybe Signal Processing Toolbox is not installed).']);
end
end
kw = repmat(w,[1,size(dj,2),size(dj,3)]);
dj = dj(1:N,:,:).* kw;
end
function [y orig] = eachchunk(orig,option,missing,postchunk)
option.zp = option.zp+missing;
y = mirspectrum(orig,option);
function y = combinechunk(old,new)
do = get(old,'Data');
do = do{1}{1};
dn = get(new,'Data');
dn = dn{1}{1};
y = set(old,'ChunkData',do+dn);