/// <summary> /// FFT cache constructor. /// </summary> public FFTCache(int size) { if (CavernAmp.Available) { Native = CavernAmp.FFTCache_Create(size); return; } int halfSize = size / 2; double step = -2 * Math.PI / size; cos = new float[halfSize]; sin = new float[halfSize]; for (int i = 0; i < halfSize; ++i) { double rotation = i * step; cos[i] = (float)Math.Cos(rotation); sin[i] = (float)Math.Sin(rotation); } for (int depth = 0, maxDepth = QMath.Log2(size); depth < maxDepth; ++depth) { if (Even[depth] == null) { Even[depth] = new Complex[1 << depth]; Odd[depth] = new Complex[1 << depth]; } } }
public static void InPlaceFFT(this Complex[] samples, FFTCache cache) { if (CavernAmp.Available) { CavernAmp.InPlaceFFT(samples, cache); } else { ProcessFFT(samples, cache, QMath.Log2(samples.Length) - 1); } }
/// <summary> /// Inverse Fast Fourier Transform of a transformed signal, while keeping the source array allocation. /// </summary> public static void InPlaceIFFT(this Complex[] samples, FFTCache cache) { if (CavernAmp.Available) { CavernAmp.InPlaceIFFT(samples, cache); return; } ProcessIFFT(samples, cache, QMath.Log2(samples.Length) - 1); float multiplier = 1f / samples.Length; for (int i = 0; i < samples.Length; ++i) { samples[i].Real *= multiplier; samples[i].Imaginary *= multiplier; } }
/// <summary> /// Apply a delay on the <paramref name="signal"/> even with fraction <paramref name="samples"/>. /// </summary> public static void Delay(float[] signal, float samples) { using FFTCache cache = new FFTCache(QMath.Base2Ceil(signal.Length)); Delay(signal, samples); }