I've got this transform method with a triple-nested loop. The Generate
methods do their own caching so they are fast. K
will have a worst-case value of 150. N
will have a worst-case value of about 20000. It's that 200002 that's killing me. It looks to me like the innermost loop could be moved out, but would you store every possible sum?
public static void Transform(IList<float> x, int offset, int sampleRate, int binsPerOctave,
double minFrequency, double maxFrequency, out double[] magnitudes, out double maxMagnitude)
{
var Q = 1.0 / (Math.Pow(2.0, 1.0 / binsPerOctave) - 1.0);
var K = (int)Math.Ceiling(Math.Log(maxFrequency / minFrequency, 2.0) * binsPerOctave);
magnitudes = new double[K];
var maxN = (int)Math.Round(Q * sampleRate / minFrequency);
var halfN = -maxN / 2;
double[] wcs = GenerateWindowConstants(maxN);
maxMagnitude = double.NegativeInfinity;
for(int k = 0; k < K; k++)
{
var N = (int)Math.Round(Q * sampleRate / (minFrequency * Math.Pow(2.0, (double)k / binsPerOctave)));
Complex[] piqs = GeneratePiQConstants(N, Q);
var maxMag = double.NegativeInfinity;
for(int i = 0; i < N; i++)
{
Complex sum = new Complex();
for(int n = 0; n < maxN; n++)
{
var index = n + offset + halfN;
index = Math.Min(x.Count - 1, index);
index = Math.Max(0, index);
sum += (wcs[n] * x[index]) * piqs[(n + i) % N];
}
sum /= maxN;
maxMag = Math.Max(maxMag, sum.Magnitude);
}
magnitudes[k] = maxMag;
maxMagnitude = Math.Max(maxMagnitude, maxMag);
}
}