static void EnumerateBySamples(WaveReader originalReader, WaveReader compressedReader, long compressedSamplesToSkip, Action<float[], float[]> compareMethod)
        {
            originalReader.Seek(0);
            compressedReader.Seek(compressedSamplesToSkip);

            using (var compressedSamplesItr = compressedReader.ReadAllSamples_Float ().GetEnumerator ())
            {
                foreach (var originalSamples in originalReader.ReadAllSamples_Float ())
                {
                    if (compressedSamplesItr.MoveNext ())
                    {
                        var compressedSamples = compressedSamplesItr.Current;
                        compareMethod (originalSamples, compressedSamples);
                    }
                    else
                    {
                        Console.WriteLine ("Compressed file is shorter");
                        break;
                    }
                }
                if (compressedSamplesItr.MoveNext ())
                {
                    Console.WriteLine ("Compressed file is longer");
                }
            }
        }
        static void EnumerateByFrequencies(WaveReader originalReader, WaveReader compressedReader, int numChannels, int windowSize, float samplesPerCheck, Dictionary<int, Action<float[], float[]>> comparisonMethods, long compressedSamplesToSkip)
        {
            originalReader.Seek(0);
            compressedReader.Seek(compressedSamplesToSkip);

            var fft = new ComplexFourierTransformation();

            var originalQueue = new Queue<float[]> ();
            var compressedQueue = new Queue<float[]> ();

            using (var compressedSamplesItr = compressedReader.ReadAllSamples_Float ().GetEnumerator ())
            {
                foreach (var originalSamples in originalReader.ReadAllSamples_Float ())
                {
                    if (compressedSamplesItr.MoveNext ())
                    {
                        originalQueue.Enqueue (originalSamples);
                        compressedQueue.Enqueue (compressedSamplesItr.Current);

                        if (originalQueue.Count == windowSize)
                        {
                            for (var channelCtr = 0; channelCtr < numChannels; channelCtr++)
                            {
                                var originalSamplesToTransform = originalQueue.Select (s => new Complex (s [channelCtr], 0)).ToArray ();
                                var compressedSamplesToTransform = compressedQueue.Select (s => new Complex (s [channelCtr], 0)).ToArray ();

                                fft.TransformForward (originalSamplesToTransform);
                                fft.TransformForward (compressedSamplesToTransform);

                                foreach (var kvp in comparisonMethods)
                                {
                                    var fftIndex = kvp.Key;
                                    var comparisonMethod = kvp.Value;

                                    comparisonMethod(
                                        new float[] { Convert.ToSingle (originalSamplesToTransform [fftIndex].Modulus) },
                                        new float[] { Convert.ToSingle (compressedSamplesToTransform [fftIndex].Modulus) });
                                }
                            }

                            for (var ctr = 0; ctr < samplesPerCheck; ctr++)
                            {
                                originalQueue.Dequeue ();
                                compressedQueue.Dequeue ();
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine ("Compressed file is shorter");
                        break;
                    }
                }

                if (compressedSamplesItr.MoveNext ())
                {
                    Console.WriteLine ("Compressed file is longer");
                }
            }
        }
        static void EnumerateByFrequencyBands(
			WaveReader originalReader,
			WaveReader compressedReader,
			long compressedSamplesToSkip,
			Action<float[], float[]> highComparisonMethod,
			Action<float[], float[]> midComparisonMethod,
			Action<float[], float[]> lowComparisonMethod)
        {
            originalReader.Seek(0);
            compressedReader.Seek(compressedSamplesToSkip);

            var originalHighSamplesQueue = new Queue<float[]> ();
            var compressedHighSamplesQueue = new Queue<float[]> ();

            var originalMidSamples = SampleRateAdjustor.DownSample (originalReader.ReadAllSamples_Float (), originalReader.NumChannels, 16, originalHighSamplesQueue.Enqueue);
            var compressedMidSamples = SampleRateAdjustor.DownSample (compressedReader.ReadAllSamples_Float (), compressedReader.NumChannels, 16, compressedHighSamplesQueue.Enqueue);

            var originalMidSamplesQueue = new Queue<float[]> ();
            var compressedMidSamplesQueue = new Queue<float[]> ();

            var originalLowSamples = SampleRateAdjustor.DownSample (originalMidSamples, originalReader.NumChannels, 16, originalMidSamplesQueue.Enqueue);
            var compressedLowSamples = SampleRateAdjustor.DownSample (compressedMidSamples, compressedReader.NumChannels, 16, compressedMidSamplesQueue.Enqueue);

            using (var compressedSamplesItr = compressedLowSamples.GetEnumerator ())
            {
                foreach (var originalSamples in originalLowSamples)
                {
                    if (compressedSamplesItr.MoveNext ())
                    {
                        var compressedSamples = compressedSamplesItr.Current;
                        lowComparisonMethod (originalSamples.ToArray (), compressedSamples.ToArray ());

                        while (originalHighSamplesQueue.Count > 0 && compressedHighSamplesQueue.Count > 0)
                            highComparisonMethod (originalHighSamplesQueue.Dequeue (), compressedHighSamplesQueue.Dequeue ());

                        while (originalMidSamplesQueue.Count > 0 && compressedMidSamplesQueue.Count > 0)
                            midComparisonMethod (originalMidSamplesQueue.Dequeue (), compressedMidSamplesQueue.Dequeue ());
                    }
                    else
                    {
                        Console.WriteLine ("Compressed file is shorter");
                        break;
                    }
                }

                if (compressedSamplesItr.MoveNext ())
                {
                    Console.WriteLine ("Compressed file is longer");
                }
            }
        }
        static IEnumerable<IEnumerable<float>> UpSample(WaveReader reader, int windowSize)
        {
            var fft = new MathNet.Numerics.Transformations.ComplexFourierTransformation ();

            var determineVolumeSource = new Complex[]
            {
                new Complex(1, 0),
                new Complex(1, 0),
                new Complex(1, 0),
                new Complex(1, 0),
            };

            fft.TransformForward(determineVolumeSource);

            var determineVolumeDestination = new Complex[windowSize];
            determineVolumeDestination[0] = determineVolumeSource[0];
            for (var sampleCtr = 1; sampleCtr < windowSize; sampleCtr++)
                determineVolumeDestination[sampleCtr] = Complex.FromModulusArgument(0,0);

            fft.TransformBackward(determineVolumeDestination);

            var multiplier = determineVolumeDestination[0].Real;

            var sampleQueue = new Queue<float[]>();
            for (var sampleCtr = 0; sampleCtr < 2; sampleCtr++)
                sampleQueue.Enqueue(new float[reader.NumChannels]);

            foreach (var samples in reader.ReadAllSamples_Float().Select(s => s.ToArray()))
            {
                sampleQueue.Enqueue(samples);

                if (sampleQueue.Count == 4)
                {
                    var expanded = new float[windowSize / 2][];

                    for (var ctr = 0; ctr < windowSize / 2; ctr++)
                        expanded[ctr] = new float[reader.NumChannels];

                    for (var channelCtr = 0; channelCtr < reader.NumChannels; channelCtr++)
                    {
                        var samplesToTransform = sampleQueue.Select(s => new Complex (s[channelCtr], 0)).ToArray();

                        fft.TransformForward (samplesToTransform);

                        var samplesToTransformBack = new Complex[windowSize];
                        samplesToTransformBack[0] = samplesToTransform[0];
                        samplesToTransformBack[1] = samplesToTransform[1];
                        samplesToTransformBack[1].Modulus /= 2;
                        samplesToTransformBack[samplesToTransformBack.Length - 1] = samplesToTransform[1];
                        samplesToTransformBack[samplesToTransformBack.Length - 1].Modulus /= 2;
                        samplesToTransformBack[samplesToTransformBack.Length - 1].Argument *= -1;

                        for (var ctr = 2; ctr < samplesToTransformBack.Length - 1; ctr++)
                            samplesToTransformBack[ctr] = Complex.FromModulusArgument(0, 0);

                        fft.TransformBackward(samplesToTransformBack);

                        for (var ctr = 0; ctr < windowSize / 2; ctr++)
                            expanded[ctr][channelCtr] = Convert.ToSingle(samplesToTransformBack[ctr + windowSize / 4].Real / multiplier);
                    }

                    foreach (var simplified in expanded)
                        yield return simplified;

                    sampleQueue.Dequeue();
                    sampleQueue.Dequeue();
                }
            }
        }