private void ProcessFullSpectrum(
        SpectralFluxAnalyzer analyzer,
        ThreadSafeAudioClip clip,
        OnAudioClipProcessed callback)
    {
        var processedSamples = GetChannelsCombined(clip.Samples, clip.ChannelCount, clip.SampleCount);

        Debug.Log("Channels have been combined");

        var iterations = processedSamples.Length / _fftSampleSize;

        var fft = new FFT();

        fft.Initialize(_fftSampleSize);

        var chunk = new double[_fftSampleSize];

        for (var i = 0; i < iterations; ++i)
        {
            Array.Copy(processedSamples, i * _fftSampleSize, chunk, 0, _fftSampleSize);

            var windowCoefficients  = DSP.Window.Coefficients(DSP.Window.Type.Hamming, _fftSampleSize);
            var scaledSpectrumChunk = DSP.Math.Multiply(chunk, windowCoefficients);
            var scaleFactor         = DSP.Window.ScaleFactor.Signal(windowCoefficients);

            var fftSpectrum       = fft.Execute(scaledSpectrumChunk);
            var scaledFftSpectrum = DSP.ConvertComplex.ToMagnitude(fftSpectrum);
            scaledFftSpectrum = DSP.Math.Multiply(scaledFftSpectrum, scaleFactor);

            var currentSongTime = GetTimeFromIndex(i, clip.Frequency) * _fftSampleSize;
            analyzer.AnalyzeSpectrum(Array.ConvertAll(scaledFftSpectrum, x => (float)x), currentSongTime);
        }

        callback(analyzer);
    }
    public void ProcessClip(AudioClip clip, SpectralFluxAnalyzer spectralFluxAnalyzer, OnAudioClipProcessed callback)
    {
        _threadClip = new ThreadSafeAudioClip(clip);

        var t = new Thread(() =>
        {
            ProcessFullSpectrum(
                spectralFluxAnalyzer,
                _threadClip,
                callback);
        });

        t.Start();
    }