Beispiel #1
0
        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");
                }
            }
        }
        /// <summary>
        /// judge the FFT result for log data.
        /// </summary>
        /// <param name="resDic">log data.</param>
        /// <param name="rate">FFT rate.</param>
        /// <returns>if all judgement is ok, return true.</returns>
        private bool JudgeBifurcationAnalysisByFFT(Dictionary<double, double> resDic, double rate)
        {
            double maxFreq = m_param.MaxFreq;
            double minFreq = m_param.MinFreq;
            int maxSize = m_param.MaxInput;

            ComplexFourierTransformation cft = new ComplexFourierTransformation();
            int size = 4;
            int divide = 1;
            while (true)
            {
                if (resDic.Count <= size) break;
                if (size >= maxSize)
                {
                    divide = resDic.Count / maxSize + 1;
                    break;
                }
                size = size * 2;
            }
            double[] data = new double[size * 2];
            int i = 0;
            foreach (double d in resDic.Keys)
            {
                if (i % divide != 0) continue;
                data[i * 2] = resDic[d];
                data[i * 2 + 1] = 0.0;
                i++;
            }

            cft.Convention = TransformationConvention.Matlab; // so we can check MATLAB consistency
            cft.TransformForward(data);

            int count = 0;
            for (int j = 0; j < size; j++)
            {
                double d = Math.Sqrt(data[j * 2] * data[j * 2] + data[j * 2 + 1] * data[j * 2 + 1]);
                if (maxFreq > d && minFreq < d) count++;
            }
            if ((double)count / (double)size > rate)
                return true;

            return false;
        }
        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();
                }
            }
        }
 public void SetUp()
 {
     cft = new ComplexFourierTransformation();
     rft = new RealFourierTransformation();
 }
        public static IEnumerable<float[]> DownSample(IEnumerable<float[]> samplesEnumerator, int numChannels, int windowSize, Action<float[]> highSampleCallback)
        {
            var fft = new MathNet.Numerics.Transformations.ComplexFourierTransformation ();

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

            fft.TransformForward(determineVolumeSource);

            var determineVolumeDestination = new Complex[]
            {
                determineVolumeSource[0],
                Complex.FromModulusArgument(0,0),
                Complex.FromModulusArgument(0,0),
                Complex.FromModulusArgument(0,0)
            };

            fft.TransformBackward(determineVolumeDestination);

            var dcMultiplier = determineVolumeDestination[0].Modulus;

            var ratio = (1d / Convert.ToDouble(windowSize)) * 2d * Math.PI;
            for (var sampleCtr = 0; sampleCtr < windowSize; sampleCtr++)
            {
                var sampleCtrDouble = Convert.ToDouble(sampleCtr);
                determineVolumeSource[sampleCtr] = new Complex(Math.Cos(sampleCtrDouble * ratio), 0);
            }

            fft.TransformForward(determineVolumeSource);

            determineVolumeDestination = new Complex[]
            {
                Complex.FromModulusArgument(0,0),
                determineVolumeSource[1],
                Complex.FromModulusArgument(0,0),
                determineVolumeSource[determineVolumeSource.Length - 1],
            };

            fft.TransformBackward(determineVolumeDestination);

            var midMultiplier = determineVolumeDestination.Select(s => s.Modulus).Max();

            /*// This only works when windowsize is 8
            for (var sampleCtr = 0; sampleCtr < windowSize; sampleCtr++)
            {
                var abs = sampleCtr % 2 == 1 ? 1 : 0;
                var sign = sampleCtr % 4 > 1 ? 1 : -1;
                determineVolumeSource[sampleCtr] = new Complex(abs * sign, 0);
            }*/

            ratio = (1d / Convert.ToDouble(windowSize)) * 4d * Math.PI;
            for (var sampleCtr = 0; sampleCtr < windowSize; sampleCtr++)
            {
                var sampleCtrDouble = Convert.ToDouble(sampleCtr);
                determineVolumeSource[sampleCtr] = new Complex(Math.Cos(sampleCtrDouble * ratio), 0);
            }

            fft.TransformForward(determineVolumeSource);

            determineVolumeDestination = new Complex[]
            {
                Complex.FromModulusArgument(0,0),
                Complex.FromModulusArgument(0,0),
                determineVolumeSource[2],
                Complex.FromModulusArgument(0,0),
            };

            fft.TransformBackward(determineVolumeDestination);

            var highMultiplier = determineVolumeDestination.Select(s => s.Modulus).Max();

            var sampleQueue = new Queue<float[]>();
            for (var sampleCtr = 0; sampleCtr < windowSize / 4; sampleCtr++)
                sampleQueue.Enqueue(new float[numChannels]);

            var maxOriginalSample = 0.0;
            var maxLowFrequencySample = 0.0;

            using (var sampleEnumerator = samplesEnumerator.GetEnumerator())
            {
                int samplesFromSource;

                do
                {
                    samplesFromSource = 0;

                    while (sampleQueue.Count < windowSize)
                    {
                        if (sampleEnumerator.MoveNext())
                        {
                            sampleQueue.Enqueue(sampleEnumerator.Current.ToArray());
                            samplesFromSource++;
                        }
                        else
                            sampleQueue.Enqueue(new float[numChannels]);
                    }

                    var simplified = new float[][]
                    {
                        new float[numChannels],
                        new float[numChannels]
                    };

                    var filtered = new float[windowSize / 2][];
                    for (var sampleCtr = 0; sampleCtr < windowSize / 2; sampleCtr++)
                        filtered[sampleCtr] = new float[numChannels];

                    for (var channelCtr = 0; channelCtr < numChannels; channelCtr++)
                    {
                        maxOriginalSample = Math.Max(
                            maxOriginalSample,
                            sampleQueue.Select(s => Math.Abs(s[channelCtr])).Max());

                        var samplesToTransform = sampleQueue.Select (s => new Complex (s [channelCtr], 0)).ToArray ();

                        fft.TransformForward (samplesToTransform);

                        var samplesToTransformBack = new Complex[]
                        {
                            samplesToTransform[0],
                            samplesToTransform[1],
                            samplesToTransform[2],
                            samplesToTransform[samplesToTransform.Length - 1]
                        };

                        samplesToTransformBack[0].Modulus /= dcMultiplier;
                        samplesToTransformBack[1].Modulus /= midMultiplier;
                        samplesToTransformBack[2].Modulus /= highMultiplier;
                        samplesToTransformBack[3].Modulus /= midMultiplier;

                        fft.TransformBackward(samplesToTransformBack);

                        simplified[0][channelCtr] = Convert.ToSingle(samplesToTransformBack[1].Real);
                        simplified[1][channelCtr] = Convert.ToSingle(samplesToTransformBack[2].Real);

                        for (var filterCtr = 3; filterCtr < (samplesToTransform.Length - 1); filterCtr++)
                            samplesToTransform[filterCtr] = Complex.FromModulusArgument(0, 0);

                        fft.TransformBackward(samplesToTransform);
                        for (var sampleCtr = 0; sampleCtr < windowSize / 2; sampleCtr++)
                            filtered[sampleCtr][channelCtr] = Convert.ToSingle(samplesToTransform[sampleCtr + (windowSize / 4)].Real);
                    }

                    maxLowFrequencySample = Math.Max(
                        maxLowFrequencySample,
                        simplified.SelectMany(s => s).Select(Math.Abs).Max());

                    foreach (var samples in simplified)
                        yield return samples;

                    foreach (var samples in filtered)
                        highSampleCallback(samples);

                    while (sampleQueue.Count > windowSize / 2)
                        sampleQueue.Dequeue();

                } while (samplesFromSource > (windowSize / 4));
            }

            /*Console.WriteLine("Loudest sample in source: {0}", maxOriginalSample);
            Console.WriteLine("Loudest sample in low frequency: {0}", maxLowFrequencySample);
            //Console.WriteLine("Loudest sample in high frequency: {0}", maxHighFrequencySample);
            Console.WriteLine();*/
        }