GazeDecimator.cs 2.55 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
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 GazeData output;
        private Single outputFrequency;
16
        private Timer timer;
17 18
        private readonly Object outputLock = new Object();
        private readonly Object valueCountLock = new Object();
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
        private Int64 valueCount;

        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;
                }
            }
        }

51
        public GazeDecimator(GazeDataProcessor dataProcessor)
52
        {
53
            outputFrequency = dataProcessor.OutputFrequency;
54
            SetupTimer();
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
        }
        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;
        }

79
        private void SetupTimer()
80
        {
81 82 83
            timer?.Stop();
            timer?.Dispose();
            timer = new Timer(1000.0 / outputFrequency);
84 85 86 87 88 89 90 91 92 93 94
            timer.Elapsed += (Object sender, ElapsedEventArgs e) =>
            {
                if (ValueCount > 0)
                {
                    OutputAvailable?.Invoke(Output, this);
                    Reset();
                }
            };
            timer.AutoReset = true;
            timer.Start();
        }
95 96 97 98

        public void Update(GazeDataProcessor dataProcessor)
        {
            outputFrequency = dataProcessor.OutputFrequency;
99
            SetupTimer();
100
        }
101 102
    }
}