2013/01/05(Sat)いろんなとけい

はてブ数 2013/01/05 1:13 プログラミング::C# つーさ

今日のアウトプット。
C#でいろんな時計をつくってみる。

using System;
using System.Collections.Generic;
using System.Text;

namespace Tsukikage.GameSDK.Util
{
    public interface IReferenceClock : IDisposable
    {
        void Initialize();
        double GetCurrentTime();
    }

    public class StopwatchClock : IReferenceClock
    {
        System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
        public void Initialize() { stopwatch.Start(); }
        public double GetCurrentTime() { return stopwatch.Elapsed.TotalMilliseconds; }
        public void Dispose() { GC.SuppressFinalize(this); }
    }

    public class DateTimeClock : IReferenceClock
    {
        DateTime start = DateTime.Now;
        public void Initialize() { this.start = DateTime.Now; }
        public double GetCurrentTime() { return (DateTime.Now - this.start).TotalMilliseconds; }
        public void Dispose() { GC.SuppressFinalize(this); }
    }

    public class TimeGetTimeClock : IReferenceClock
    {
        int start = 0;
        public void Initialize() { timeBeginPeriod(1); start = timeGetTime(); }
        public double GetCurrentTime() { return timeGetTime() - start; }
        public void Dispose() { GC.SuppressFinalize(this); }

        [System.Runtime.InteropServices.DllImport("winmm", EntryPoint = "timeBeginPeriod")]
        [System.Security.SuppressUnmanagedCodeSecurity]
        static extern int timeBeginPeriod(int p);

        [System.Runtime.InteropServices.DllImport("winmm", EntryPoint = "timeGetTime")]
        [System.Security.SuppressUnmanagedCodeSecurity]
        static extern int timeGetTime();
    }

    public class QueryPerformanceCounterClock : IReferenceClock
    {
        long start = 0L;
        long freq = 1L;

        public void Initialize()
        {
            QueryPerformanceFrequency(out freq);
            QueryPerformanceCounter(out start);
        }

        public double GetCurrentTime()
        {
            long cur;
            QueryPerformanceCounter(out cur);
            return ((cur - start) * 1000.0 / freq);
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        [System.Security.SuppressUnmanagedCodeSecurity]
        extern static short QueryPerformanceCounter(out long x);

        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        [System.Security.SuppressUnmanagedCodeSecurity]
        extern static short QueryPerformanceFrequency(out long x);
    }

    public class AudioDeviceClock : IReferenceClock
    {
        Tsukikage.Audio.AudioDevice audioDevice;
        Tsukikage.Audio.IAudioBuffer buffer;
        System.Threading.ManualResetEvent disposed;
        System.Threading.Thread thread;
        int trigCount;

        public AudioDeviceClock(Tsukikage.Audio.AudioDevice device)
        {
            this.audioDevice = device;
        }

        public void Initialize()
        {
            trigCount = 0;

            int freq = 44100, ch = 1, bps = 16;

            // 1 sec empty audio buffer
            buffer = audioDevice.CreateBuffer(freq, ch, bps, freq * ch * bps / 8);
            buffer.Play(true);

            this.disposed = new System.Threading.ManualResetEvent(false);
            this.thread = new System.Threading.Thread(() =>
            {
                bool prev = true;
                while (!disposed.WaitOne(100))
                {
                    // pata pata pata ...
                    bool cur = buffer.PlayPosition < buffer.Length / 2;
                    if ((!prev && cur) || (prev && !cur)) { prev ^= true; trigCount++; }
                }
            });
            this.thread.Priority = System.Threading.ThreadPriority.Highest;
            this.thread.Start();
        }

        public double GetCurrentTime()
        {
            int curPos = buffer.PlayPosition;
            int bufOrign = curPos < buffer.Length / 2 ? trigCount + 1 & ~1 : trigCount & ~1;
            return bufOrign * 500 + curPos / (buffer.Length / 1000.0); // in millisecond
        }

        public void Dispose()
        {
            if (thread != null)
            {
                disposed.Set();
                thread.Join();
                disposed.Close();
                disposed = null;
                thread = null;
            }

            if (buffer != null)
            {
                buffer.Dispose();
                buffer = null;
            }

            GC.SuppressFinalize(this);
        }
    }
}