/// <summary> /// Free all used resources if there is any. /// </summary> public void Dispose() { if (Native.ToInt64() != 0) { CavernAmp.FFTCache_Dispose(Native); } }
/// <summary> /// Minimizes the phase of a spectrum. /// </summary> /// <remarks>This function does not handle zeros in the spectrum. /// Make sure there is a threshold before using this function.</remarks> public static void MinimumPhaseSpectrum(Complex[] response, FFTCache cache = null) { bool customCache = false; if (cache == null) { cache = new FFTCache(response.Length); customCache = true; } int halfLength = response.Length / 2; for (int i = 0; i < response.Length; ++i) { response[i] = Complex.Log(response[i].Real); } if (CavernAmp.Available) { CavernAmp.InPlaceIFFT(response, cache); } else { response.InPlaceIFFT(cache); } for (int i = 1; i < halfLength; ++i) { response[i].Real += response[^ i].Real;
/// <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]; } } }
/// <summary> /// Inverse Fast Fourier Transform of a transformed signal, while keeping the source array allocation. /// </summary> public static void InPlaceIFFT(this Complex[] samples) { if (CavernAmp.Available) { CavernAmp.InPlaceIFFT(samples); return; } using FFTCache cache = new FFTCache(samples.Length); samples.InPlaceIFFT(cache); }
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); } }
public static void InPlaceFFT(this float[] samples, FFTCache cache) { if (CavernAmp.Available) { CavernAmp.InPlaceFFT(samples, cache); } else { ProcessFFT(samples, cache); } }
public static void InPlaceFFT(this float[] samples) { if (CavernAmp.Available) { CavernAmp.InPlaceFFT(samples); } else { using FFTCache cache = new FFTCache(samples.Length); ProcessFFT(samples, cache); } }
/// <summary> /// Inverse Fast Fourier Transform of a transformed signal. /// </summary> public static Complex[] IFFT(this Complex[] samples, FFTCache cache) { samples = samples.FastClone(); if (CavernAmp.Available) { CavernAmp.InPlaceIFFT(samples, cache); } else { samples.InPlaceIFFT(cache); } return(samples); }
/// <summary> /// Inverse Fast Fourier Transform of a transformed signal. /// </summary> public static Complex[] IFFT(this Complex[] samples) { if (CavernAmp.Available) { samples = samples.FastClone(); CavernAmp.InPlaceIFFT(samples); } else { using FFTCache cache = new FFTCache(samples.Length); samples.InPlaceIFFT(cache); } return(samples); }
/// <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; } }