Complex number wrapper class.

The class encapsulates complex number and provides set of different operators to manipulate it, lake adding, subtractio, multiplication, etc.

Sample usage:

// define two complex numbers Complex c1 = new Complex( 3, 9 ); Complex c2 = new Complex( 8, 3 ); // sum Complex s1 = Complex.Add( c1, c2 ); Complex s2 = c1 + c2; Complex s3 = c1 + 5; // difference Complex d1 = Complex.Subtract( c1, c2 ); Complex d2 = c1 - c2; Complex d3 = c1 - 2;
Beispiel #1
0
        private void OnDataReceiverEvent(int[] real, int[] imaginary, int length, rx_metadata_t md)
        {
            if (length < numberOfPoints) // Insufficient data for FFT
            {
                return;
            }
            for (int i = 0; i < numberOfPoints; i++)
            {
                data[i] = new AForge.Math.Complex(real[i], imaginary[i]);
            }

            FourierTransform.FFT(data, FourierTransform.Direction.Forward);
            int count = 0;

            for (int i = numberOfPoints / 2; i < numberOfPoints; i++)
            {
                testValues[i, 1] = data[count++].Magnitude;
            }

            for (int i = 0; i < numberOfPoints / 2; i++)
            {
                testValues[i, 1] = data[count++].Magnitude;
            }

            chart.UpdateDataSeries("Test", testValues);
            //chart.RangeY = new AForge.Range(0, 2048);
        }
Beispiel #2
0
        public static object FFT(double[] Data, object BackwardFlagOpt)
        {
            bool backwards = Utils.GetOptionalParameter(BackwardFlagOpt, false);

            af.FourierTransform.Direction direction = (backwards ? af.FourierTransform.Direction.Backward : af.FourierTransform.Direction.Forward);

            af.Complex[] cData = new af.Complex[Data.Length];
            for (int i = 0; i < Data.Length; ++i)
            {
                cData[i] = new af.Complex(Data[i], 0);
            }

            try
            {
                af.FourierTransform.FFT(cData, direction);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.ToString());
            }

            double[,] ret = new double[Data.Length, 1];
            for (int i = 0; i < Data.Length; ++i)
            {
                ret[i, 0] = cData[i].Re;
            }

            return(ret);
        }
        //public int[] FFT(int[] y)
        public async Task <int[]> FFT(int[] y)
        {
            WvlLogger.Log(LogType.TraceAll, "FFT()");
            var input = new AForge.Math.Complex[y.Length];

            for (int i = 0; i < y.Length; i++)
            {
                input[i] = new AForge.Math.Complex(y[i], 0);
            }

            FourierTransform.FFT(input, FourierTransform.Direction.Forward);

            var result = new int[y.Length / 2];

            // getting magnitude
            for (int i = 0; i < y.Length / 2 - 1; i++)
            {
                var current = Math.Sqrt(input[i].Re * input[i].Re + input[i].Im * input[i].Im);
                current   = Math.Log10(current) * 10;
                result[i] = (int)current;
            }

            samplesUpdated(this, new SamplesUpdatedEventArgs(result));
            //PrepareHeatmapDataSeries(result);
            return(result);
        }
Beispiel #4
0
 /// <summary>
 ///   Computes the absolute value of an array of complex numbers.
 /// </summary>
 public static Complex[] Abs(this Complex[] x)
 {
     var r = new Complex[x.Length];
     for (int i = 0; i < x.Length; i++)
         r[i] = new Complex(x[i].Magnitude, 0);
     return r;
 }
Beispiel #5
0
 /// <summary>
 ///   Elementwise multiplication of two complex vectors.
 /// </summary>
 public static Complex[] Multiply(this Complex[] a, Complex[] b)
 {
     var r = new Complex[a.Length];
     for (int i = 0; i < a.Length; i++)
     {
         r[i] = Complex.Multiply(a[i], b[i]);
     }
     return r;
 }
Beispiel #6
0
        /// <summary>
        ///   Performs the transformation over a double[] array.
        /// </summary>
        public static void FHT(double[] data, FourierTransform.Direction direction)
        {
            int N = data.Length;


            // Forward operation
            if (direction == FourierTransform.Direction.Forward)
            {
                // Copy the input to a complex array which can be processed
                //  in the complex domain by the FFT
                var cdata = new Complex[N];
                for (int i = 0; i < N; i++)
                    cdata[i].Re = data[i];

                // Perform FFT
                FourierTransform.FFT(cdata, FourierTransform.Direction.Forward);

                //double positive frequencies
                for (int i = 1; i < (N/2); i++)
                {
                    cdata[i].Re *= 2.0;
                    cdata[i].Im *= 2.0;
                }

                // zero out negative frequencies
                //  (leaving out the dc component)
                for (int i = (N/2) + 1; i < N; i++)
                {
                    cdata[i].Re = 0.0;
                    cdata[i].Im = 0.0;
                }

                // Reverse the FFT
                FourierTransform.FFT(cdata, FourierTransform.Direction.Backward);

                // Convert back to our initial double array
                for (int i = 0; i < N; i++)
                    data[i] = cdata[i].Im;
            }

            else // Backward operation
            {
                // The inverse Hilbert can be calculated by
                //  negating the transform and reapplying the
                //  transformation.
                //
                // H^–1{h(t)} = –H{h(t)}

                FHT(data, FourierTransform.Direction.Forward);

                for (int i = 0; i < data.Length; i++)
                    data[i] = -data[i];
            }
        }
        /// <summary>
        ///   Processes the filter.
        /// </summary>
        /// 
        protected override void ProcessFilter(ComplexSignal sourceData, ComplexSignal destinationData)
        {
            int length = sourceData.Length;

            unsafe
            {
                Complex* src = (Complex*)sourceData.Data.ToPointer();
                Complex* dst = (Complex*)destinationData.Data.ToPointer();

                Complex d = new Complex();

                for (int i = 0; i < length - 1; i++, src++, dst++)
                {
                    d.Re = src[i + 1].Re - src[i].Re;

                    // Retain only if difference is positive
                    *dst = (d.Re > 0) ? d : Complex.Zero;
                }
            }
        }
        /// <summary>
        ///   1-D Discrete Fourier Transform.
        /// </summary>
        /// 
        /// <param name="data">The data to transform..</param>
        /// <param name="direction">The transformation direction.</param>
        /// 
        public static void DFT(Complex[] data, FourierTransform.Direction direction)
        {
            int n = data.Length;
            var c = new Complex[n];

            // for each destination element
            for (int i = 0; i < c.Length; i++)
            {
                double sumRe = 0;
                double sumIm = 0;
                double phim = 2 * Math.PI * i / (double)n;

                // sum source elements
                for (int j = 0; j < n; j++)
                {
                    double re = data[j].Re();
                    double im = data[j].Im();
                    double cosw = Math.Cos(phim * j);
                    double sinw = Math.Sin(phim * j);

                    if (direction == FourierTransform.Direction.Backward)
                        sinw = -sinw;

                    sumRe += (re * cosw + im * sinw);
                    sumIm += (im * cosw - re * sinw);
                }

                c[i] = new Complex(sumRe, sumIm);
            }

            if (direction == FourierTransform.Direction.Backward)
            {
                for (int i = 0; i < c.Length; i++)
                    data[i] = c[i] / n;
            }
            else
            {
                for (int i = 0; i < c.Length; i++)
                    data[i] = c[i];
            }
        }
Beispiel #9
0
        public int[] FFT(int[] y)
        {
            WvlLogger.Log(LogType.TraceAll, "FFT()");
            WvlLogger.Log(LogType.TraceValues, "FFT() - int[] y.length : " + y.Length.ToString() + "y.Sum : " + y.Sum().ToString());


            var input = new AForge.Math.Complex[y.Length];

            for (int i = 0; i < y.Length; i++)
            {
                input[i] = new AForge.Math.Complex(y[i], 0);
            }

            FourierTransform.FFT(input, FourierTransform.Direction.Forward);

            var result = new int[y.Length / 2];

            // getting magnitude
            for (int i = 0; i < y.Length / 2 - 1; i++)
            {
                var current = Math.Sqrt(input[i].Re * input[i].Re + input[i].Im * input[i].Im);
                current   = Math.Log10(current) * 10;
                result[i] = (int)current;
            }


            // debug

            /*
             * int myMin = 0;
             * int myMax = 0;
             * myMin = result.Min();
             * myMax = result.Max();
             * debugMin = (debugMin <= myMin) ? debugMin : myMin;
             * debugMax = (debugMax >= myMax) ? debugMax : myMax;
             */

            WvlLogger.Log(LogType.TraceValues, "FFT() - result : " + result.Length.ToString() + "y.Sum : " + result.Sum().ToString());
            return(result);
        }
        public int[] FFT(int[] y)
        {
            var input = new AForge.Math.Complex[y.Length];

            for (int i = 0; i < y.Length; i++)
            {
                input[i] = new AForge.Math.Complex(y[i], 0);
            }

            FourierTransform.FFT(input, FourierTransform.Direction.Forward);

            var result = new int[y.Length / 2];

            // getting magnitude
            for (int i = 0; i < y.Length / 2 - 1; i++)
            {
                var current = Math.Sqrt(input[i].Re * input[i].Re + input[i].Im * input[i].Im);
                current   = Math.Log10(current) * 10;
                result[i] = (int)current;
            }

            return(result);
        }
Beispiel #11
0
 /// <summary>
 /// Adds scalar value to a complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="s">A scalar value.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the sum of specified
 /// complex number and scalar value.</returns>
 ///
 public static Complex Add(Complex a, double s)
 {
     return(new Complex(a.Re + s, a.Im));
 }
Beispiel #12
0
 /// <summary>
 /// Subtracts a scalar value from a complex number and puts the result into another complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance to subtract from.</param>
 /// <param name="s">A scalar value to be subtracted.</param>
 /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
 ///
 public static void Subtract(Complex a, double s, ref Complex result)
 {
     result.Re = a.Re - s;
     result.Im = a.Im;
 }
Beispiel #13
0
 /// <summary>
 /// Multiplies a complex number by a scalar value.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="s">A scalar value.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the result of multiplication.</returns>
 ///
 public static Complex Multiply(Complex a, double s)
 {
     return(new Complex(a.Re * s, a.Im * s));
 }
Beispiel #14
0
 /// <summary>
 /// Adds two complex numbers and puts the result into the third complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="b">A <see cref="Complex"/> instance.</param>
 /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
 ///
 public static void Add(Complex a, Complex b, ref Complex result)
 {
     result.Re = a.Re + b.Re;
     result.Im = a.Im + b.Im;
 }
Beispiel #15
0
 /// <summary>
 /// Subtracts one complex number from another.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance to subtract from.</param>
 /// <param name="b">A <see cref="Complex"/> instance to be subtracted.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the subtraction result (<b>a - b</b>).</returns>
 ///
 public static Complex Subtract(Complex a, Complex b)
 {
     return(new Complex(a.Re - b.Re, a.Im - b.Im));
 }
Beispiel #16
0
 /// <summary>
 /// Subtracts a complex number from a scalar value.
 /// </summary>
 ///
 /// <param name="s">A scalar value to subtract from.</param>
 /// <param name="a">A <see cref="Complex"/> instance to be subtracted.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the subtraction result (<b>s - a</b>).</returns>
 ///
 public static Complex Subtract(double s, Complex a)
 {
     return(new Complex(s - a.Re, a.Im));
 }
Beispiel #17
0
 /// <summary>
 /// Subtracts one complex number from another and puts the result in the third complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance to subtract from.</param>
 /// <param name="b">A <see cref="Complex"/> instance to be subtracted.</param>
 /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
 ///
 public static void Subtract(Complex a, Complex b, ref Complex result)
 {
     result.Re = a.Re - b.Re;
     result.Im = a.Im - b.Im;
 }
Beispiel #18
0
 /// <summary>
 /// Adds a complex number and a scalar value.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="s">A scalar value.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the sum.</returns>
 ///
 public static Complex operator +(double s, Complex a)
 {
     return(Complex.Add(a, s));
 }
Beispiel #19
0
 /// <summary>
 /// Adds two complex numbers.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="b">A <see cref="Complex"/> instance.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the sum.</returns>
 ///
 public static Complex operator +(Complex a, Complex b)
 {
     return(Complex.Add(a, b));
 }
Beispiel #20
0
 /// <summary>
 /// Negates the complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/>  instance.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the negated values.</returns>
 ///
 public static Complex operator -(Complex a)
 {
     return(Complex.Negate(a));
 }
Beispiel #21
0
 /// <summary>
 /// Tests whether two complex numbers are approximately equal using default tolerance value.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="b">A <see cref="Complex"/> instance.</param>
 ///
 /// <returns>Return <see langword="true"/> if the two vectors are approximately equal or <see langword="false"/> otherwise.</returns>
 ///
 /// <remarks><para>The default tolerance value, which is used for the test, equals to 8.8817841970012523233891E-16.</para></remarks>
 ///
 public static bool ApproxEqual(Complex a, Complex b)
 {
     return(ApproxEqual(a, b, 8.8817841970012523233891E-16));
 }
Beispiel #22
0
 /// <summary>
 /// Negates a complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the negated values.</returns>
 ///
 public static Complex Negate(Complex a)
 {
     return(new Complex(-a.Re, -a.Im));
 }
Beispiel #23
0
 /// <summary>
 /// Multiplies a complex number by a scalar value and puts the result into another complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="s">A scalar value.</param>
 /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
 ///
 public static void Multiply(Complex a, double s, ref Complex result)
 {
     result.Re = a.Re * s;
     result.Im = a.Im * s;
 }
Beispiel #24
0
        void solve()
        {
            show_result_2.Clear();
            if (a == 0)
            {
                if (b != 0)
                {
                    root_1.Clear();
                    root_2.Clear();
                    root_1.Text         = root_1.Text + Convert.ToString(Math.Round(-c / b, 4));
                    show_result_2.Text += "Phương trình có 1 nghiệm duy nhất";
                    ;
                }
                else
                {
                    root_1.Clear();
                    root_2.Clear();
                    root_1.Text         = root_1.Text + "No solution";
                    root_2.Text         = root_2.Text + "No solution";
                    show_result_2.Text += "Phương trình vô nghiệm";
                }
            }
            else
            {
                double delta = b * b - 4 * a * c;
                if (delta >= 0)
                {
                    double x1, x2;
                    x1 = (-b + Math.Sqrt(delta)) / (2 * a);
                    x2 = (-b - Math.Sqrt(delta)) / (2 * a);
                    root_1.Clear();
                    root_1.Text = root_1.Text + Convert.ToString(Math.Round(x1, 4));
                    root_2.Clear();
                    root_2.Text = root_2.Text + Convert.ToString(Math.Round(x2, 4));
                    if (delta == 0)
                    {
                        show_result_2.Text += "Phương trình có nghiệm kép";
                    }
                    else
                    {
                        show_result_2.Text += "Phương trình có 2 nghiệm phân biệt";
                    }
                }
                else
                {
                    AForge.Math.Complex x1;
                    AForge.Math.Complex delta_1 = new AForge.Math.Complex(delta, 0);
                    x1 = (-b + AForge.Math.Complex.Sqrt(delta_1)) / (2 * a);
                    root_1.Clear();

                    root_1.Text = root_1.Text + Convert.ToString(Math.Round(x1.Re, 4));
                    if (x1.Im > 0)
                    {
                        root_1.Text = root_1.Text + "+";
                    }
                    root_1.Text = root_1.Text + Convert.ToString(Math.Round(x1.Im, 4));
                    root_1.Text = root_1.Text + "*i";
                    root_2.Clear();
                    root_2.Text = root_2.Text + Convert.ToString(Math.Round(x1.Re, 4));
                    if (x1.Im < 0)
                    {
                        root_2.Text = root_1.Text + "+";
                    }
                    root_2.Text         = root_2.Text + Convert.ToString(Math.Round(-x1.Im, 4));
                    root_2.Text         = root_2.Text + "*i";
                    show_result_2.Text += "Phương trình có 2 nghiệm phân biệt";
                }
            }
        }
Beispiel #25
0
        /// <summary>
        ///   Performs the transformation over a complex[] array.
        /// </summary>
        public static void FHT(Complex[] data, FourierTransform.Direction direction)
        {
            int N = data.Length;

            // Forward operation
            if (direction == FourierTransform.Direction.Forward)
            {
                // Makes a copy of the data so we don't lose the
                //  original information to build our final signal
                var shift = (Complex[]) data.Clone();

                // Perform FFT
                FourierTransform.FFT(shift, FourierTransform.Direction.Backward);

                //double positive frequencies
                for (int i = 1; i < (N/2); i++)
                {
                    shift[i].Re *= 2.0;
                    shift[i].Im *= 2.0;
                }
                // zero out negative frequencies
                //  (leaving out the dc component)
                for (int i = (N/2) + 1; i < N; i++)
                {
                    shift[i].Re = 0.0;
                    shift[i].Im = 0.0;
                }

                // Reverse the FFT
                FourierTransform.FFT(shift, FourierTransform.Direction.Forward);

                // Put the Hilbert transform in the Imaginary part
                //  of the input signal, creating a Analytic Signal
                for (int i = 0; i < N; i++)
                    data[i].Im = shift[i].Im;
            }

            else // Backward operation
            {
                // Just discard the imaginary part
                for (int i = 0; i < data.Length; i++)
                    data[i].Im = 0.0;
            }
        }
        /// <summary>
        ///   Applies the filter to a signal.
        /// </summary>
        protected unsafe override void ProcessFilter(Signal sourceData, Signal destinationData)
        {
            SampleFormat format = sourceData.SampleFormat;
            int samples = sourceData.Samples;

            if (format == SampleFormat.Format32BitIeeeFloat)
            {
                float* src = (float*)sourceData.Data.ToPointer();
                float* dst = (float*)destinationData.Data.ToPointer();

                for (int i = 0; i < samples; i++, dst++, src++)
                    *dst = System.Math.Abs(*src);
            }
            else if (format == SampleFormat.Format128BitComplex)
            {
                Complex* src = (Complex*)sourceData.Data.ToPointer();
                Complex* dst = (Complex*)destinationData.Data.ToPointer();

                Complex c = new Complex();

                for (int i = 0; i < samples; i++, dst++, src++)
                {
                    c.Re = (*src).Magnitude;
                    *dst = c;
                }
            }
        }
        /// <summary>
        ///   Splits a signal using the window.
        /// </summary>
        /// 
        public virtual ComplexSignal Apply(ComplexSignal complexSignal, int sampleIndex)
        {
            Complex[,] resultData = new Complex[Length, complexSignal.Channels];
            ComplexSignal result = ComplexSignal.FromArray(resultData, complexSignal.SampleRate);

            int channels = result.Channels;
            int minLength = System.Math.Min(complexSignal.Length - sampleIndex, Length);

            unsafe
            {
                for (int c = 0; c < complexSignal.Channels; c++)
                {
                    Complex* dst = (Complex*)result.Data.ToPointer() + c;
                    Complex* src = (Complex*)complexSignal.Data.ToPointer() + c + channels * sampleIndex;

                    for (int i = 0; i < minLength; i++, dst += channels, src += channels)
                    {
                        *dst = window[i] * (*src);
                    }
                }
            }

            return result;
        }
        /// <summary>
        ///   1-D Fast Fourier Transform.
        /// </summary>
        /// 
        /// <param name="data">The data to transform..</param>
        /// <param name="direction">The transformation direction.</param>
        /// 
        public static void FFT(Complex[] data, FourierTransform.Direction direction)
        {
            int n = data.Length;

            if (n == 0)
                return;

            if (direction == FourierTransform.Direction.Backward)
            {
                for (int i = 0; i < data.Length; i++)
                    data[i] = new Complex(data[i].Im(), data[i].Re());
            }

            if ((n & (n - 1)) == 0)
            {
                // Is power of 2
                TransformRadix2(data);
            }
            else
            {
                // More complicated algorithm for arbitrary sizes
                TransformBluestein(data);
            }

            if (direction == FourierTransform.Direction.Backward)
            {
                for (int i = 0; i < data.Length; i++)
                {
                    double im = data[i].Im();
                    double re = data[i].Re();
                    data[i] = new Complex(im / n, re / n);
                }
            }
        }
Beispiel #29
0
 /// <summary>
 /// Subtracts a scalar from a complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance to subtract from.</param>
 /// <param name="s">A scalar value to be subtracted.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the subtraction result (<b>a - s</b>).</returns>
 ///
 public static Complex Subtract(Complex a, double s)
 {
     return(new Complex(a.Re - s, a.Im));
 }
        /// <summary>
        ///   Computes the inverse discrete Fourier transform (IDFT) of the given complex 
        ///   vector, storing the result back into the vector. The vector can have any length.
        ///   This is a wrapper function. This transform does not perform scaling, so the 
        ///   inverse is not a true inverse.
        /// </summary>
        /// 
        private static void IDFT(Complex[] data)
        {
            int n = data.Length;

            if (n == 0)
                return;

            for (int i = 0; i < data.Length; i++)
                data[i] = new Complex(data[i].Im(), data[i].Re());

            if ((n & (n - 1)) == 0)
            {
                // Is power of 2
                TransformRadix2(data);
            }
            else
            {
                // More complicated algorithm for arbitrary sizes
                TransformBluestein(data);
            }

            for (int i = 0; i < data.Length; i++)
            {
                double im = data[i].Im();
                double re = data[i].Re();
                data[i] = new Complex(im, re);
            }
        }
Beispiel #31
0
 /// <summary>
 /// Adds scalar value to a complex number and puts the result into another complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="s">A scalar value.</param>
 /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
 ///
 public static void Add(Complex a, double s, ref Complex result)
 {
     result.Re = a.Re + s;
     result.Im = a.Im;
 }
        private static void TransformBluestein(Complex[] data)
        {
            int n = data.Length;
            int m = HighestOneBit(n * 2 + 1) << 1;

            // Trignometric tables
            var cosTable = new double[n];
            var sinTable = new double[n];
            for (int i = 0; i < cosTable.Length; i++)
            {
                int j = (int)((long)i * i % (n * 2));  // This is more accurate than j = i * i
                cosTable[i] = Math.Cos(Math.PI * j / n);
                sinTable[i] = Math.Sin(Math.PI * j / n);
            }

            // Temporary vectors and preprocessing
            var areal = new double[m];
            var aimag = new double[m];

            for (int i = 0; i < data.Length; i++)
            {
                double re = data[i].Re();
                double im = data[i].Im();

                areal[i] = +re * cosTable[i] + im * sinTable[i];
                aimag[i] = -re * sinTable[i] + im * cosTable[i];
            }

            var breal = new double[m];
            var bimag = new double[m];
            breal[0] = cosTable[0];
            bimag[0] = sinTable[0];

            for (int i = 1; i < cosTable.Length; i++)
            {
                breal[i] = breal[m - i] = cosTable[i];
                bimag[i] = bimag[m - i] = sinTable[i];
            }

            // Convolution
            var creal = new double[m];
            var cimag = new double[m];
            Convolve(areal, aimag, breal, bimag, creal, cimag);

            // Postprocessing
            for (int i = 0; i < data.Length; i++)
            {
                double re = +creal[i] * cosTable[i] + cimag[i] * sinTable[i];
                double im = -creal[i] * sinTable[i] + cimag[i] * cosTable[i];
                data[i] = new Complex(re, im);
            }
        }
Beispiel #33
0
 /// <summary>
 /// Subtracts one complex number from another complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="b">A <see cref="Complex"/> instance.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the difference.</returns>
 ///
 public static Complex operator -(Complex a, Complex b)
 {
     return(Complex.Subtract(a, b));
 }
Beispiel #34
0
 /// <summary>
 /// Subtracts a complex number from a scalar value and puts the result into another complex number.
 /// </summary>
 ///
 /// <param name="s">A scalar value to subtract from.</param>
 /// <param name="a">A <see cref="Complex"/> instance to be subtracted.</param>
 /// <param name="result">A <see cref="Complex"/> instance to hold the result.</param>
 ///
 public static void Subtract(double s, Complex a, ref Complex result)
 {
     result.Re = s - a.Re;
     result.Im = a.Im;
 }
Beispiel #35
0
        private void AllFrameAvailable(object sender, MultiSourceFrameArrivedEventArgs e)
        {
            bool processed    = true;
            bool dataReceived = true;

            using (MultiSourceFrame multiFrame = e.FrameReference.AcquireFrame())
            {
                #region Image Display
                using (ColorFrame colorFrame = multiFrame.ColorFrameReference.AcquireFrame())
                {
                    if (multiFrame != null && colorFrame != null)
                    {
                        hrData[j] = multiFrame;
                        j++;
                        if (j == 60)
                        {
                            j = 0;
                        }

                        FrameDescription colorFrameDescription = colorFrame.FrameDescription;

                        // verify data and write the new color frame data to the display bitmap
                        if ((colorFrameDescription.Width == this.wBitmap.PixelWidth) && (colorFrameDescription.Height == this.wBitmap.PixelHeight))
                        {
                            if (colorFrame.RawColorImageFormat == ColorImageFormat.Bgra)
                            {
                                colorFrame.CopyRawFrameDataToArray(this.colorPixels);
                            }
                            else
                            {
                                colorFrame.CopyConvertedFrameDataToArray(this.colorPixels, ColorImageFormat.Bgra);
                            }

                            processed = true;
                        }
                    }

                    // we got a frame, render
                    if (processed)
                    {
                        RenderColorPixels(this.colorPixels);
                    }

                    #endregion
                    #region Body Tracking
                    using (BodyFrame bodyFrame = multiFrame.BodyFrameReference.AcquireFrame())
                    {
                        if (bodyFrame != null)
                        {
                            bodyFrame.GetAndRefreshBodyData(this.bodies);

                            dataReceived = true;
                        }
                    }
                    if (dataReceived)
                    {
                        StatusTexts[0] = PersonStatus1;
                        StatusTexts[1] = PersonStatus2;
                        StatusTexts[2] = PersonStatus3;
                        StatusTexts[3] = PersonStatus4;
                        StatusTexts[4] = PersonStatus5;
                        StatusTexts[5] = PersonStatus6;

                        for (int bodyIndex = 0; bodyIndex < this.bodies.Length - 1; bodyIndex++)
                        {
                            Body body = this.bodies[bodyIndex];
                            if (body != null && body.IsTracked)
                            {
                                //  mainImage.Visibility = Visibility.Visible;
                                StatusTexts[bodyIndex].Visibility = Visibility.Visible;

                                if (!this.currentlyTakingVitals)
                                {
                                    VisualStateManager.GoToState(this, VSG_TakingVitals.Name, false);
                                    //mainImage.Opacity = 1;
                                    //this.storyboard.Stop();
                                    //this.takeVitals.Begin();
                                    this.currentlyTakingVitals = true;
                                }

                                //Get Facial expressions
                                var expressions = body.Expressions;
                                //foreach(var expressionItem in expressions)
                                //{
                                //    var expression = expressionItem.Value;
                                //    var expName = expressionItem.Key;


                                //}

                                //var appearanceItem = body.Appearance;

                                //foreach (var appearanceItem in body.Appearance)
                                //{
                                //    var appearance = appearanceItem.Value;
                                //    var appName = appearanceItem.Key;
                                //}

                                //var activities = body.Activities;
                                //foreach(var activityItem in activities)
                                //{
                                //    var activity = activityItem.Value;
                                //    var actName = activityItem.Key;

                                //}

                                var   jointPointsInDepthSpace = new Dictionary <JointType, Point>();
                                Joint head = body.Joints[JointType.Head];

                                Rect headRct, chestRct;
                                var  foundHead = GetHeadRegion(body, ref headRct);

                                if (foundHead)
                                {
                                    //start calculating heart Rate
                                    using (InfraredFrame irFrame = multiFrame.InfraredFrameReference.AcquireFrame())
                                    {
                                        if (irFrame != null)
                                        {
                                            var timestamp = irFrame.RelativeTime;

                                            irFrame.CopyFrameDataToArray(this.irData);
                                            var avg = GetAverageIRIntensity(headRct, this.irData);
                                            this.irAverages[matrixCounter[bodyIndex], bodyIndex]                  = avg;
                                            this.matrices[matrixCounter[bodyIndex], bodyIndex].BodyIndex          = bodyIndex;
                                            this.matrices[matrixCounter[bodyIndex], bodyIndex].AverageIRIntensity = avg;
                                            this.matrices[matrixCounter[bodyIndex], bodyIndex].TimeStamp          = timestamp;

                                            if (matrixCounter[bodyIndex] == 0)
                                            {
                                                this.matrices[matrixCounter[bodyIndex], bodyIndex].AverageIRIntensity = 0;
                                                this.matrices[matrixCounter[bodyIndex], bodyIndex].RateOfChange       = 0;
                                            }
                                            else
                                            {
                                                var timeDelta    = this.matrices[matrixCounter[bodyIndex], bodyIndex].TimeStamp - this.matrices[matrixCounter[bodyIndex] - 1, bodyIndex].TimeStamp;
                                                var freqDelta    = this.matrices[matrixCounter[bodyIndex], bodyIndex].AverageIRIntensity - this.matrices[matrixCounter[bodyIndex] - 1, bodyIndex].AverageIRIntensity;
                                                var rateOfChange = freqDelta / timeDelta.Milliseconds;
                                                this.matrices[matrixCounter[bodyIndex], bodyIndex].RateOfChange = rateOfChange;
                                            }

                                            matrixCounter[bodyIndex]++;

                                            //every 6 seconds, or 1800 frames calculate a value...
                                            if ((matrixCounter[bodyIndex]) % 256 == 0)
                                            {
                                                AForge.Math.Complex[] cmpxArray = new AForge.Math.Complex[256];

                                                var cnt = matrixCounter[bodyIndex] - 256;
                                                for (int i = 0; i < 256; i++)
                                                {
                                                    cmpxArray[i] = new AForge.Math.Complex(this.irAverages[cnt, bodyIndex], 0);

                                                    cnt++;
                                                }

                                                var cmplx = Hann(cmpxArray);
                                                FourierTransform.FFT(cmplx, FourierTransform.Direction.Forward);
                                                double bpm = 0;
                                                for (int j = 1; j < cmpxArray.Length; j++)
                                                {
                                                    if (cmpxArray[j].Re > cmpxArray[j - 1].Re)
                                                    {
                                                        bpm = cmpxArray[j].Re * 9;
                                                        //was 12;
                                                    }
                                                }
                                                HeartRateCount = (int)bpm;

                                                StatusTexts[bodyIndex].Text = string.Format("{0} bpm", HeartRateCount);

                                                if (!currentlyShowingResults && currentlyTakingVitals)
                                                {
                                                    VisualStateManager.GoToState(this, VSG_ShowResults.Name, true);
                                                    //this.takeVitals.Stop();
                                                    this.currentlyTakingVitals = false;
                                                    this.title5.Text           = string.Format("Person tracked at: {0}", bodyIndex);
                                                    this.title6.Text           = string.Format("has a HeartRate Of {0} bpm", HeartRateCount);
                                                    //this.showVitalResults.Begin();
                                                    currentlyShowingResults = true;
                                                }
                                            }

                                            if (matrixCounter[bodyIndex] >= maxSeconds)
                                            {
                                                //    //we're finished counting...

                                                VisualStateManager.GoToState(this, VSG_ShowResults.Name, true);

                                                matrixCounter[bodyIndex] = 0;
                                            }

                                            //    var size = matrixCounter[bodyIndex] - 1;
                                            //    var calcAvg = AverageRateOfChange(size, bodyIndex);

                                            //    var calcStdDev = Deviation(calcAvg, size, bodyIndex);
                                            //    var heartRateCount = CalculateRateSpikesMoreThan3Deviations(calcAvg, calcStdDev, size, bodyIndex);
                                            //    HeartRateCount = heartRateCount;
                                            //    StatusTexts[bodyIndex].Text = string.Format("{0} bpm", HeartRateCount);
                                            //    matrixCounter[bodyIndex] = 0;
                                            //}
                                        }
                                    }
                                }
                                // var foundChest = GetChestRegion(body, ref chestRct);

                                CameraSpacePoint position = body.Joints[JointType.Head].Position;

                                DepthSpacePoint depthSpacePoint = coordinateMapper.MapCameraPointToDepthSpace(position);
                                jointPointsInDepthSpace[JointType.Head] = new Point(depthSpacePoint.X, depthSpacePoint.Y);



                                StatusTexts[bodyIndex].SetValue(Canvas.TopProperty, 140 + jointPointsInDepthSpace[JointType.Head].Y);
                                StatusTexts[bodyIndex].SetValue(Canvas.LeftProperty, 180 + jointPointsInDepthSpace[JointType.Head].X);
                                showStartScreenCounter = 0;
                                VisualStateManager.GoToState(this, VSG_TakingVitals.Name, true);
                            }
                            else
                            {
                                //if
                                //if(currentlyShowingResults || currentlyTakingVitals)
                                //{
                                //  VisualStateManager.GoToState(this, VSG_Attract.Name, true);
                                //this.showVitalResults.Stop();
                                //this.takeVitals.Stop();
                                //this.storyboard.Begin();
                                //this.currentlyShowingResults = false;
                                //this.currentlyTakingVitals = false;
                                //
                                // }
                                showStartScreenCounter++;
                                if (showStartScreenCounter > 600)
                                {
                                    VisualStateManager.GoToState(this, VSG_Attract.Name, true);
                                    showStartScreenCounter = 0;
                                }
                                StatusTexts[bodyIndex].Visibility = Visibility.Collapsed;
                                // mainImage.Visibility = Visibility.Collapsed;
                            }
                        }
                    }
                    else
                    {
                        VisualStateManager.GoToState(this, VSG_Attract.Name, true);
                    }
                }
                #endregion

                //#region "Heart Rate Section"

                //using (BodyFrame bodyFrame = multiFrame.BodyFrameReference.AcquireFrame())
                //{
                //    if (bodyFrame == null)
                //    {
                //        return;
                //    }
                //    using (BodyIndexFrame bodyIndexFrame = multiFrame.BodyIndexFrameReference.AcquireFrame())
                //    {
                //        if (bodyIndexFrame == null)
                //        {
                //            return;
                //        }


                //        using (InfraredFrame irFrame = multiFrame.InfraredFrameReference.AcquireFrame())
                //        {
                //            if (irFrame == null)
                //            {
                //                return;
                //            }

                //            needsMoreFrames = m_heartRate.GetCurrentHeartRate(bodyFrame, bodyIndexFrame, irFrame);
                //        }
                //    }
                //}
                //#endregion
            }
        }
Beispiel #36
0
 /// <summary>
 /// Subtracts a scalar value from a complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="s">A scalar value.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the difference.</returns>
 ///
 public static Complex operator -(Complex a, double s)
 {
     return(Complex.Subtract(a, s));
 }
        /// <summary>
        ///   2-D Discrete Fourier Transform.
        /// </summary>
        /// 
        /// <param name="data">The data to transform.</param>
        /// <param name="direction">The transformation direction.</param>
        /// 
        public static void DFT2(Complex[][] data, FourierTransform.Direction direction)
        {
            int n = data.Length;
            int m = data[0].Length;

            // process rows
            var row = new Complex[m];
            for (int i = 0; i < n; i++)
            {
                // copy row
                for (int j = 0; j < row.Length; j++)
                    row[j] = data[i][j];

                // transform it
                DFT(row, direction);

                // copy back
                for (int j = 0; j < row.Length; j++)
                    data[i][j] = row[j];
            }

            // process columns
            var col = new Complex[n];
            for (int j = 0; j < n; j++)
            {
                // copy column
                for (int i = 0; i < col.Length; i++)
                    col[i] = data[i][j];

                // transform it
                DFT(col, direction);

                // copy back
                for (int i = 0; i < col.Length; i++)
                    data[i][j] = col[i];
            }
        }
Beispiel #38
0
 /// <summary>
 /// Subtracts a complex number from a scalar value.
 /// </summary>
 ///
 /// <param name="s">A scalar value.</param>
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the difference.</returns>
 ///
 public static Complex operator -(double s, Complex a)
 {
     return(Complex.Subtract(s, a));
 }
        /// <summary>
        ///   2-D Fast Fourier Transform.
        /// </summary>
        /// 
        /// <param name="data">The data to transform..</param>
        /// <param name="direction">The Transformation direction.</param>
        /// 
        public static void FFT2(Complex[][] data, FourierTransform.Direction direction)
        {
            int n = data.Length;
            int m = data[0].Length;

            // process rows
            for (int i = 0; i < data.Length; i++)
            {
                // transform it
                FFT(data[i], direction);
            }

            // process columns
            var col = new Complex[n];
            for (int j = 0; j < m; j++)
            {
                // copy column
                for (int i = 0; i < col.Length; i++)
                    col[i] = data[i][j];

                // transform it
                FFT(col, direction);

                // copy back
                for (int i = 0; i < col.Length; i++)
                    data[i][j] = col[i];
            }
        }
Beispiel #40
0
 /// <summary>
 /// Multiplies two complex numbers.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="b">A <see cref="Complex"/> instance.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the result of multiplication.</returns>
 ///
 public static Complex operator *(Complex a, Complex b)
 {
     return(Complex.Multiply(a, b));
 }
        /// <summary>
        ///   Computes the discrete Fourier transform (DFT) of the given complex vector, storing 
        ///   the result back into the vector. The vector's length must be a power of 2. Uses the 
        ///   Cooley-Tukey decimation-in-time radix-2 algorithm.
        /// </summary>
        /// 
        /// <exception cref="System.ArgumentException">Length is not a power of 2.</exception>
        /// 
        private static void TransformRadix2(Complex[] complex)
        {
            int n = complex.Length;

            int levels = (int)Math.Floor(Math.Log(n, 2));

            if (1 << levels != n)
                throw new ArgumentException("Length is not a power of 2");

            // TODO: keep those tables in memory
            var cosTable = new double[n / 2];
            var sinTable = new double[n / 2];
            for (int i = 0; i < n / 2; i++)
            {
                cosTable[i] = Math.Cos(2 * Math.PI * i / n);
                sinTable[i] = Math.Sin(2 * Math.PI * i / n);
            }

            // Bit-reversed addressing permutation
            for (int i = 0; i < complex.Length; i++)
            {
                int j = unchecked((int)((uint)Reverse(i) >> (32 - levels)));

                if (j > i)
                {
                    var temp = complex[i];
                    complex[i] = complex[j];
                    complex[j] = temp;
                }
            }


            // Cooley-Tukey decimation-in-time radix-2 FFT
            for (int size = 2; size <= n; size *= 2)
            {
                int halfsize = size / 2;
                int tablestep = n / size;

                for (int i = 0; i < n; i += size)
                {
                    for (int j = i, k = 0; j < i + halfsize; j++, k += tablestep)
                    {
                        int h = j + halfsize;
                        double re = complex[h].Re();
                        double im = complex[h].Im();

                        double tpre = +re * cosTable[k] + im * sinTable[k];
                        double tpim = -re * sinTable[k] + im * cosTable[k];

                        double rej = complex[j].Re();
                        double imj = complex[j].Im();

                        complex[h] = new Complex(rej - tpre, imj - tpim);
                        complex[j] = new Complex(rej + tpre, imj + tpim);
                    }
                }

                // Prevent overflow in 'size *= 2'
                if (size == n)
                    break;
            }
        }
Beispiel #42
0
 /// <summary>
 /// Multiplies a complex number by a scalar value.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="s">A scalar value.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the result of multiplication.</returns>
 ///
 public static Complex operator *(Complex a, double s)
 {
     return(Complex.Multiply(a, s));
 }
        /// <summary>
        ///   Computes the circular convolution of the given complex 
        ///   vectors. All vectors must have the same length.
        /// </summary>
        /// 
        public static void Convolve(Complex[] x, Complex[] y, Complex[] result)
        {
            FFT(x, FourierTransform.Direction.Forward);
            FFT(y, FourierTransform.Direction.Forward);

            for (int i = 0; i < x.Length; i++)
            {
                double xreal = x[i].Re();
                double ximag = x[i].Im();
                double yreal = y[i].Re();
                double yimag = y[i].Im();

                double re = xreal * yreal - ximag * yimag;
                double im = ximag * yreal + xreal * yimag;

                x[i] = new Complex(re, im);
            }

            IDFT(x);

            // Scaling (because this FFT implementation omits it)
            for (int i = 0; i < x.Length; i++)
            {
                result[i] = x[i] / x.Length;
            }
        }
Beispiel #44
0
 /// <summary>
 /// Divides one complex number by another complex number.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="b">A <see cref="Complex"/> instance.</param>
 ///
 /// <returns>A new Complex instance containing the result.</returns>
 /// <returns>Returns new <see cref="Complex"/> instance containing the result of division.</returns>
 ///
 public static Complex operator /(Complex a, Complex b)
 {
     return(Complex.Divide(a, b));
 }
Beispiel #45
0
        /// <summary>
        /// Processes the filter.
        /// </summary>
        /// 
        protected override void ProcessFilter(ComplexSignal sourceData, ComplexSignal destinationData)
        {
            SampleFormat format = sourceData.SampleFormat;
            int channels = sourceData.Channels;
            int length = sourceData.Length;
            int samples = sourceData.Samples;

            unsafe
            {
                Complex* src = (Complex*)sourceData.Data.ToPointer();
                Complex* dst = (Complex*)destinationData.Data.ToPointer();
                Complex* comb = (Complex*)combSignal.Data.ToPointer();

                Complex d = new Complex();

                for (int i = 0; i < samples; i++, src++, dst++, comb++)
                {
                    d.Re = (src[0] * comb[0]).Magnitude;
                    *dst = d;
                }
            }
        }
Beispiel #46
0
 /// <summary>
 /// Divides a complex number by a scalar value.
 /// </summary>
 ///
 /// <param name="a">A <see cref="Complex"/> instance.</param>
 /// <param name="s">A scalar value.</param>
 ///
 /// <returns>Returns new <see cref="Complex"/> instance containing the result of division.</returns>
 ///
 public static Complex operator /(Complex a, double s)
 {
     return(Complex.Divide(a, s));
 }