Ejemplo n.º 1
0
        public static double FrequencyDistribution(byte[] x, byte[] y)
        {
            if (x.Length != y.Length)
            {
                throw new ArgumentException("interval lengths do not match");
            }

            int samples = x.Length / 4;

            float[] xF = new float[samples];
            float[] yF = new float[samples];

            Buffer.BlockCopy(x, 0, xF, 0, x.Length);
            Buffer.BlockCopy(y, 0, yF, 0, y.Length);

            int fftSize = 2048; // max FFT size

            // if there are less samples to analyze, find a fitting FFT size
            while (fftSize > samples)
            {
                fftSize /= 2;
            }
            int hopSize = fftSize / 8;

            if (fftSize < 64)
            {
                throw new Exception("FFT might be too small to get a meaningful result");
            }

            double[] xSum   = new double[fftSize / 2];
            double[] ySum   = new double[fftSize / 2];
            float[]  buffer = new float[fftSize];

            if (windowFunction == null || windowFunction.Size != fftSize)
            {
                windowFunction = WindowUtil.GetFunction(WindowType.Hann, fftSize);
            }

            var fft = FFTFactory.CreateInstance(fftSize);

            int blocks = (samples - fftSize) / hopSize;

            for (int block = 0; block < blocks; block++)
            {
                Array.Copy(xF, block * hopSize, buffer, 0, buffer.Length);
                FrequencyDistributionBlockProcess(buffer, xSum, fft);

                Array.Copy(yF, block * hopSize, buffer, 0, buffer.Length);
                FrequencyDistributionBlockProcess(buffer, ySum, fft);
            }

            fft.Dispose();

            // remove DC offset
            xSum[0] = 0;
            ySum[0] = 0;

            double xScalarSum = xSum.Sum();
            double yScalarSum = ySum.Sum();

            double result = 0;

            for (int i = 0; i < fftSize / 2; i++)
            {
                result += Math.Abs(xSum[i] / xScalarSum - ySum[i] / yScalarSum);
            }

            return(1 - result);
        }