I'd like to switch from MATLAB to Mathematica for my research in digital signal processing. I used Mathematica a lot during the '90s but I haven't used it since then, so I might as well be a complete newbie. As a first experiment I tried to port the following MATLAB function (a slow implementation of CQT):
function cq= slowQ(x, minFreq, maxFreq, bins, fs) % x must be a row vector
Q = 1/(2^(1/bins)-1);
maxK = ceil(bins*log2(maxFreq/minFreq));
maxN = ceil(Q*fs/minFreq);
if size(x,2) < maxN
x(end+1:maxN) = 0;
end
for k=1:maxK
fk = minFreq * 2^((k-1)/bins);
N = ceil(Q*fs/fk);
cq(k) = x(1:N) * (hamming(N) .* exp( -2*pi*i*Q*(0:N-1)'/N)) / N;
end
end
This is the code I came up with, which not only looks horrible but is also horribly slow (several orders of magnitude slower than MATLAB):
slowCQT[x_, minFreq_, maxFreq_, bins_, fs_] :=
Module[{Q, maxK, maxN, k, fk, Ncq, cqt},
Q = 1/(2^(1/bins) - 1);
maxK = Ceiling[bins*Log2[maxFreq/minFreq]];
maxN = Ceiling[Q*fs/minFreq];
If[Length[x] < maxN,
x = Join[x, ConstantArray[0, maxN - Length[x]]]];
cqt = ConstantArray[0, maxK];
For[k = 1, k < maxK, k++,
fk = minFreq*2^((k - 1)/bins);
Ncq = Ceiling[Q*fs/fk];
cqt[[k]] =
N[x[[1 ;; Ncq]].(N[HammingWindow[Range[-1/2, 1/2, 1/(Ncq - 1)]]] *
N[Exp[-2*Pi*I*Q*Range[0, Ncq - 1]/Ncq]])/Ncq];];
cqt]
Any suggestions or pointers to improve it?
EDIT: Example usage
MATLAB
fs = 44100;
T = (0:2*fs)/fs;
x=sin(2*pi*440*T);
tic; cqt = slowQ(x,27.5,880,24,fs); toc
Elapsed time is 0.305124 seconds.
Mathematica
fs = 44100;
T = N[Range[0, 2*fs]/fs];
x = N[Sin[2 Pi 440 * T]];
tic = AbsoluteTime[];
cqt = slowCQT[x, 27.5, 880, 24, fs];
AbsoluteTime[] - tic
89.755638