GazeDecimator.cs 2.36 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 17
        private readonly Object outputLock = new Object();
        private readonly Object valueCountLock = new Object();
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
        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;
                }
            }
        }

50
        public GazeDecimator(Single outputFrequency)
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
        {
            this.outputFrequency = outputFrequency;
            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();
        }
    }
}