GazeDecimator.cs 2.54 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace TrackerBridge.DSP
{
    class GazeDecimator : IGazeFilter
    {
        public event GazeDataHandler OutputAvailable;

        private Single inputFrequency;
        private GazeData output;
        private Single outputFrequency;
        private Object outputLock = new Object();
        private Object valueCountLock = new Object();
        private Int64 valueCount;

        public Single InputFrequency { get => inputFrequency; set => inputFrequency = value; }
        private Int64 ValueCount {
            get {
                lock (valueCountLock)
                {
                    return valueCount;
                }
            }
            set {
                lock (valueCountLock)
                {
                    valueCount = value;
                }
            }
        }

        private GazeData Output {
            get {
                lock (outputLock)
                {
                    return output;
                }
            }
            set {
                lock (outputLock)
                {
                    output = value;
                }
            }
        }

        public GazeDecimator(Single outputFrequency, Single inputFrequency)
        {
            this.outputFrequency = outputFrequency;
            this.InputFrequency = inputFrequency;
            Task.Run(() => TriggerOutput(outputFrequency));
        }
        public void Input(GazeData input, Object sender = null)
        {
            if (ValueCount == 0)
            {
                Output = input;
            }
            else
            {
                //Cumulative moving average (CMA) -> https://en.wikipedia.org/wiki/Moving_average#Cumulative_moving_average
                lock (outputLock)
                {
                    output += (input - output) / (ValueCount + 1);
                }

            }
            ValueCount++;
        }

        public void Reset()
        {
            ValueCount = 0;
        }

        private void TriggerOutput(Single frequency)
        {
            Timer timer = new Timer(1000.0 / frequency); //TODO: Implement Dispose
            timer.Elapsed += (Object sender, ElapsedEventArgs e) =>
            {
                if (ValueCount > 0)
                {
                    OutputAvailable?.Invoke(Output, this);
                    Reset();
                }
            };
            timer.AutoReset = true;
            timer.Start();
        }
    }
}