{"id":10,"date":"2020-06-04T07:41:49","date_gmt":"2020-06-04T07:41:49","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=10"},"modified":"2020-07-09T18:43:36","modified_gmt":"2020-07-09T18:43:36","slug":"jitterex-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2020\/06\/04\/jitterex-cs\/","title":{"rendered":"JitterEx.cs"},"content":{"rendered":"\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/#define TEST\nusing System;\nusing System.Diagnostics;\nusing System.Management;\nusing System.Runtime.CompilerServices;\nusing System.Threading;\n[Serializable]\npublic class JitterEx\n{\n    private const    int    DesaturationLoopLimit = 500;\n    private const    int    UpperCpuLoadLimit     = 90;\n    private const    int    LowerCpuLoadLimit     = 10;\n    private static   bool   _scaleSet;\n    private readonly int    _bufferSize;\n    private readonly object _lock = new object();\n    private readonly Random _prng;\n    private          byte[] _rngCache;\n    private          int    _tscLoopLimitCpu  = 10;\n    private          int    _tscSampleSizeRam = 18;\n    public JitterEx(int buffersize, bool randomize = false)\n    {\n        _bufferSize = buffersize;\n        _rngCache   = new byte[_bufferSize];\n        _prng       = new Random();\n        Randomize   = randomize;\n        SetScale();\n    }\n    public bool Randomize\n    {\n        get;\n        set;\n    }\n#if TEST\n    public void TestListF()\n    {\n        var rlst = new List&lt;List&lt;(byte[], int)>>();\n        for (var i = 0; i &lt; TestList.Count; i++)\n        {\n            var f = TestList[i];\n            for (var j = i + 1; j &lt; TestList.Count; j++)\n            {\n                var s = TestList[j];\n                rlst.Add(new BMPartialPatternSearch(3).SearchPartialAll(f, s));\n            }\n        }\n    }\n#endif\n    [MethodImpl(MethodImplOptions.NoOptimization)]\n    private float GetCpuSpeed()\n    {\n        void Loop()\n        {\n            var i = 0;\n            while (true)\n                i = i + 1 - 1;\n        }\n        var cpuCounter = new PerformanceCounter(\"Processor Information\", \"% Processor Performance\", \"_Total\");\n        var cpuValue   = cpuCounter.NextValue();\n        var loop       = new Thread(() => Loop()) {Priority = ThreadPriority.Highest};\n        var Speed      = 0f;\n        lock (_lock)\n        {\n            loop.Start();\n            Thread.Sleep(60);\n            cpuValue = cpuCounter.NextValue();\n            loop.Abort();\n        }\n        foreach (ManagementObject obj in new ManagementObjectSearcher(\"SELECT *, Name FROM Win32_Processor\").Get())\n        {\n            var v = Convert.ToSingle(obj[\"MaxClockSpeed\"]);\n            Speed = v \/ 1000 * cpuValue \/ 100;\n        }\n        return Speed;\n    }\n    \/\/\/ &lt;summary>\n    \/\/\/     This is a fairly arbitrary value which is based on the CPU speed. 4.7 is the speed on which the tests are based.\n    \/\/\/ &lt;\/summary>\n    private void SetScale()\n    {\n        if (_scaleSet)\n            return;\n        _scaleSet = true;\n        const float baseFreq = 4.7f;\n        var         thisFreq = GetCpuSpeed();\n        var         rat      = baseFreq \/ thisFreq;\n        _tscLoopLimitCpu  = (int) Math.Ceiling(_tscLoopLimitCpu  * rat);\n        _tscSampleSizeRam = (int) Math.Ceiling(_tscSampleSizeRam * rat);\n    }\n    private void LoadBlock()\n    {\n        var DesaturationLoops = 0;\n        var dump              = CpuTotalPc.CPULoad;\n        do\n        {\n            Thread.Sleep(0);\n            DesaturationLoops++;\n        } while (DesaturationLoops &lt; DesaturationLoopLimit &amp;&amp; ((int) CpuTotalPc.CPULoad > UpperCpuLoadLimit || (int) CpuTotalPc.CPULoad &lt; LowerCpuLoadLimit));\n    }\n    [MethodImpl(MethodImplOptions.NoInlining)]\n    private byte[] GetBufferCpu()\n    {\n        void Loop()\n        {\n            var x = 0;\n            for (var i = 0; i &lt; _tscLoopLimitCpu; i++)\n                x = x + 1 - 1;\n        }\n        var jitterBuffer = new byte[_bufferSize];\n        var ptr          = 0;\n        LoadBlock();\n        lock (_lock)\n        {\n            var start = Rdtsc.TimestampP();\n            do\n            {\n                var loop = new Thread(() => Loop()) {Priority = ThreadPriority.Highest};\n                loop.Start();\n                loop.Join();\n                var stop = Rdtsc.TimestampP();\n                Buffer.BlockCopy((100000.0 \/ ((stop - start) * 100000.0)).GetBytes(), 0, jitterBuffer, ptr, 4);\n                start =  stop;\n                ptr   += 4;\n            } while (ptr &lt; _bufferSize);\n            return jitterBuffer;\n        }\n    }\n    [MethodImpl(MethodImplOptions.NoInlining)]\n    private unsafe byte[] GetBufferRam()\n    {\n        void Loop()\n        {\n            byte tempByte;\n            fixed (byte* p1 = _rngCache)\n            {\n                var x1 = p1;\n                for (var j = 0; j &lt; _tscSampleSizeRam; ++j, ++x1)\n                    tempByte = *x1;\n            }\n        }\n        LoadBlock();\n        var jitterBuffer = new byte[_bufferSize];\n        lock (_lock)\n        {\n            if (_rngCache.Length != _bufferSize)\n                _rngCache = new byte[_bufferSize];\n            _prng.NextBytes(_rngCache);\n            var ptr   = 0;\n            var start = Rdtsc.TimestampP();\n            while (true)\n            {\n                do\n                {\n                    var loop = new Thread(() => Loop()) {Priority = ThreadPriority.Highest};\n                    loop.Start();\n                    loop.Join();\n                    var stop = Rdtsc.TimestampP();\n                    Buffer.BlockCopy((100000.0 \/ ((stop - start) * 100000.0)).GetBytes(), 0, jitterBuffer, ptr, 4);\n                    start =  stop;\n                    ptr   += 4;\n                    if (ptr &lt; _bufferSize)\n                    {\n                        if (_rngCache.Length != _bufferSize)\n                            _rngCache = new byte[_bufferSize];\n                        _prng.NextBytes(_rngCache);\n                    }\n                } while (ptr &lt; _bufferSize);\n                return jitterBuffer;\n            }\n        }\n    }\n    public byte[] GetBuffer()\n    {\n        var firstBuffer = GetBufferCpu();\n#if TEST\n        \/\/\/Weighting add 15%, perfection is not what we are looking for here.\n        var lim = _bufferSize &lt;= 256 ? _bufferSize \/ 256.0 * 85.0 : 6.8;\n        if (ent.Entropy(firstBuffer) &lt; lim)\n            throw new Exception(\"Error CPU Jitter Buffer Contains only zeros.\");\n#endif\n        var secondBuffer = GetBufferRam();\n#if TEST\n        if (ent.Entropy(secondBuffer) &lt; lim)\n            throw new Exception(\"Error CPU Jitter Buffer Contains only zeros.\");\n#endif\n        var finalBuffer = new byte[_bufferSize];\n        for (var j = 0; j &lt; _bufferSize; ++j)\n            finalBuffer[j] = (byte) (firstBuffer[j] ^ secondBuffer[j]);\n#if TEST\n        if (ent.Entropy(finalBuffer) &lt; lim)\n            throw new Exception(\"Error CPU Jitter Buffer Contains only zeros.\");\n#endif\n        if (Randomize)\n        {\n            var ula    = CreateNoiseArrays(finalBuffer);\n            var rBlock = new byte[ula.Length * 8];\n            Buffer.BlockCopy(ula, 0, rBlock, 0, ula.Length * 8);\n#if TEST\n            if (_bufferSize >= 256)\n            {\n                var loop = new Thread(() =>\n                {\n                    if (!rBlock.ChiSquaredTest().isRandom)\n                        MessageBoxEx.Show(\"Warning\", \"Block not random.\", MessageBoxExButtons.OK, MessageBoxExIcon.Warning);\n                }) {Priority = ThreadPriority.Highest};\n                loop.Start();\n            }\n            TestList.Add(rBlock);\n#endif\n            return rBlock;\n        }\n#if TEST\n        if (_bufferSize >= 256)\n        {\n            var loop = new Thread(() =>\n            {\n                if (!finalBuffer.ChiSquaredTest().isRandom)\n                    MessageBoxEx.Show(\"Warning\", \"Block not random.\", MessageBoxExButtons.OK, MessageBoxExIcon.Warning);\n            }) {Priority = ThreadPriority.Highest};\n            loop.Start();\n        }\n        TestList.Add(finalBuffer);\n#endif\n        return finalBuffer;\n    }\n    private ulong[] ByteArrayToULongArray(byte[] ba, int finalSize)\n    {\n        var minSize = ba.Length \/ 8;\n        if (finalSize &lt; minSize)\n            finalSize = minSize;\n        ba = PadULong(ba);\n        var result = new ulong[finalSize];\n        for (var i = 0; i &lt; ba.Length; i += 8)\n            Buffer.BlockCopy(ba, i, result, i, 8);\n        return result;\n    }\n    private static byte[] PadULong(byte[] ba)\n    {\n        var s = ba.Length % 8;\n        switch (s)\n        {\n            case 0:\n                break;\n            case 1:\n                Array.Resize(ref ba, ba.Length + 7);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                ba[ba.Length - 3] = 0x80;\n                ba[ba.Length - 4] = 0x80;\n                ba[ba.Length - 5] = 0x80;\n                ba[ba.Length - 6] = 0x80;\n                ba[ba.Length - 7] = 0x80;\n                break;\n            case 2:\n                Array.Resize(ref ba, ba.Length + 6);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                ba[ba.Length - 3] = 0x80;\n                ba[ba.Length - 4] = 0x80;\n                ba[ba.Length - 5] = 0x80;\n                ba[ba.Length - 6] = 0x80;\n                break;\n            case 3:\n                Array.Resize(ref ba, ba.Length + 5);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                ba[ba.Length - 3] = 0x80;\n                ba[ba.Length - 4] = 0x80;\n                ba[ba.Length - 5] = 0x80;\n                break;\n            case 4:\n                Array.Resize(ref ba, ba.Length + 4);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                ba[ba.Length - 3] = 0x80;\n                ba[ba.Length - 4] = 0x80;\n                break;\n            case 5:\n                Array.Resize(ref ba, ba.Length + 3);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                ba[ba.Length - 3] = 0x80;\n                break;\n            case 6:\n                Array.Resize(ref ba, ba.Length + 2);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                break;\n            case 7:\n                Array.Resize(ref ba, ba.Length + 1);\n                ba[ba.Length - 1] = 0x80;\n                break;\n        }\n        return ba;\n    }\n    private static void Extrude(ulong[] x)\n    {\n        var size = x.Length;\n        for (var i = 0; i &lt; size; i++)\n        {\n            ulong n = 0;\n            var   j = 0;\n            while (j &lt; size)\n            {\n                n ^= x[j];\n                ++j;\n            }\n            x[i] = (n &lt;&lt; 1) | (n >> 56);\n        }\n    }\n    private ulong[] CreateNoiseArrays(byte[] ba)\n    {\n        var ula = ByteArrayToULongArray(ba, ba.Length \/ 8);\n        Extrude(ula);\n        return ula;\n    }\n    internal class EntropyI\n    {\n        private const double NaturalLogOfTwo = 0.69314718055994530941723212145818; \/\/Math.Log(2);\n        \/\/\/ &lt;summary>\n        \/\/\/     Get the Entropy from 1 to 100% 1 being very ordered data,\n        \/\/\/     100% being very disordered data.\n        \/\/\/ &lt;\/summary>\n        public double Entropy(byte[] a)\n        {\n            var h = new int[256];\n            var l = a.Length;\n            for (var i = 0; i &lt; l; ++i)\n                h[a[i]]++;\n            var e = 0.0;\n            for (var i = 0; i &lt; 256; ++i)\n            {\n                var v = h[i];\n                if (v &lt;= 0)\n                    continue;\n                var r = v             \/ (double) l;\n                e -= r * (Math.Log(r) \/ NaturalLogOfTwo);\n            }\n            return e \/ 8.0 * 100.0;\n        }\n    }\n#if TEST\n    private EntropyI     ent = new EntropyI();\n    private List&lt;byte[]> TestList = new List&lt;byte[]>();\n#endif\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[15,40,41,37],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/10"}],"collection":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/comments?post=10"}],"version-history":[{"count":5,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/10\/revisions"}],"predecessor-version":[{"id":107,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/10\/revisions\/107"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=10"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=10"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=10"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}