From 4520762a720926d87723e0250119f0061a0169cb Mon Sep 17 00:00:00 2001 From: chudov Date: Tue, 15 Nov 2011 10:56:49 +0000 Subject: [PATCH] CTDB 2.0 --- CUETools.AVX/CUETools.AVX.c | 618 ++++++++++++++++++ CUETools.AVX/CUETools.AVX.vcxproj | 133 ++++ CUETools.AccurateRip/AccurateRip.cs | 167 ++--- CUETools.AccurateRip/CDRepair.cs | 331 +++++----- CUETools.CDImage/CDImage.cs | 2 +- .../CUETools.CTDB.Converter.csproj | 73 +++ CUETools.CTDB.Converter/Program.cs | 237 +++++++ .../Properties/AssemblyInfo.cs | 36 + CUETools.CTDB.EACPlugin/Plugin.cs | 27 +- CUETools.CTDB/CTDBResponseEntry.cs | 4 + CUETools.CTDB/CTDBSubmitResponse.cs | 28 + CUETools.CTDB/CUETools.CTDB.csproj | 3 +- CUETools.CTDB/CUEToolsDB.cs | 504 +++++++------- CUETools.CTDB/DBEntry.cs | 36 +- CUETools.CTDB/DBHDR.cs | 63 -- CUETools.CTDB/ReadDB.cs | 47 -- CUETools.Codecs.ALAC/ALACWriter.cs | 143 +++- .../CUETools.Codecs.FLAC.vcxproj | 1 + CUETools.Parity/Parity2Syndrome.cs | 53 +- CUETools.Parity/RsDecode.cs | Bin 22680 -> 28946 bytes CUETools.Processor/CUESheet.cs | 21 +- .../NoiseAndErrorsGenerator.cs | 13 +- CUETools.TestHelpers/TestImageGenerator.cs | 24 +- .../CUETools.TestParity/CDRepairDecodeTest.cs | 132 ++-- CUETools/localtestrun.testrunconfig | 42 +- 25 files changed, 1958 insertions(+), 780 deletions(-) create mode 100644 CUETools.AVX/CUETools.AVX.c create mode 100644 CUETools.AVX/CUETools.AVX.vcxproj create mode 100644 CUETools.CTDB.Converter/CUETools.CTDB.Converter.csproj create mode 100644 CUETools.CTDB.Converter/Program.cs create mode 100644 CUETools.CTDB.Converter/Properties/AssemblyInfo.cs create mode 100644 CUETools.CTDB/CTDBSubmitResponse.cs delete mode 100644 CUETools.CTDB/DBHDR.cs delete mode 100644 CUETools.CTDB/ReadDB.cs diff --git a/CUETools.AVX/CUETools.AVX.c b/CUETools.AVX/CUETools.AVX.c new file mode 100644 index 0000000..b77b30b --- /dev/null +++ b/CUETools.AVX/CUETools.AVX.c @@ -0,0 +1,618 @@ +#include +#include + +int __stdcall _DllMainCRTStartup(void *hModule, + unsigned long ul_reason_for_call, + void* lpReserved) +{ + (void) hModule; + (void) ul_reason_for_call; + (void) lpReserved; + return 1; +} + +__declspec(dllexport) void __stdcall SyndromeCalc16(uint16_t *table, uint16_t *parity_base, uint16_t* samples, int n) +{ + const int npar = 16; + int i; + for (i = 0; i < n; i++) + { + uint16_t* parity = parity_base + i * npar; + uint16_t wrlo = parity[0] ^ samples[i]; + uint16_t* ptiblo0 = table + (wrlo & 255) * npar * 2; + uint16_t* ptiblo1 = table + (wrlo >> 8) * npar * 2 + npar; + ((uint64_t*)parity)[0] = ((uint64_t*)(parity + 1))[0] ^ ((uint64_t*)ptiblo0)[0] ^ ((uint64_t*)ptiblo1)[0]; + ((uint64_t*)parity)[1] = ((uint64_t*)(parity + 1))[1] ^ ((uint64_t*)ptiblo0)[1] ^ ((uint64_t*)ptiblo1)[1]; + ((uint64_t*)parity)[2] = ((uint64_t*)(parity + 1))[2] ^ ((uint64_t*)ptiblo0)[2] ^ ((uint64_t*)ptiblo1)[2]; + ((uint64_t*)parity)[3] = (((uint64_t*)(parity))[3] >> 16) ^ ((uint64_t*)ptiblo0)[3] ^ ((uint64_t*)ptiblo1)[3]; + } +} + +uint16_t encodeTable[]; + +__declspec(dllexport) void __stdcall SyndromeCalc16AVX(uint16_t *table, uint16_t *parity_base, uint16_t* samples, int n) +{ + const int npar = 16; + int i; + for (i = 0; i < n; i++) + { + uint16_t* parity = parity_base + i * npar; + __m256i temp0 = _mm256_loadu_si256((__m256i*)(parity + 1)); + uint16_t wrlo = parity[0] ^ samples[i]; + uint16_t* ptiblo0 = encodeTable + (wrlo & 255) * npar * 2; + uint16_t* ptiblo1 = encodeTable + (wrlo >> 8) * npar * 2 + npar; + __m256 temp1 = _mm256_load_ps((float*)ptiblo0); + __m256 temp2 = _mm256_load_ps((float*)ptiblo1); + temp0.m256i_i16[npar-1] = 0; + temp1 = _mm256_xor_ps(_mm256_castsi256_ps(temp0), _mm256_xor_ps(temp1, temp2)); + _mm256_storeu_ps((float*)parity, temp1); + //_mm256_stream_ps((float*)parity, temp1); + } + _mm256_zeroupper(); +} + +__declspec(dllexport) void __stdcall SyndromeCalc16AVX1(uint16_t *table, uint16_t *parity_base, uint16_t* samples, int n) +{ + const int npar = 16; + int i; + for (i = 0; i < n; i++) + { + uint16_t* parity = parity_base + i * npar; + __m128i lo = _mm_loadu_si128((__m128i*)parity); + __m128i hi = _mm_loadu_si128(1 + (__m128i*)parity); + uint16_t wrlo = lo.m128i_u16[0] ^ samples[i]; + __m256 temp0, temp1, temp2; + lo = _mm_srli_si128(lo, 2); + lo.m128i_u16[7] = hi.m128i_u16[0]; + hi = _mm_srli_si128(hi, 2); + temp0 = _mm256_castsi256_ps(_mm256_insertf128_si256(_mm256_castsi128_si256(lo), hi, 1)); + temp1 = _mm256_load_ps((float*)(encodeTable + (wrlo & 255) * npar * 2)); + temp2 = _mm256_load_ps((float*)(encodeTable + (wrlo >> 8) * npar * 2 + npar)); + temp1 = _mm256_xor_ps(temp0, _mm256_xor_ps(temp1, temp2)); + _mm256_storeu_ps((float*)parity, temp1); + //_mm256_stream_ps((float*)parity, temp1); + } + _mm256_zeroupper(); +} + +//__declspec(dllexport) void SyndromeCalc16AVX(uint16_t *table, uint16_t *parity, uint16_t sample) +//{ +// const int npar = 16; +// uint16_t wrlo = parity[0] ^ sample; +// uint16_t* ptiblo0 = table + (wrlo & 255) * npar * 2; +// uint16_t* ptiblo1 = table + (wrlo >> 8) * npar * 2 + npar; +// +// //__m128i lo = _mm_loadu_si128((__m128i*)parity); +// //__m128i hi = _mm_loadu_si128(1 + (__m128i*)parity); +// //_mm_srli_si128(lo, 2); +// //_mm_srli_si128(hi, 2); +// __m256 temp = _mm256_load_ps((float*)(parity + 1)); +// //__m256i temp0 = _mm256_loadu_si256((__m256i*)(parity)); +// ////__m256 temp = _mm256_castsi256_ps(temp0); +// //__m256 temp = _mm256_castsi256_ps(_mm256_set_epi16( +// // temp0.m256i_i16[1], temp0.m256i_i16[2],temp0.m256i_i16[3],temp0.m256i_i16[4],temp0.m256i_i16[5],temp0.m256i_i16[6],temp0.m256i_i16[7], temp0.m256i_i16[8], +// // temp0.m256i_i16[9], temp0.m256i_i16[10],temp0.m256i_i16[11],temp0.m256i_i16[12],temp0.m256i_i16[13],temp0.m256i_i16[14],temp0.m256i_i16[15], 0)); +// __m256 temp1 = _mm256_load_ps((float*)ptiblo0); +// __m256 temp2 = _mm256_load_ps((float*)ptiblo1); +// temp = _mm256_xor_ps(temp, temp1); +// temp = _mm256_xor_ps(temp, temp2); +// _mm256_store_ps((float*)parity, temp); //_mm256_stream_si256 +// _mm256_zeroupper(); +//} + + +uint16_t encodeTable[] = +{ +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0xFFFF, 0xA7BD, 0x7206, 0xE9CF, 0xEB10, 0x709D, 0xA8D4, 0xD52A, 0x8879, 0x810F, 0xCFB3, 0xF669, 0x5ABA, 0x2F8D, 0x47D5, 0x27B7, +0xF990, 0x699F, 0x5537, 0xB911, 0x4607, 0xEE21, 0xF0F6, 0xADA8, 0x7C80, 0x9AD3, 0x845D, 0xFFC3, 0x4819, 0x5C1F, 0xE7DD, 0xE647, +0xEFF5, 0x5F71, 0xE40C, 0xC395, 0xC62B, 0xE13A, 0x41A3, 0xBA5F, 0x00F9, 0x1215, 0x8F6D, 0xFCD9, 0xB574, 0x5F1A, 0x8FAA, 0x4F6E, +0xE32B, 0xD33E, 0xAA6E, 0x6229, 0x8C0E, 0xCC49, 0xF1E7, 0x4B5B, 0xF900, 0x25AD, 0x18B1, 0xEF8D, 0x9032, 0xB83E, 0xDFB1, 0xDC85, +0x100A, 0xF8CC, 0x960A, 0x2A5A, 0x2D3B, 0x91A7, 0xE977, 0x6F75, 0x8880, 0x931A, 0x40DE, 0x0AB0, 0xEFCE, 0x7097, 0xC87F, 0x68D9, +0x1ABB, 0xBAA1, 0xFF59, 0xDB38, 0xCA09, 0x2268, 0x0111, 0xE6F3, 0x8580, 0xBF7E, 0x9CEC, 0x104E, 0xD82B, 0xE421, 0x386C, 0x3AC2, +0xCFE1, 0xBEE2, 0xD813, 0x9721, 0x9C5D, 0xD27F, 0x8346, 0x64B5, 0x01F2, 0x242A, 0x0ED1, 0xE9B9, 0x7AE3, 0xBE34, 0x0F5F, 0x9EDC, +0xD65D, 0xB677, 0x44D7, 0xC452, 0x0817, 0x8899, 0xF3C5, 0x96B6, 0xE20B, 0x4B5A, 0x3162, 0xCF11, 0x306F, 0x6077, 0xAF69, 0xA901, +0x301E, 0x195F, 0xAA15, 0x7EEE, 0x774D, 0xA2E2, 0x2B92, 0xB19F, 0x898B, 0xA525, 0xC162, 0x1FD0, 0x2059, 0x91B9, 0x488A, 0xB96B, +0x2FCD, 0xDFE8, 0x11E0, 0x7D43, 0x4E10, 0x66B8, 0x0333, 0x3B1E, 0x9E8B, 0xD189, 0xB53F, 0x30D2, 0x7876, 0x3C68, 0x48B4, 0x4F46, +0x2014, 0xE193, 0x3C1F, 0x54B4, 0x5A76, 0x3345, 0xC2E5, 0xDEEA, 0x010B, 0x363F, 0x81BC, 0x1560, 0xCF97, 0xE12E, 0x80F5, 0xD1B2, +0x3576, 0x6549, 0xEEB9, 0xA67B, 0x8419, 0x44D0, 0x0222, 0xDDED, 0x1B0B, 0x6EF7, 0x29D3, 0x209C, 0xA05D, 0xD849, 0x70D8, 0x7584, +0xDFEB, 0x462E, 0x4E19, 0xBD7B, 0xB166, 0x43D8, 0x6A31, 0x0BC0, 0x8972, 0xB730, 0x4E0F, 0xE309, 0x952D, 0xCEA3, 0xC720, 0xF605, +0xCCE6, 0x0CD6, 0xBB8E, 0x1F6A, 0xC21E, 0xAAF1, 0xF2D4, 0x7045, 0x678B, 0xF424, 0xAD8E, 0xDF5F, 0xE844, 0x8456, 0x9705, 0x93C3, +0x8FC9, 0x6DCF, 0xA02D, 0x3E49, 0x28B1, 0xB4F5, 0x1687, 0xC96A, 0x03E4, 0x4854, 0x1DA2, 0xC379, 0xF5C6, 0x6C63, 0x1EBE, 0x2DB3, +0xBCB1, 0x7CE5, 0x89AE, 0x98AF, 0x102E, 0x0139, 0xF781, 0x3D67, 0xD41D, 0x96B4, 0x62C4, 0x8E29, 0x60DE, 0xC0EE, 0x4ED9, 0x4209, +0x7036, 0xCA72, 0xD22B, 0xD786, 0xC3A1, 0xC468, 0xBE53, 0x1C40, 0x8B9D, 0xC95B, 0xD211, 0x3510, 0xAF7C, 0x43EE, 0x596B, 0x0A04, +0x4521, 0x157A, 0xDC99, 0x21BE, 0x5629, 0xEF18, 0x0777, 0x90CF, 0xA89D, 0x0C67, 0xE699, 0x71EA, 0x28C7, 0x9CF1, 0xA904, 0xA44E, +0x603C, 0x32BE, 0x4421, 0xFDDC, 0xEE9A, 0x55CF, 0x5724, 0x7335, 0x031D, 0x5A41, 0x92CF, 0x3FA0, 0x40B2, 0x3379, 0x9114, 0x62DD, +0x5F9A, 0xAFDB, 0x23C0, 0xFA86, 0x9C20, 0xCD70, 0x0666, 0x763C, 0x2D1D, 0xB319, 0x7A75, 0x61A4, 0xF0EC, 0x78D0, 0x9168, 0x9E8C, +0x9FC3, 0x9503, 0x3627, 0x1413, 0x058A, 0x2552, 0xFFF0, 0xA61F, 0x8B64, 0xDB4E, 0x5D7C, 0xC9C9, 0x1A08, 0x1CF4, 0xD6C1, 0x456A, +0xA60A, 0xC644, 0x76F7, 0x4397, 0xDA27, 0x2351, 0xF690, 0xDB94, 0x519D, 0x29CA, 0xFE28, 0x9E67, 0xB8F5, 0x24CF, 0x76B5, 0x78CB, +0x4028, 0xD32D, 0x783E, 0xA968, 0xB4EC, 0x668A, 0x95C1, 0xADDF, 0x0216, 0x6C7E, 0x1373, 0x2AC0, 0x8F25, 0xD257, 0x11E1, 0xB36F, +0x6AEC, 0xCA92, 0xCD79, 0x5CFD, 0x1839, 0x89A0, 0x0444, 0xABD1, 0x3616, 0xDDEE, 0x53A6, 0x4138, 0x50B1, 0xA099, 0xE1B0, 0xEB08, +0xBFD7, 0x7490, 0x0A38, 0x40A7, 0x5FFC, 0x1617, 0x3D15, 0x78F5, 0x8A6F, 0xED71, 0xDCC0, 0xDCA9, 0xD59F, 0xFDDA, 0x5634, 0x94D8, +0x937C, 0xA30D, 0x984E, 0xE5EC, 0x5E3E, 0x6781, 0xF4B2, 0x0679, 0x4A96, 0x473D, 0xD7FB, 0xBEFB, 0x18A8, 0xFC86, 0x066D, 0x0D4F, +0xAFDD, 0x8C5C, 0x9C32, 0x6AFD, 0x72C7, 0x87B0, 0xD462, 0x1780, 0x02EF, 0x7E6B, 0x9C1E, 0xD619, 0x3A51, 0x8D4D, 0x9E4B, 0xFC01, +0x89C7, 0x19AC, 0x6717, 0x3ED4, 0x9437, 0x45E9, 0xF5A3, 0xE08A, 0xCF16, 0xF843, 0x4B17, 0xAEB5, 0xC083, 0x18A7, 0x3E01, 0x378D, +0x5022, 0x2BE1, 0xEE34, 0x8332, 0x99D7, 0xF72D, 0x7CB6, 0xC2AA, 0x8A96, 0xFF64, 0x53AD, 0x2070, 0x60EB, 0xA2C0, 0xD99E, 0xDBB6, +0x7057, 0x7033, 0x3220, 0x87C5, 0xD230, 0xABC8, 0x0555, 0x4D22, 0xB396, 0x6290, 0xCF4A, 0x5176, 0x889A, 0x44B8, 0xD9DC, 0xD1CA, +0x0F99, 0xDB9E, 0x5051, 0x7C92, 0x5162, 0x79E1, 0x2D0E, 0x82DF, 0x07C8, 0x90A8, 0x3B44, 0x96F9, 0xFB87, 0xD8C6, 0x3D7C, 0x5B66, +0x6969, 0xF9CA, 0x0357, 0x2155, 0x205C, 0x0272, 0xFF09, 0x7ACE, 0xB831, 0x3D63, 0xC588, 0x0C59, 0xC1BC, 0x91D7, 0x9DB2, 0x8412, +0xF066, 0x7C23, 0x2257, 0x955D, 0xBA72, 0x097C, 0x85DA, 0x57F5, 0x8FB1, 0x11A7, 0xF4F7, 0x6090, 0xA13D, 0xF74B, 0x7AA9, 0x7CD1, +0x90F9, 0x9055, 0x5660, 0x9844, 0x665B, 0xEC53, 0x0FFF, 0xD766, 0xC4B1, 0xA7B0, 0x41D5, 0xF39A, 0x89A5, 0xCDC8, 0x7A6F, 0x6255, +0xE06C, 0x84EF, 0xB45D, 0xBF07, 0x9749, 0x98DB, 0x6CAD, 0x3880, 0x0731, 0x82BD, 0xB429, 0x6A20, 0x4EF3, 0x87DC, 0xB2D6, 0x1408, +0x8A42, 0x2AF4, 0xA939, 0x437C, 0xAC52, 0xCE3B, 0x0EEE, 0x3195, 0x4131, 0x18CE, 0xDD39, 0xE3D4, 0x518E, 0x29E9, 0x4203, 0x5897, +0x1F93, 0x2352, 0xC65B, 0x56C8, 0x7C59, 0xE846, 0xC479, 0xEDAA, 0x8F48, 0x03B2, 0x7B9A, 0x9C49, 0x1449, 0xA851, 0xF503, 0x33BF, +0x73D2, 0x436B, 0xFC0E, 0xFA6D, 0xEA55, 0x201A, 0xFE18, 0x9C3D, 0x3DB1, 0x821D, 0x5964, 0x1C17, 0x1997, 0x75F6, 0xA5DE, 0xBED0, +0xC078, 0x657C, 0x8842, 0xEBB3, 0xCD3F, 0xAB9E, 0xAE48, 0xE66A, 0x063A, 0xB482, 0x3595, 0x7F40, 0x8164, 0x66F2, 0x3223, 0xC5BA, +0xBF34, 0x4FBD, 0x4780, 0xE507, 0x284B, 0x8AEB, 0x0CCC, 0xEC78, 0x5A3A, 0x7639, 0xF4EA, 0xC348, 0xF1D3, 0xF1A0, 0x32DB, 0x2D13, +0x3F87, 0xC2C1, 0xFA44, 0x027C, 0x262F, 0xDB03, 0x069C, 0x3340, 0x8E43, 0x358D, 0xFA26, 0x8929, 0xDBDE, 0x497F, 0x75F6, 0xE20D, +0x46A4, 0x2622, 0x12B7, 0x5C16, 0x6E4C, 0x64CA, 0xFC3A, 0x41D0, 0x26BA, 0xECEA, 0x70B7, 0x3C8B, 0xB9CA, 0xADBF, 0xD506, 0xCB54, +0x2F8D, 0x3A0D, 0x6C4E, 0x2826, 0x0B14, 0x4AA4, 0xEFEB, 0x5C35, 0x06C3, 0xA697, 0xBAF8, 0x8399, 0x3410, 0x39E8, 0xBD89, 0x8AD4, +0x5C1F, 0x9C83, 0xEDEE, 0x872E, 0xA445, 0x46A2, 0xFD2B, 0xA723, 0xA33A, 0x5394, 0xEC5B, 0x2CC5, 0x61E1, 0x499E, 0xED6A, 0xF196, +0xD072, 0x9DB0, 0x1E48, 0xC1E9, 0xE004, 0x3A39, 0x473F, 0x891F, 0x8EBA, 0x2798, 0x754B, 0x75F0, 0x6EAA, 0x1665, 0xFA5C, 0xAD63, +0xA58F, 0xF51C, 0xB8D9, 0x3E3F, 0xE242, 0xA883, 0x0DDD, 0x0A8B, 0xDFBA, 0xC947, 0x6806, 0xD306, 0x29F8, 0x1581, 0x0AB7, 0x17D1, +0x8050, 0xB651, 0xF07C, 0x42DB, 0x79D3, 0xCD14, 0x3B89, 0x4BB5, 0x042C, 0xD8FC, 0x26E6, 0x5580, 0x0E41, 0xB4A5, 0x23C2, 0x76D5, +0xD5D8, 0x852F, 0x8AF9, 0xB9FA, 0x3072, 0x034B, 0x0888, 0x47A9, 0x6C2C, 0xABD7, 0xA74C, 0x8270, 0xA162, 0x5139, 0xD36B, 0xC61B, +0x7FAF, 0x11EC, 0x827A, 0xAB14, 0x92C3, 0xBD89, 0x935D, 0x9E9F, 0x8C55, 0x59F3, 0xE955, 0xA3E9, 0x54FB, 0x9B28, 0x6417, 0x5162, +0x2C48, 0xECB0, 0xDFCE, 0x00EB, 0x7675, 0xED6A, 0xF87E, 0xEA01, 0x10AC, 0x3104, 0x2311, 0x7DB3, 0xE97B, 0x0D26, 0x34B6, 0x205C, +0x6FA5, 0xE920, 0x1470, 0x814E, 0xBFF8, 0x2C2E, 0x7A2A, 0xF1EA, 0x04D5, 0xCAE9, 0xA98B, 0xA959, 0xBB35, 0xEBBF, 0xAC68, 0x39BB, +0x36F3, 0x5611, 0x2097, 0xDBD3, 0xBC7C, 0xCF02, 0xF96F, 0x0CF2, 0x952C, 0x8E7A, 0xBFFD, 0x6DFD, 0x3150, 0xE907, 0x0CDA, 0x1A9E, +0x905A, 0x4E9D, 0x6676, 0x6881, 0x54E8, 0x5CB3, 0xD2FE, 0x24C0, 0x8CAC, 0x4BE6, 0x6638, 0x5F30, 0xE18F, 0xC432, 0xEBBD, 0x1E0C, +0xCF63, 0x3F8E, 0x75A0, 0x62C2, 0xFA7B, 0x2123, 0x0999, 0xA15A, 0xE9AC, 0x14A9, 0x3BA0, 0x923E, 0x7949, 0xB518, 0xEB07, 0xFCD9, +0x4FB1, 0x08B3, 0x286F, 0xD5FA, 0xE58E, 0x1F6B, 0xB8CF, 0x2F00, 0x05DE, 0xFCD6, 0x2837, 0xBC39, 0x74A2, 0x0A91, 0x2C9D, 0xE809, +0x0385, 0x3358, 0xCE2E, 0x7DA8, 0x3865, 0x8BD2, 0xFB4D, 0xD11F, 0x8E27, 0xE08D, 0x962E, 0x4D61, 0x910D, 0x314E, 0x7C02, 0x6F1A, +0xB04E, 0xAF0E, 0x5A69, 0x3C35, 0x0E9E, 0x6FF6, 0x101B, 0xFA2A, 0x8DA7, 0x7DD9, 0xE784, 0x4A50, 0x2E18, 0x251C, 0x6B48, 0xCFBE, +0xFA15, 0x5AC7, 0x9B19, 0xC4B9, 0x7E62, 0x65F3, 0x0BBB, 0x7CB7, 0xF2A7, 0x7A5E, 0x1273, 0xB2A2, 0xD914, 0x6D51, 0x9BDF, 0x895D, +0xA044, 0x57C2, 0xCC63, 0x166F, 0x23A5, 0xFE51, 0xF96C, 0x955F, 0x0527, 0xEEC3, 0xA75A, 0x40E0, 0xC1D6, 0x558B, 0xA337, 0xA767, +0xE0AE, 0xE066, 0x6440, 0x1F81, 0xB46B, 0x479B, 0x0AAA, 0x9A44, 0x7727, 0xC520, 0x8E9F, 0xA2EC, 0x013F, 0x8970, 0xA3B3, 0xB39F, +0x5FBB, 0xF07F, 0xBE65, 0xFFA0, 0xC8B5, 0x8ECC, 0x51B8, 0x4075, 0x8D5E, 0x6FCC, 0x68E9, 0xB689, 0x9B6C, 0x7A06, 0xE4E2, 0x80D0, +0x193E, 0x89F9, 0x3177, 0xA690, 0xF26C, 0xA9BA, 0xFA5C, 0x37EC, 0x0BA7, 0x5FF3, 0x0AC2, 0x5D2F, 0x4926, 0xD56F, 0x446E, 0x55D8, +0x1F32, 0xA737, 0xA0A2, 0xF924, 0xA2C4, 0xF3C2, 0x5A1C, 0x15B5, 0x0F90, 0x315B, 0x7688, 0x3DF9, 0xE705, 0xA187, 0x7AF8, 0xB6CC, +0xD2D2, 0xE39F, 0x06AE, 0x42AA, 0x40B8, 0x04E4, 0xEE19, 0xF59C, 0x6069, 0x7AC6, 0x9B1B, 0x18B2, 0x9373, 0x33A5, 0x2B6F, 0x182F, +0xE0CD, 0x008A, 0xD2A4, 0x10EB, 0x49D4, 0x835F, 0xF2C8, 0xC09F, 0x87E9, 0xB054, 0xB93B, 0xCB90, 0xBDBF, 0x8E0A, 0x3D2D, 0x917B, +0x2B42, 0x8A00, 0x5399, 0xFBBB, 0x06BF, 0xEAC5, 0x1EEF, 0x5834, 0x1CE9, 0xE015, 0x1F46, 0xE771, 0xDB6A, 0x6FBA, 0xCCB2, 0xFE68, +0xF0C7, 0xF846, 0x44AE, 0x3AB1, 0x64EF, 0x12F8, 0x1BBF, 0xAFEA, 0x0F69, 0x234E, 0xF9E5, 0xC120, 0x5271, 0xFE9D, 0xF552, 0xF9A2, +0x31F9, 0x30A1, 0xACC0, 0x2083, 0xCCB6, 0xC8AD, 0x1FFE, 0xBEC7, 0x9969, 0x5F6B, 0x83AA, 0xF73F, 0x0341, 0x8B9B, 0xF4DE, 0xC4AA, +0x0F38, 0x5FFB, 0x36A8, 0xD37E, 0x8FFF, 0x6265, 0xB36B, 0x7AC0, 0x8710, 0xA241, 0x3656, 0x3749, 0x08CB, 0xD110, 0xB287, 0xDE15, +0xC869, 0x593E, 0xF9F7, 0x9992, 0x8AB1, 0x268C, 0xEF08, 0x136F, 0xE5E9, 0xC5B8, 0x07F7, 0x08FC, 0x4B58, 0xD784, 0x1303, 0x22ED, +0xD0D3, 0x19D5, 0x78B1, 0x6E05, 0x3E99, 0x21BD, 0xD95A, 0x7100, 0x0E62, 0x1571, 0x7859, 0xD440, 0x9DE6, 0x1FB3, 0x75A7, 0x2810, +0x048F, 0x55E8, 0x4279, 0x86F8, 0x48AF, 0x8C7D, 0x1DDC, 0x632A, 0x8262, 0x319C, 0xAA79, 0xD7A3, 0xA31C, 0x53D2, 0x8406, 0xB12E, +0x2F2C, 0xBE68, 0x0AB7, 0x87CA, 0xD589, 0x5120, 0x718E, 0xA42A, 0x861B, 0x947E, 0xB7EA, 0x2229, 0xC75C, 0x303E, 0x3272, 0x0FA7, +0xFD1F, 0x3C77, 0x174E, 0x3FE9, 0x0EA8, 0x625C, 0xED2A, 0xCE82, 0xFEE2, 0xAB4F, 0x2E24, 0x2860, 0xEB05, 0x0FCD, 0x63DB, 0x5769, +0x3F26, 0x46A4, 0x9CBD, 0xAD90, 0xF8B2, 0xC087, 0x98F9, 0xCB5F, 0x0E9B, 0x0764, 0xF734, 0x2899, 0x2892, 0x40A9, 0xFA0D, 0x677E, +0xE7A4, 0x86D6, 0xE817, 0xE4D1, 0xC4A1, 0x4034, 0xEC3B, 0x2871, 0x7B62, 0x1431, 0xB2C8, 0x382E, 0x332E, 0xEBEC, 0x5BB7, 0x6DAB, +0xC0D9, 0xE119, 0xEEBB, 0x445F, 0x13A2, 0xB01A, 0x302D, 0x1E75, 0x86E2, 0x866B, 0x3887, 0xDEF0, 0x7228, 0x6F24, 0xBDD8, 0x40C9, +0x1E34, 0xEF49, 0xBD20, 0x5DC0, 0x82A6, 0xAE15, 0x1CCD, 0x85D9, 0x07E2, 0x8EE2, 0x3695, 0xC7ED, 0x7B37, 0xB7F3, 0xBC6A, 0x8BEC, +0x90FB, 0xCAF8, 0x008F, 0xC76D, 0x8A75, 0x4737, 0x4C9B, 0xDCDF, 0x0C74, 0x790F, 0x6B2A, 0xFE80, 0x12C3, 0xCDE4, 0x6446, 0x9B7F, +0x6E63, 0x9F7A, 0x8F00, 0xDA05, 0x5096, 0x05DD, 0x1998, 0xC8FB, 0xB474, 0xEC72, 0xF9DF, 0x969B, 0xF3AD, 0xF34B, 0x65B6, 0x5A26, +0x6F04, 0x6D45, 0x7289, 0x2EA2, 0x6165, 0x37AA, 0xE44F, 0x09F5, 0x840D, 0xF800, 0xA499, 0x08E9, 0x4879, 0xE269, 0x2393, 0xBCC8, +0x97F3, 0xF6E5, 0xDA37, 0x6314, 0x1691, 0xEBFC, 0xE96E, 0x6553, 0xC8F4, 0x76A1, 0x7D82, 0x6958, 0xBBB4, 0xAF54, 0x826B, 0xBC61, +0x7F0E, 0x9589, 0xE483, 0x04F8, 0x4C5E, 0xA60D, 0x0D38, 0x6680, 0x0C8D, 0x6B1A, 0xE447, 0x0259, 0xA7B7, 0x92FE, 0xEBEC, 0xD411, +0x8D48, 0x4C44, 0x256E, 0xB82C, 0xDC98, 0xC994, 0xE87F, 0x83A0, 0x4D74, 0xC9DF, 0xE16E, 0x7916, 0x639F, 0x4B75, 0xBA07, 0x86A3, +0x80F1, 0x3234, 0x9685, 0xED37, 0xA74E, 0xD690, 0xA5EC, 0xB3AA, 0x84F4, 0xEA15, 0x2BF4, 0xF430, 0xFD0D, 0xBD73, 0xAC39, 0xF3A6, +0x74D8, 0x25DB, 0x7059, 0x013D, 0x9A9F, 0x27B5, 0x1889, 0x2E08, 0x31F4, 0x530C, 0x6533, 0x86D5, 0x2B86, 0x176A, 0x5DDA, 0x60E4, +0x5F1A, 0x741A, 0xD89C, 0x504C, 0x1628, 0x9548, 0xCFDD, 0xB86A, 0x0D86, 0x5D25, 0x65FB, 0x1739, 0x6820, 0x73D0, 0x6B19, 0x05A3, +0xB83E, 0x290D, 0xCBD7, 0x1E57, 0x5881, 0x8D44, 0xEA5D, 0x5E4D, 0x567F, 0xA728, 0xC8BD, 0x598A, 0xC3C2, 0x933C, 0xCADF, 0xF327, +0xA0E5, 0xD3A7, 0xAA9A, 0xB983, 0xFD38, 0xE5D5, 0x6709, 0x6D40, 0x85FF, 0xDC2A, 0xAA48, 0xE150, 0x329A, 0x5C5D, 0x2CCC, 0x2214, +0x41AE, 0x4092, 0x9EE0, 0xA746, 0x1E86, 0x6365, 0x1AAB, 0xF3E5, 0x2AFF, 0x3DFB, 0x4CE0, 0xA649, 0x8BDB, 0xCF23, 0x2D02, 0x1560, +0xB0EF, 0x2B6B, 0x3C90, 0x93D9, 0xD003, 0x7472, 0x8E7E, 0x0235, 0x0D7F, 0x4F30, 0xEA96, 0xEBE0, 0xDD54, 0x2CCA, 0xE4B3, 0x4ACD, +0x5B15, 0xFA33, 0x61B9, 0x7C7E, 0xD48F, 0x410D, 0x1BBA, 0x1516, 0xAF7F, 0x8285, 0xD00C, 0xB607, 0x53F0, 0x2B02, 0x156E, 0x2FA2, +0x4F10, 0x8CD6, 0x4E96, 0x7A16, 0x3B13, 0x04EF, 0x26AA, 0xD71F, 0x8506, 0xCE3F, 0x2525, 0x1D89, 0x87EE, 0x0347, 0xA366, 0x6D7A, +0xA285, 0x93AC, 0x348E, 0xC56F, 0x9288, 0xAF2C, 0xEB4C, 0xB8BE, 0xD3FF, 0x1856, 0x5451, 0x49C4, 0x1BE9, 0x771D, 0xF2B3, 0xC9E5, +0x10AB, 0x7CA9, 0xF0F3, 0x85B6, 0xF3A6, 0x8A23, 0x7712, 0x976A, 0x0858, 0xA1F3, 0x4DCC, 0xAB00, 0x1C82, 0x7941, 0x4784, 0xEDAA, +0xBBBB, 0x1A55, 0x05F9, 0x63FF, 0x60E4, 0x0696, 0x1110, 0x8F52, 0xD858, 0x47A5, 0x5E93, 0x14EB, 0x52CF, 0xA272, 0xB6DD, 0x9C3D, +0xEF54, 0xDB14, 0x82F5, 0x6C79, 0x18B6, 0xFABE, 0xDFC6, 0x4240, 0x8021, 0x20FC, 0x827F, 0x5D69, 0x4638, 0x56CC, 0x0051, 0xCA1D, +0x422B, 0x73CA, 0x50CE, 0xDAEE, 0x26E3, 0xE8B7, 0xE1E6, 0x22FA, 0xA4D8, 0xDD76, 0xDACE, 0xEB28, 0x1AD6, 0xFE6D, 0x5100, 0x7A7A, +0xFF5E, 0x23D8, 0x14FF, 0x4623, 0x358D, 0x6B19, 0x36B1, 0x2D35, 0x08A1, 0xB3E6, 0xC2A1, 0x57D9, 0xA9F6, 0x265B, 0xC82E, 0xA2C4, +0x5890, 0xC96B, 0xAF97, 0x01D6, 0xECEA, 0xCADF, 0xE0F7, 0xC409, 0x2158, 0x6208, 0x4622, 0xFB66, 0xC2FD, 0x1A4C, 0x696C, 0x40B8, +0x00A1, 0x8465, 0x66F9, 0xAFEC, 0xDE9D, 0x1B84, 0x9E65, 0xF81F, 0x80D8, 0x32E9, 0x0D12, 0xA1B0, 0xF34C, 0x09D6, 0x8FFB, 0x8573, +0xA100, 0xA0F4, 0xFAA0, 0xB8C7, 0xAAED, 0x24FE, 0x1001, 0x69A1, 0x5DD8, 0xF8DB, 0xC27F, 0x04A5, 0x8AE4, 0x4653, 0x8EB1, 0xA6FF, +0xDF4A, 0xC24B, 0x28E0, 0x1297, 0x6FFB, 0x585C, 0xF454, 0xF3DF, 0x09AA, 0x85D9, 0x431D, 0x42B9, 0x6661, 0xC775, 0x48DB, 0x7376, +0x6DE6, 0xAC22, 0x412E, 0xA7AD, 0x68F3, 0x8E0F, 0xE2D5, 0x19E4, 0x3A53, 0x0CFF, 0x6FF1, 0xDBFA, 0x62A0, 0xC205, 0x19B4, 0x353C, +0x20B5, 0x65F6, 0x5AE6, 0xFB58, 0x84EB, 0x28C1, 0x5C80, 0x26F5, 0x81D3, 0x04D6, 0x8CAE, 0xB4D0, 0x3CDB, 0xE8F8, 0x0F0E, 0x54C1, +0x9476, 0xC5BD, 0x1419, 0x1EBC, 0x2EF4, 0x602E, 0x1223, 0xB44C, 0x46D3, 0x962C, 0xEBAC, 0x2439, 0x2AB9, 0x9E1A, 0xFE69, 0xD37B, +0x30BF, 0x9D3A, 0xCCEC, 0xD102, 0xA9D0, 0xB966, 0xB5F7, 0x4980, 0x0953, 0x97CC, 0xCC70, 0xBE60, 0xD315, 0x986F, 0xC771, 0x3C18, +0x8ECD, 0x7F1C, 0xEB40, 0xC584, 0xE4FD, 0x4246, 0x1332, 0x52BF, 0xC353, 0x2952, 0x7740, 0x3477, 0xF292, 0x7A3B, 0xC605, 0xE9B9, +0xCF40, 0x3A87, 0xBEEA, 0x38CD, 0x42C0, 0xC9FB, 0x1D23, 0x9CAA, 0x812A, 0x16C3, 0x03C3, 0x4809, 0x89AF, 0xB7E2, 0x80A4, 0x1BAF, +0x775D, 0x1683, 0xBE77, 0x7C95, 0xA2FA, 0xAC67, 0xE3C4, 0xFF17, 0xBFD3, 0xB381, 0xF31D, 0xCBB4, 0xBA8B, 0x2624, 0x21D8, 0x0FFE, +0x9F62, 0x1166, 0x50DE, 0xBBFF, 0xDB17, 0x3ED6, 0x6195, 0x5E00, 0x0BBC, 0xE9A7, 0x506E, 0x6879, 0xE944, 0x1522, 0x593A, 0xC019, +0x070A, 0x66B0, 0x8C57, 0xFB50, 0x70CA, 0x07AF, 0xE691, 0xB235, 0x0C45, 0xD111, 0x3C57, 0x9AC2, 0x3211, 0x629C, 0xF804, 0xDE34, +0x609D, 0xB6DB, 0x22D8, 0x5230, 0x3007, 0x4E4B, 0xC941, 0x8B2A, 0x83C5, 0x68A8, 0x9FDD, 0x9E10, 0xB3FE, 0x3AAF, 0x1EEF, 0xE7AE, +0xFE9A, 0x0F2F, 0xD960, 0x4241, 0x36CD, 0xE98E, 0x1667, 0x1F9D, 0x70C5, 0x4BC2, 0xB80A, 0x6501, 0x7A08, 0x3E83, 0x1FD9, 0x3873, +0x7097, 0x4E17, 0xB4D2, 0x786A, 0x1D3C, 0xDFEC, 0x2036, 0xE45F, 0x0B45, 0xFBB2, 0xDF03, 0x94A0, 0x5C30, 0x4A38, 0xD690, 0x8F77, +0xE421, 0xB58E, 0x2639, 0x9979, 0xFCC4, 0xCBE6, 0x1776, 0xF96E, 0xF545, 0xF4BC, 0x24E6, 0x754F, 0xA223, 0xDAA2, 0x27B5, 0x02B1, +0x8F68, 0xE9AA, 0xC6D4, 0x91A5, 0xF62C, 0xAF71, 0x88E2, 0x3175, 0x833C, 0x7ABD, 0x10B0, 0x62C9, 0x068A, 0x65B5, 0x9145, 0xA8C0, +0x1DB1, 0xDC11, 0x730E, 0x2068, 0xBAC3, 0x25C7, 0xE780, 0x54C6, 0x89C5, 0x6E6F, 0xA0BB, 0x8A8C, 0xEA3A, 0x86BD, 0xC068, 0xE4F6, +0x5083, 0xAF84, 0x88CD, 0x2CDE, 0x474A, 0xECA9, 0xE2D3, 0x3AB5, 0x0A4E, 0xCD8D, 0x5EBF, 0x81C0, 0x93A7, 0xAB16, 0x5665, 0x5EC5, +0xD157, 0xD0C7, 0xC880, 0x3F02, 0x78DD, 0x8F36, 0x1554, 0x2483, 0xEE4E, 0x9A4B, 0x0D35, 0x55D3, 0x027E, 0x02EB, 0x576D, 0x7735, +0xAF7C, 0x0839, 0xFACB, 0xC511, 0xAC5A, 0x9C34, 0x4A07, 0xEF9F, 0x8237, 0x4C82, 0x910C, 0x77A9, 0xC91D, 0x849B, 0x11B0, 0x7972, +0x28C7, 0xB958, 0x9DB7, 0x8613, 0x3EDA, 0x6117, 0xE5A2, 0x892B, 0x92CE, 0x0098, 0x8968, 0xAA10, 0x4A67, 0x5EF4, 0xB0B0, 0x9172, +0xBF76, 0xF0F5, 0x6CC1, 0xEF4B, 0x8161, 0x0D93, 0xA370, 0x80EA, 0x0AB7, 0xDF98, 0xD1D2, 0x7D19, 0x26D3, 0xF40C, 0xD9CF, 0x11AB, +0x327C, 0x03F9, 0x62EE, 0x5D2B, 0xF4D3, 0x437F, 0xE4B3, 0x6FD8, 0x174E, 0xBFE6, 0x1584, 0xBA5E, 0x924C, 0xBAD5, 0x88DC, 0xABB0, +0x4089, 0x5748, 0x1EC7, 0x0684, 0x6A71, 0x7D0E, 0x0BA4, 0x55C0, 0x82CE, 0x5E97, 0x1E61, 0x8B70, 0x7C69, 0xDB81, 0x9E1A, 0x361C, +0xCBEC, 0x6A66, 0x37D9, 0xE43A, 0xB2D4, 0xAD5E, 0x1445, 0xC270, 0x6BCE, 0x2535, 0x91D9, 0x459D, 0xDA55, 0xE6CA, 0x6F01, 0x4DF7, +0x3E64, 0x5E65, 0x514F, 0xE243, 0x5583, 0xF78F, 0xB438, 0x2B6A, 0x1F20, 0x62B6, 0xED10, 0x7BF2, 0xDE01, 0x5305, 0xF5F0, 0x7D93, +0xB5AF, 0xD735, 0x0D5C, 0x8554, 0x8170, 0x09C8, 0xCC39, 0xFB33, 0xC0D2, 0xF58C, 0x263D, 0x3164, 0x36ED, 0x674A, 0x56DE, 0x305E, +0xC19B, 0xF9D8, 0x2349, 0x0B8C, 0xBE93, 0x8712, 0x1CEC, 0xFE40, 0x9759, 0xE3B9, 0x22A3, 0x8D9B, 0x84BB, 0x7C88, 0xB225, 0x5A24, +0x4C3F, 0xBEAA, 0x586B, 0x3C45, 0xC777, 0xE7E9, 0x3CCF, 0x569B, 0xBC52, 0x6F5F, 0xA260, 0xCEA7, 0x7EF4, 0x3B55, 0xB103, 0xD619, +0xD191, 0x0114, 0xB543, 0x21D6, 0x93A8, 0x16B5, 0xF59B, 0x9135, 0x1FD9, 0x70A3, 0x627D, 0x872B, 0x6B75, 0x0C1F, 0x7A5A, 0x32FD, +0x5684, 0x040B, 0xA732, 0xE77D, 0x0D7E, 0xC581, 0x3DDE, 0xB068, 0x39D2, 0xD021, 0x3E8C, 0xDEE9, 0xA6DF, 0xDF74, 0x896F, 0xECDB, +0x2E6E, 0xA6A9, 0xC745, 0xC819, 0x78B8, 0x6628, 0x5D4F, 0x441F, 0x97A0, 0xF1AC, 0xADCE, 0x7142, 0x31CF, 0x2392, 0x3D8F, 0x154A, +0xAF14, 0x6D94, 0xF205, 0x5E6C, 0x4B79, 0x2BA0, 0xCD28, 0x1DC0, 0x4552, 0x4AF2, 0xBAD1, 0x212A, 0xEEC6, 0x836B, 0x6EB2, 0x0A9C, +0xF185, 0xE087, 0x895C, 0x7562, 0xC9DE, 0x25F0, 0x377E, 0x4FDF, 0x1ED2, 0x469C, 0xE3C1, 0x924B, 0xA4E2, 0xED31, 0xFAAF, 0xE34F, +0x63F2, 0x6142, 0x498B, 0x4106, 0x8967, 0x8151, 0x3FFC, 0x6D85, 0x22D9, 0xBED6, 0x175F, 0xFE75, 0x0682, 0x073D, 0xF9B7, 0x995F, +0x0E7A, 0x473A, 0xFB5A, 0x9CAD, 0x22CE, 0x556D, 0x9FAA, 0x9AF5, 0x96AB, 0xC793, 0x2C72, 0x6422, 0xFE58, 0xC2BC, 0xBD7A, 0xC4F8, +0x9A62, 0x08DD, 0x1CBC, 0xF817, 0xCF60, 0x6F70, 0xCF0A, 0xC02D, 0x5E59, 0x2405, 0x9302, 0x01B6, 0x4E9B, 0x5B22, 0x1E6A, 0x7F18, +0x1E70, 0xBFF6, 0x6D50, 0xB6F7, 0x0FF5, 0xC4CA, 0x76DD, 0xF580, 0x1E2B, 0x5489, 0x6CAC, 0x6E92, 0x1196, 0xB22B, 0x7505, 0xAC21, +0x80D9, 0xB27C, 0xE3E5, 0x232F, 0x0569, 0x4D18, 0xCE1B, 0x26DE, 0xDBD9, 0x9B7B, 0x0FEE, 0x11F8, 0x96B0, 0xBF03, 0x2606, 0x45DA, +0xE18F, 0x184B, 0x1F56, 0x5F38, 0xE4E5, 0xB457, 0xDE09, 0x20AA, 0x9652, 0xD586, 0xA31F, 0x98FB, 0x4B2C, 0x9DA6, 0x32D0, 0x8B96, +0x7949, 0xDBE3, 0xB6D2, 0x9A3E, 0x436E, 0xA339, 0x3EED, 0x8B76, 0xA759, 0x01A8, 0x8BB3, 0xEE3B, 0xDEA9, 0xE31C, 0xC1DB, 0xA39D, +0xB1AD, 0x33AA, 0xF162, 0xDC0A, 0x7D32, 0x437A, 0xA2BF, 0xE200, 0x1CC4, 0x2AE2, 0xF0B2, 0xB88B, 0x2BC7, 0x3F66, 0xEB4E, 0x5020, +0x091E, 0xABD0, 0x84F2, 0x1DFB, 0x915E, 0x08F1, 0x3BB8, 0xC654, 0x14CF, 0x6338, 0x44F9, 0xBF4D, 0x5633, 0xA7A4, 0x1807, 0x7257, +0x4E52, 0x9417, 0x8364, 0x35C5, 0x9622, 0x33E7, 0x0A6B, 0x372A, 0x94BD, 0xABED, 0x3F01, 0x4EE2, 0x717D, 0x10EB, 0xAC9B, 0x7797, +0xF08E, 0xC24F, 0xD1C5, 0xA4EA, 0xD759, 0xE6D0, 0xCB4E, 0x6BFC, 0x684F, 0xF9EB, 0xC0A4, 0x408E, 0x1E2A, 0xFBBB, 0xFFDA, 0x9410, +0x5E58, 0x6CDB, 0x156E, 0x1F9F, 0xBB19, 0xA240, 0xE31C, 0x585F, 0x1C3D, 0x38F7, 0x7FDF, 0x4452, 0x9EB3, 0x607C, 0x64E4, 0x1F4E, +0xEA35, 0x78EE, 0x2E9C, 0x7FD2, 0x1D50, 0xC4B8, 0xCA5F, 0x8D0F, 0xEDCF, 0x4695, 0x5C48, 0x50C0, 0xC601, 0x1F9A, 0xC7B6, 0xAED2, +0xA1A7, 0xCB66, 0x6768, 0xF650, 0x5009, 0xD2DD, 0x4BC8, 0x8D75, 0x9444, 0xB9F8, 0xB06C, 0xB23B, 0xC409, 0x4FF1, 0x2331, 0x38F9, +0x13A5, 0x1171, 0x7BAB, 0xC6C3, 0x5B57, 0x2A99, 0x3AA9, 0x20A7, 0x914F, 0xDC46, 0xD815, 0xAF03, 0x8E18, 0x4385, 0x206B, 0x4895, +0x7E4C, 0x8D48, 0x2971, 0x4B2B, 0xE16F, 0x9105, 0x21F9, 0x86B5, 0x1D36, 0x0EC8, 0xFE63, 0x5132, 0x5124, 0x8152, 0xE411, 0xCEFC, +0xDF43, 0x1DA7, 0xC025, 0xD9A9, 0x9949, 0x8068, 0xC87D, 0x50E2, 0xF6C4, 0x2862, 0x759B, 0x705C, 0x665C, 0xC7D3, 0xB76E, 0xDB56, +0x81B3, 0x2AF5, 0x5B77, 0xA2E4, 0x0A7F, 0xE198, 0x892D, 0x539F, 0x954F, 0x8FC7, 0x31D0, 0xA75B, 0x0B9E, 0xAEDF, 0xA3C4, 0xE94B, +0x26D3, 0x7438, 0x9512, 0x60B8, 0xDF4E, 0x6E49, 0x388B, 0xFD4A, 0x8A44, 0xB2B1, 0xF1C6, 0x8F9F, 0x2E45, 0x9BCC, 0x50B3, 0x3D11, +0x91B9, 0xD239, 0xCD7D, 0x88BE, 0x2744, 0x703F, 0x605A, 0x3CEA, 0x1DCF, 0x1CDD, 0x710E, 0xADEB, 0xE450, 0xDE48, 0x6BBB, 0x8192, +0x3C68, 0xCE99, 0x6A4B, 0xBB80, 0x1547, 0x4C21, 0x399A, 0x1BB9, 0x0FC4, 0x0DCF, 0x6D2A, 0x9FD1, 0xF66E, 0x7FED, 0x68DF, 0x07D3, +0x6E46, 0x7584, 0xBF7B, 0x6171, 0xCC54, 0x00A2, 0xC88E, 0xE9C0, 0x95B6, 0x9DD2, 0xBEBD, 0x5B82, 0xBEEA, 0xF1C5, 0x2C6E, 0xA625, +0xC5F8, 0xA706, 0x3F7C, 0x0291, 0x5340, 0xA200, 0xC96C, 0xB611, 0x7344, 0x971C, 0xE977, 0x6012, 0xBE77, 0x23F2, 0x8F02, 0xE194, +0x31FD, 0x85FB, 0x011E, 0x9ED1, 0x04E1, 0x8E6E, 0x9936, 0xA9B5, 0x18E8, 0xF21E, 0xD654, 0xED0B, 0x2586, 0x8BC3, 0xC88C, 0x26F5, +0xDCC6, 0x2EFF, 0x0E0B, 0xA401, 0xA12C, 0x0BBA, 0x3330, 0x81FD, 0x78E3, 0xC8EF, 0xE3B5, 0x3D3D, 0xF751, 0xF69D, 0xCB6C, 0xB44C, +0xCE02, 0x2246, 0x7318, 0x771E, 0xEFF1, 0xFEF3, 0x31E2, 0x7C9F, 0x9091, 0x7311, 0x19E7, 0x1B62, 0x7F3C, 0xA44E, 0x8F59, 0x0142, +0x2556, 0x4760, 0x5B3C, 0x1D10, 0xE72B, 0xE59B, 0xC3C6, 0x2C55, 0x0463, 0x523C, 0x67E8, 0xC2FE, 0xBF48, 0xAA82, 0x2CB1, 0x520B, +0xDE08, 0xDA8A, 0xE512, 0x5D44, 0xC2CA, 0x6F54, 0xD895, 0x13EA, 0x1811, 0xE00B, 0x5939, 0x11D2, 0x90F2, 0xD4D9, 0x4726, 0x699B, +0x3FED, 0xFDC1, 0xA465, 0xC628, 0x2D22, 0xC7F3, 0xC2D7, 0xCAA6, 0x81E3, 0xED42, 0xFB04, 0xD2B0, 0x6763, 0x4EA3, 0x14DD, 0x68C9, +0x21F7, 0x7D37, 0x9714, 0xB48B, 0x29DA, 0x1FC9, 0x7041, 0xC6C0, 0x9068, 0x6104, 0x968A, 0xE7BB, 0xCA48, 0xFB54, 0x00F3, 0x4E2C, +0xC67D, 0x945E, 0xF152, 0x7F39, 0x6B25, 0x29D2, 0x3221, 0x670E, 0xFD63, 0x7791, 0x7F59, 0x2D73, 0x2F7A, 0x12BC, 0xF300, 0x8E8E, +0xFE1C, 0x3B19, 0xD90D, 0x09F0, 0x98BC, 0x5C11, 0x1A70, 0xCD00, 0x191A, 0xD634, 0xD885, 0x04B2, 0x5F65, 0x35F7, 0xC7D3, 0xB829, +0x0A9B, 0x9888, 0x4ADC, 0x6053, 0xA93B, 0x8323, 0xC0F5, 0x174B, 0x9AE8, 0x83B5, 0xD2D7, 0xF22C, 0xC73E, 0x96EA, 0x6405, 0x1D4D, +0x01E3, 0x9CA4, 0xAB0B, 0xE03F, 0x73AC, 0x2C8C, 0xB2A4, 0x182A, 0x9163, 0x573B, 0x1736, 0xF2DB, 0x05DF, 0x1A7A, 0x8006, 0x9F9E, +0xF30B, 0xF117, 0x1FEB, 0xD942, 0xEF3C, 0x6D02, 0x3003, 0xBAE3, 0xE668, 0x1966, 0x568A, 0x0DEF, 0x8F27, 0xCAF5, 0x83D8, 0xFB0A, +0x11E9, 0x6468, 0x3D01, 0xCA65, 0x5E97, 0xBD2B, 0x5BD3, 0x775F, 0x19E3, 0xC421, 0x57E8, 0xF86B, 0xEA11, 0x6AED, 0x4879, 0xF747, +0xE9B0, 0x4BB6, 0xE0B2, 0x027A, 0x2535, 0x4F6A, 0x3112, 0x5C10, 0x63E8, 0xA618, 0xCA66, 0x1DA1, 0x570C, 0x2ED4, 0xBBB4, 0xC1C8, +0xEE16, 0xC3D5, 0x4F07, 0x23AA, 0xB587, 0xCDB6, 0xF307, 0xA275, 0x919A, 0x452E, 0x985B, 0x0E02, 0xB0AB, 0x4560, 0x0FAC, 0xD0F0, +0x1020, 0x2229, 0xB585, 0xBB6B, 0x6332, 0xA14B, 0xC1E4, 0xF1B8, 0x1F68, 0x3CCB, 0x4E3B, 0xE262, 0x1F15, 0x72CB, 0x5C69, 0x278F, +0xBE34, 0xE834, 0xA133, 0xA098, 0x2C50, 0x3A9B, 0x8FB1, 0x60DF, 0x1B0C, 0xBA4A, 0xCBF6, 0x2E72, 0xD040, 0xE7A0, 0xD632, 0x0B46, +0x6077, 0x521A, 0x87A5, 0x3CAE, 0xB102, 0x0A83, 0xC4B1, 0xBC9A, 0xACFE, 0x5E5B, 0x8171, 0xB314, 0x978F, 0x3673, 0x85B5, 0xF645, +0x41CB, 0x4F89, 0xD335, 0x4957, 0xC740, 0x4A06, 0x2765, 0xB5F5, 0x9375, 0x3B45, 0x0445, 0xD81B, 0x8AFA, 0xC82D, 0x91E7, 0x2CF1, +0x99E7, 0x3B85, 0xD292, 0x85BF, 0xF705, 0xE4A2, 0x3447, 0x1132, 0xD07E, 0xC488, 0x052C, 0x4CD7, 0xDF96, 0x6A6C, 0x6268, 0x1002, +0x51C1, 0xB745, 0x453F, 0x630D, 0xEA7B, 0xDBA1, 0xCE12, 0xDA80, 0x1BF5, 0xA85F, 0x449B, 0xD2AB, 0x6534, 0xB8BA, 0x5998, 0x4428, +0x835C, 0x8124, 0x2DCB, 0x5E87, 0x3D0C, 0xC6CA, 0x3556, 0xF7C1, 0x55FE, 0x7BF6, 0x99C0, 0x5C99, 0x07BD, 0x8E4D, 0x5A04, 0x2AC0, +0xAE3E, 0x10F8, 0x3739, 0x8AC2, 0x016B, 0xAB3C, 0x66C6, 0x0FAA, 0x938C, 0x2950, 0x8B28, 0x24C2, 0x3F8E, 0x9737, 0x1E4D, 0x639F, +0x7ACC, 0xE8BB, 0x78FC, 0xE796, 0x7B0B, 0x28EB, 0xC5A0, 0x5A69, 0x297E, 0xE125, 0x1D9D, 0xA35A, 0x4FA4, 0xD252, 0xBDD9, 0xCC87, +0x71D5, 0x56D6, 0x7920, 0x37B9, 0xB00D, 0xE8E4, 0x0CF7, 0x046A, 0x1AFE, 0x9E60, 0xC527, 0xC7CB, 0xAAA3, 0x5994, 0xD96D, 0x959A, +0xB62A, 0xE46D, 0xC372, 0xF8FC, 0xB915, 0x821A, 0x3774, 0x2A2C, 0x4EF5, 0x1501, 0xB013, 0x7C05, 0xA7E0, 0x5604, 0x2ADC, 0x5F44, +0x8E2A, 0xF16B, 0x0B26, 0xDE76, 0x5B1D, 0x9879, 0xA423, 0xD140, 0x9287, 0x1F6F, 0x0A94, 0x31A2, 0xF019, 0x7619, 0x9EB8, 0xB22D, +0x4FBA, 0x8DF2, 0x9645, 0x41ED, 0xFF12, 0x6C3B, 0xC782, 0x8784, 0x3275, 0x8FD2, 0x344E, 0x83C6, 0xEFF9, 0x0A1B, 0xCD01, 0xB903, +0x9E20, 0x09A7, 0x9D2C, 0xF42C, 0x7626, 0x09DE, 0x4D54, 0xBE35, 0x1A07, 0x8C75, 0x4A4A, 0x3B12, 0x1FD7, 0x068E, 0x56C7, 0xDAF4, +0x5501, 0x3753, 0x691C, 0x9AD5, 0x351B, 0x4E53, 0xC693, 0x6177, 0xB7F5, 0x30AC, 0xA8A2, 0x9388, 0x37D2, 0xEE3A, 0xF56D, 0x83C1, +0x61DF, 0xAE1A, 0xEF2A, 0x1DE3, 0x9D36, 0x7943, 0xE580, 0x6B1F, 0x927E, 0x0D7A, 0x85F9, 0xCD7B, 0x456D, 0x2903, 0x1112, 0xFD43, +0xAC91, 0x5ECC, 0x3C2B, 0x23C4, 0x731C, 0xA072, 0x3665, 0xCCDF, 0xCB75, 0xAA7F, 0x2CFF, 0x6C4B, 0x7FCB, 0xB225, 0x12B0, 0x6586, +0x2156, 0xF952, 0xF1ED, 0x1B67, 0xF747, 0x044D, 0xEE24, 0x3EDF, 0x10B0, 0x53ED, 0x9B98, 0x460B, 0x3904, 0xF282, 0x8F08, 0xCB5F, +0x677D, 0x34AA, 0x0BF2, 0xC7FE, 0xC1C8, 0x0D2C, 0x2220, 0x0EAF, 0xA0BB, 0x8F4A, 0xBD26, 0x29D6, 0xA59E, 0x54EF, 0x7DB1, 0x2871, +0xDEA9, 0x5EEF, 0x83EB, 0xF2A8, 0x1C57, 0x74D0, 0x46F0, 0xEBF5, 0x98C9, 0xD2E2, 0x542B, 0xB062, 0x63BE, 0xDD0F, 0xC8DD, 0xECE8, +0x9EED, 0x5D35, 0x5EC5, 0x7EEF, 0x87CF, 0xE30D, 0xD2D6, 0xA307, 0xDC3B, 0x1599, 0x397B, 0xD615, 0xED87, 0x08F0, 0x9A6C, 0xCE36, +0xCEA3, 0xA623, 0x15E1, 0xD8F2, 0x316C, 0xE577, 0xAF87, 0x8480, 0x1049, 0x41F8, 0x14F5, 0xBAD2, 0x8C70, 0xAD98, 0x00A2, 0x8431, +0x8456, 0xE794, 0xA19C, 0xA5D7, 0x4DC6, 0xC165, 0xD3C7, 0x45F4, 0x59BB, 0xAAE7, 0xA597, 0xC65B, 0x35AC, 0xECD1, 0xA200, 0xF4F4, +0x315C, 0x019E, 0x67E7, 0x313D, 0xDA7C, 0x95EA, 0x0753, 0x51AA, 0x9830, 0xC0F7, 0xDB46, 0x4CBB, 0xD6CA, 0x8215, 0x4777, 0xA386, +0x7DC6, 0x8E0B, 0xF4AB, 0x1CC6, 0x0BC1, 0x2F44, 0x2331, 0xE85C, 0x253B, 0x3034, 0x21CA, 0x3998, 0x7DB5, 0xB0CE, 0x45DD, 0x12B3, +0xEEB7, 0x47B0, 0x29FE, 0x8C46, 0x6B1A, 0xD632, 0x6D62, 0x5A6A, 0x1142, 0x77C7, 0x9549, 0xAFB2, 0x43E7, 0x4CB6, 0x8057, 0x5583, +0xB120, 0x82DD, 0x4F25, 0x03AC, 0xC9DF, 0x85B5, 0xD1E5, 0x9819, 0x42B0, 0xC410, 0x8C44, 0xE6C7, 0x95F1, 0x3498, 0xD2D8, 0x8170, +0x1148, 0xE00D, 0x5BF8, 0x6589, 0x800A, 0xA6AF, 0xC5B6, 0x8F40, 0x993B, 0xF6C8, 0x5AFA, 0x59DB, 0x195D, 0x633B, 0xC782, 0x7234, +0x48B0, 0xEB42, 0x1A12, 0xBABD, 0x8FD8, 0x6B94, 0x2113, 0x35B1, 0x3E30, 0x5EC3, 0x0819, 0x1904, 0xDDE8, 0x6887, 0x3505, 0x6737, +0x0142, 0x18C1, 0xCDF2, 0x4FD3, 0xAD31, 0x3708, 0x2CC1, 0xE035, 0x11BB, 0x65D2, 0x1A24, 0x536B, 0xF693, 0x13AC, 0x0FFD, 0x1AED, +0x520B, 0x51E3, 0xE54B, 0x6185, 0x45D1, 0x49FC, 0x2002, 0xD342, 0xBBB0, 0xE1BD, 0x94F5, 0x094A, 0x05C3, 0x8CA6, 0x0D69, 0x5DF5, +0xFEBD, 0xBF7C, 0xBFF4, 0xA61C, 0x4621, 0x4795, 0x8415, 0x351F, 0x99C2, 0xE4DD, 0xD597, 0xA502, 0xAC29, 0x3C21, 0x4828, 0x3D5A, +0xAB9B, 0x387C, 0xB07C, 0xD894, 0x03D6, 0xA7DD, 0xD0F4, 0x7EEA, 0xC730, 0x7B6E, 0x10A8, 0xF689, 0x4DDA, 0xD0B9, 0xEAB4, 0xBBB2, +0xAE9F, 0x949D, 0x51C0, 0x252E, 0xDFF6, 0xB0B8, 0xF8A3, 0xF7B5, 0x1354, 0x1BB9, 0x863A, 0x8572, 0xCCC2, 0x9EE1, 0x91B6, 0xE6EC, +0xDBCC, 0x484F, 0x825C, 0x5F51, 0xD1E6, 0x0C15, 0xD5A1, 0x33C8, 0x74A6, 0x19FE, 0xDFE2, 0xA7FF, 0xC540, 0x9401, 0x3368, 0x6A78, +0x5160, 0x3320, 0x23C6, 0xCCE1, 0x34E6, 0xC025, 0x5077, 0x229F, 0x9B2D, 0x9AB6, 0x4989, 0x731B, 0x9678, 0xB16C, 0xD663, 0xC15B, +0x225C, 0x21D0, 0xD76B, 0xE640, 0x97E1, 0xE234, 0x2557, 0x9E60, 0x0826, 0x832D, 0x5BBF, 0x583C, 0x8D59, 0xC81E, 0xD4B5, 0x8C3F, +0x416A, 0xCBEC, 0xB5CC, 0xE6BB, 0x19DD, 0x5182, 0xB900, 0x4DEA, 0x13AD, 0x09AC, 0x0957, 0x79AB, 0x79B6, 0xC1FB, 0x1E1C, 0xA982, +0x38E7, 0x9B71, 0x2832, 0x3D78, 0x5DE8, 0xC05C, 0x2446, 0x7893, 0x8DA6, 0x3C53, 0xC753, 0x4872, 0x5572, 0x2C3F, 0xECD9, 0xB6FD, +0xBE95, 0x6C51, 0xC7CA, 0x0F74, 0xF2CD, 0x211F, 0x11D4, 0x98C0, 0x9BD4, 0x88A3, 0xC6E4, 0x8FC2, 0x230C, 0xEE76, 0x59C9, 0x8E35, +0xC177, 0xF2EE, 0x7D05, 0x8469, 0x1BEF, 0x2E7D, 0xD4B0, 0xD53B, 0xF126, 0xA680, 0x430E, 0xB7B1, 0x1D6B, 0x7020, 0x0B04, 0x50BA, +0x617E, 0x2A7F, 0x89D3, 0xB20F, 0x43AB, 0x62C7, 0x7BE5, 0x9300, 0x12A6, 0x3F93, 0x88EB, 0x6CCB, 0xB621, 0x20D5, 0x9EE9, 0x7830, +0x0D91, 0xFE38, 0xC68B, 0x9B03, 0xD9F1, 0x848C, 0x2664, 0xA57E, 0x96AD, 0x52A4, 0xEE80, 0x68EE, 0xF52F, 0xF476, 0x9C01, 0xC379, +0x9E81, 0x8DC2, 0xFBD5, 0x5BC0, 0xA8BB, 0x125A, 0xD331, 0x462A, 0x9ADF, 0xBE9C, 0x4758, 0x9AA2, 0xEC9B, 0x0F58, 0xD93C, 0x5F87, +0xF401, 0x97A7, 0x93BC, 0x2212, 0x9FF6, 0x6AAD, 0xD692, 0x08D6, 0xEA2D, 0xC877, 0x6ADD, 0x972D, 0xBD36, 0xA869, 0x7BDC, 0x253E, +0x8E8B, 0x750E, 0x6DDF, 0x719A, 0x8580, 0x83FD, 0x3A46, 0x295F, 0x125F, 0x2D86, 0x0786, 0x9012, 0x0355, 0x7FCF, 0x1143, 0x375E, +0xEEBA, 0x2D06, 0x6CE5, 0xF92A, 0x55FF, 0x48C5, 0xD783, 0xEE25, 0x6FAD, 0x7709, 0xF631, 0x8763, 0x651D, 0x4C48, 0x43B0, 0x1FFC, +0x7174, 0xD2B3, 0x1FD9, 0x9855, 0x6E90, 0xF360, 0x9292, 0xFC75, 0x9A26, 0xAC89, 0xC835, 0x667B, 0x59EF, 0x5042, 0x5696, 0x10E9, +0x172A, 0x4499, 0x39D2, 0x403B, 0x13F8, 0xA6E4, 0x2775, 0x438D, 0x132D, 0xEDDA, 0x726C, 0x78A0, 0x2D04, 0x1057, 0xA46D, 0xF9BB, +0x2ECF, 0x22CC, 0xA1BC, 0x67F5, 0xA625, 0x7DAC, 0xC32A, 0xBC00, 0x1778, 0xC345, 0xA0DC, 0xD0F2, 0xC283, 0x2A44, 0xB274, 0x9039, +0x0E14, 0xCD60, 0x08A5, 0xE6AB, 0xE194, 0x0F5E, 0xDD29, 0x7461, 0x188A, 0xB229, 0x78AE, 0x258F, 0x6422, 0xC538, 0xE003, 0xAC63, +0xD130, 0x8571, 0xD3BA, 0x8E3A, 0x4D35, 0x0D31, 0x6BFE, 0x692A, 0x9F01, 0x424A, 0x6F6F, 0x269B, 0x9839, 0x05C9, 0xF5A1, 0xB78E, +0xF784, 0xA4FF, 0x5D92, 0x5FBA, 0xA793, 0xE17F, 0x2DDF, 0xD9C9, 0x640A, 0x28FA, 0xFCF3, 0xDA4C, 0x2C3B, 0x9927, 0x07DE, 0x4A24, +0xC13A, 0x7DBD, 0x45B0, 0xA460, 0x600E, 0x9C96, 0x8289, 0x065F, 0x1781, 0xD150, 0x2FB1, 0x2C2B, 0x77F7, 0x755E, 0x3DDE, 0xDF57, +0xED3F, 0x1E5E, 0xA2CB, 0x8482, 0x6D9A, 0xC317, 0x2CCE, 0x3F3A, 0xE18A, 0x9784, 0x601F, 0xCA02, 0xF410, 0x7D06, 0x3FB2, 0x70E6, +0x3EC5, 0xDA00, 0x37B6, 0x4DAF, 0x8B1E, 0xEC0B, 0x2A5D, 0xD375, 0x9FF8, 0x505F, 0xE002, 0xDA42, 0x2D4D, 0x5AD3, 0x7A0B, 0xF8E0, +0x14AF, 0x77C1, 0xF7FC, 0x3D93, 0x2B9D, 0x2D36, 0xDC38, 0x9292, 0x9D0A, 0x0D57, 0xE442, 0x35C1, 0xBC09, 0x2119, 0xD86F, 0x96A1, +0xE12E, 0x9C2E, 0x79AF, 0xF0D4, 0x3A78, 0xAFD3, 0x406C, 0xD8B5, 0x168A, 0xE76F, 0xAE0D, 0x394B, 0xB860, 0x9470, 0xBD2B, 0x0EE5, +0xD849, 0x7B17, 0x4C72, 0x22F9, 0xE983, 0x87C7, 0x2EEC, 0xE2D7, 0xFA81, 0xF973, 0x49CC, 0xEA9E, 0x544D, 0xA54F, 0x4F6A, 0x0562, +0x1ED1, 0x3B93, 0x0BA9, 0x191B, 0xD168, 0xDF4E, 0xE8B8, 0x0D9F, 0x9EF3, 0x6660, 0x61BE, 0xCF22, 0xE2DA, 0xBBFD, 0xFAFE, 0x2952, +0x21D9, 0x1288, 0x1945, 0x9BE8, 0xAF84, 0x69E6, 0xDE1A, 0x4F7F, 0x8601, 0x63A0, 0xCD91, 0x155D, 0x1C54, 0xF950, 0xA8B7, 0xE325, +0x0EDB, 0xC35F, 0x9DA3, 0x3341, 0xFC53, 0x4EE9, 0x01CF, 0x62EA, 0x1673, 0xF57A, 0x2160, 0xC592, 0x0D14, 0xCB6A, 0x3281, 0x418B, +0x3B62, 0xA829, 0xE61C, 0x40D0, 0x658D, 0x4B8E, 0xDF0B, 0xA98C, 0x0381, 0xDCDE, 0x517D, 0x0513, 0xC47F, 0x1D71, 0x90DB, 0xD9E7, +0xF124, 0x64E2, 0xEFA5, 0xDA8E, 0x1743, 0x3E74, 0xA91B, 0xB7C0, 0x9E0A, 0x7475, 0xEED3, 0x33FB, 0x57AE, 0xE4E7, 0x7554, 0x663C, +0xC2F2, 0xC1B6, 0xB32B, 0xF9C1, 0x238A, 0xA5AF, 0x2FFD, 0x0424, 0x7F01, 0x460D, 0xD520, 0xFAD0, 0x8C66, 0x416E, 0x7706, 0x3FA0, +0xA106, 0x4F03, 0x0191, 0x59BC, 0x8E94, 0xC959, 0xD5AD, 0x756A, 0x149C, 0x8B11, 0xBD7E, 0x138B, 0x3745, 0x4627, 0xACCA, 0xBD8A, +0xB2A5, 0xB185, 0x810B, 0x7E04, 0xF1BA, 0x0E67, 0x2AA8, 0x4906, 0xCC97, 0x249D, 0x1A6A, 0xABA6, 0x04FC, 0x05D6, 0xAEDA, 0xEE6A, +0x5EF9, 0xE8BE, 0x7397, 0xB073, 0x6584, 0xB9C4, 0x7D79, 0xA040, 0x9CE5, 0x0A1E, 0x72CD, 0xE5E2, 0x6DFF, 0x69AA, 0xEB1F, 0x9A3D, +0x4B35, 0xD81A, 0xD43C, 0xC715, 0xB7BD, 0xE046, 0xDA5E, 0xE4AE, 0xB017, 0xBE4E, 0x9E37, 0x5465, 0x4CE5, 0x59C9, 0x4907, 0x082D, +0x4EF3, 0x1072, 0xE59D, 0x9A29, 0x48BF, 0x2863, 0x940E, 0xCF35, 0x1465, 0x9904, 0x3213, 0xEF52, 0x8231, 0x193D, 0x2360, 0xF2E4, +0x518E, 0x62BB, 0x2B65, 0x1C2D, 0x7DB4, 0xC22E, 0xDB4F, 0x025D, 0x3597, 0x0130, 0x02DB, 0x442B, 0x94CE, 0xBDE8, 0x716B, 0x32EF, +0xB10C, 0xB7CF, 0x979B, 0x73E6, 0xA3AF, 0x58FE, 0x3CDA, 0x1A1F, 0x9C1C, 0x180B, 0xFDA0, 0x193B, 0xD88B, 0x36B0, 0x64B5, 0xD553, +0xA81E, 0x0B24, 0x7E52, 0xA53C, 0x3BB3, 0x2C0F, 0x2BB9, 0xAFF5, 0x4917, 0x9BE3, 0x8686, 0xBBE8, 0xDCD7, 0xE1F7, 0x96B6, 0xD4A8, +0x6EE7, 0xF1E1, 0xD982, 0xCE9D, 0x12C9, 0x1B26, 0x56EB, 0x11DF, 0x156E, 0xAF3B, 0xB3AF, 0xFA32, 0x4DA6, 0xF813, 0xA395, 0x2356, +0x64F8, 0x07F2, 0xC5DC, 0xBA56, 0xF9AD, 0x86FE, 0xD96D, 0xDFB0, 0x2E9C, 0x6FC7, 0x2B08, 0x64B7, 0x3493, 0x65A1, 0x01B3, 0x476B, +0x9118, 0x565C, 0xAB84, 0x2752, 0xF9D9, 0x6BBB, 0xFE3F, 0xC4F5, 0x9D17, 0x2E34, 0x7C1C, 0x0C5B, 0x171C, 0xD79E, 0xE440, 0x04E1, +0x9D68, 0x6E6D, 0x90EB, 0x0347, 0xBFAA, 0x68DF, 0x299B, 0x7218, 0x521C, 0xF514, 0xAF55, 0x9B74, 0x7C8A, 0x39BE, 0xE66E, 0xA12C, +0x8112, 0xAE90, 0x3D8E, 0x0D08, 0xD4E2, 0xFA1C, 0x1748, 0xAB80, 0x1597, 0xBD2E, 0x3CC2, 0x06EB, 0xF8D2, 0xA709, 0x2C3F, 0x6C38, +0x87D3, 0xD4CC, 0x6FB2, 0xD87F, 0x75A3, 0x4AB7, 0x288A, 0x94EB, 0xD79C, 0x4A6A, 0x33B9, 0x8B3A, 0xA4A1, 0xDD9F, 0xDE02, 0x9BEE, +0x7EED, 0x092D, 0x4F88, 0xE4C7, 0x3FF2, 0x8A81, 0xBF9C, 0x7EAA, 0x9DEE, 0x3C21, 0xF371, 0xF082, 0xA268, 0x8884, 0x6BEA, 0x4B8F, +0x7E43, 0xBD53, 0x3A85, 0x616E, 0x33A4, 0xA496, 0xD87C, 0x3943, 0xAB1C, 0xD0B9, 0xB7E4, 0x74F9, 0xECB8, 0x8180, 0x39DF, 0x7DA9, +0x7CC8, 0xBCCA, 0xA29E, 0xD48D, 0xAB06, 0xFF15, 0x787B, 0x56D4, 0x3E40, 0xC56C, 0xCA2B, 0xF7E4, 0xAC09, 0xA60A, 0xFBEB, 0xFB26, +0x7B55, 0xBE61, 0x1AB8, 0x1AA3, 0x12EB, 0x1390, 0x8879, 0xE66D, 0x91AF, 0xFB13, 0x4C7A, 0x62C8, 0x6DDA, 0xCE94, 0xADBC, 0x60BC, +0x8337, 0x1B77, 0xD098, 0x3D42, 0x4016, 0x8F88, 0xD0AF, 0x83FE, 0xB639, 0x4463, 0x0598, 0x018D, 0xF6B3, 0x8987, 0xBC3E, 0xDC91, +0x82C5, 0xD7FE, 0x4F8F, 0xA3B2, 0x54EC, 0xFDB1, 0x788F, 0x4BC5, 0xED2F, 0x61C0, 0xC827, 0x9D0B, 0x25C3, 0x928B, 0x4A61, 0x86FB, +0x933D, 0xE3BB, 0x4692, 0x1718, 0x6D2D, 0x1E2F, 0x39D8, 0xEC8B, 0x3EB9, 0xD779, 0x4546, 0x0B3D, 0x197D, 0xF910, 0x7441, 0xB448, +0x987E, 0x6D5F, 0xB0D6, 0x788A, 0x9EE5, 0xDFD9, 0x799E, 0xAD36, 0x68AF, 0xDEBE, 0x54CB, 0x8D45, 0xFDE8, 0x76AA, 0x720D, 0xBC39, +0x6CC2, 0x4406, 0x3494, 0xFED7, 0x863D, 0x6EB2, 0x910C, 0x39A1, 0xB6C0, 0x5676, 0x8AF5, 0xFD54, 0x43C7, 0xD69D, 0x3394, 0x93FF, +0x61EE, 0x04C0, 0xE5E1, 0xC19B, 0xD8E2, 0x31F8, 0x8968, 0x009E, 0x142F, 0x446D, 0xD096, 0x7286, 0xB5F1, 0x2AB5, 0x95D0, 0x5A7E, +0xB329, 0x0228, 0x7A8D, 0x43AC, 0x375B, 0x2D6A, 0xFB3D, 0x3261, 0x3FB2, 0xE146, 0xC4FA, 0x1E5D, 0xD6EA, 0x183E, 0xF4B4, 0x65FA, +0xAD08, 0x0816, 0x5E6F, 0xDEF1, 0x1AFC, 0x9B09, 0x7BBC, 0x70DB, 0x73A4, 0xB049, 0x7D18, 0xADD9, 0x5DB5, 0xAEE3, 0x02D5, 0xC9BD, +0x4CD6, 0xA595, 0x088B, 0xAA63, 0xDC4B, 0x5DF7, 0x53E9, 0xE74B, 0xB7CB, 0x6049, 0x0B49, 0xE834, 0x8C50, 0x37B3, 0xB361, 0x424D, +0x5498, 0x6189, 0x0B58, 0x67E0, 0x5CFB, 0x7528, 0x8B4A, 0xDD73, 0x0F24, 0x2A9A, 0xF945, 0x521A, 0x15AC, 0xF2FC, 0xE508, 0x2FFA, +0x5CDC, 0x5D59, 0x9E81, 0x8039, 0xF170, 0xCC50, 0xBA9E, 0x883E, 0x3F4B, 0xF353, 0x4B97, 0xE284, 0x639E, 0x4724, 0x7B1E, 0x2A94, +0x4E23, 0xDB28, 0xF401, 0xBCD8, 0x96F2, 0x5740, 0x8A5B, 0x3B80, 0x8AA4, 0x95E4, 0x65A9, 0x4254, 0xCD87, 0x16DD, 0xDD64, 0x1538, +0xA323, 0xFAE4, 0xEC87, 0x69F6, 0x1A60, 0xBCCD, 0x124A, 0x5D14, 0xB732, 0x725C, 0x8424, 0x14ED, 0x3924, 0x68A9, 0x3CCB, 0x0D23, +0xB7B3, 0xB2B7, 0xA136, 0x05C9, 0xD0F5, 0xB961, 0x7AAD, 0x9628, 0xF624, 0x0F37, 0xE1F4, 0xBD97, 0x859E, 0x4AC2, 0x3AB9, 0xF37F, +0xF301, 0xD105, 0x02B3, 0xEAC4, 0x83B7, 0x4BE0, 0x6EFC, 0x9FBE, 0x3DA4, 0x8D38, 0xD789, 0x349D, 0x59CF, 0xCA69, 0xE555, 0xD695, +0xC7E4, 0xC284, 0x9316, 0x820C, 0x02C5, 0x12A9, 0x7FF8, 0xDB0A, 0x45B2, 0x6DA7, 0x2EBE, 0xECE1, 0x0D04, 0x0E7A, 0xE365, 0x22B5, +0x0CFE, 0x76B8, 0x70B5, 0x030B, 0x68A7, 0x3B7D, 0xC628, 0x4A94, 0xB5DD, 0x0C37, 0x183A, 0xC2F4, 0x0375, 0xE5E4, 0xA280, 0xF122, +0x3E74, 0xAB1B, 0xC621, 0x3B1D, 0x44C2, 0xFC88, 0x8F0E, 0x76A2, 0x3932, 0xF774, 0xAAE3, 0x1322, 0x451D, 0x5265, 0x04B8, 0xC4F2, +0x1CF4, 0x8E74, 0xE6BF, 0x2951, 0x459C, 0xAADA, 0x2F5F, 0x25E1, 0x3D5D, 0x9F2D, 0x58E4, 0xC844, 0xECBB, 0x9573, 0x6AFF, 0x99FB, +0x24CF, 0x11BA, 0x3978, 0xE025, 0x8ECB, 0xDEE0, 0x8E1F, 0x9051, 0xBCB2, 0x480A, 0x360F, 0x036C, 0x9D36, 0xB644, 0x3CD4, 0xFE30, +0xE30B, 0x29C9, 0x94B9, 0xC09E, 0xAE8C, 0xDA47, 0x878B, 0xF0CB, 0xB524, 0x1E22, 0x9757, 0x3E2D, 0xB601, 0xBAFE, 0x2D2A, 0xBE4C, +0xDD5F, 0x7825, 0x6C4F, 0x5934, 0xC8CC, 0x30C1, 0x7EE9, 0x3DF9, 0xC032, 0xD2D9, 0xB252, 0xFCAF, 0xD52F, 0xEA5B, 0xDB09, 0x1877, +0x3CE0, 0x6FE7, 0xDAA0, 0x7DE5, 0x1FEA, 0x999F, 0xEDBA, 0xFB0B, 0x3C56, 0xA912, 0xD958, 0xDD24, 0x232C, 0x745D, 0xEA0A, 0x4849, +0x11B9, 0x74F3, 0xD7C1, 0x465E, 0x0AD2, 0x9A30, 0x8C3D, 0x4DBC, 0xA7B9, 0x26FD, 0x1FDC, 0x23F0, 0x3D6B, 0x6E0D, 0x4C0C, 0x8BB4, +0xC31F, 0xC85A, 0xA8A6, 0x942A, 0xF4FA, 0xE902, 0x456E, 0x2E21, 0xB42F, 0x281D, 0x16EB, 0x2B4D, 0x7996, 0x5BD0, 0xADDF, 0x6FFE, +0xE829, 0x1D6C, 0x82F6, 0xFF4F, 0x4CD5, 0x7411, 0x7CCB, 0xE014, 0xDB39, 0xBC2E, 0x9B81, 0xDC33, 0x7572, 0x3212, 0xABD1, 0x6DF3, +0xD315, 0x3096, 0x3EAC, 0xBE70, 0xD9C1, 0x78A5, 0xAC19, 0x4154, 0x3CAF, 0xBB07, 0x5635, 0x21FD, 0x9658, 0x2B47, 0x65A0, 0x0727, +0xF292, 0xA7CD, 0x7DAF, 0x2477, 0x86DC, 0x5679, 0x7DDA, 0x06E7, 0x5EB9, 0x0350, 0x076D, 0xCC7D, 0xAD59, 0xD633, 0x93BD, 0x5731, +0x2CEA, 0x972B, 0x4CAA, 0x57BF, 0x32D1, 0x0838, 0x04CD, 0x947E, 0xB4D6, 0x3A08, 0x9986, 0xD794, 0xCCE2, 0x04CA, 0x2275, 0x2090, +0x0B02, 0xCE52, 0x2898, 0x9D66, 0xC0DB, 0xB858, 0x8D2C, 0xAB4F, 0x2239, 0x9983, 0x8330, 0x33BE, 0xE540, 0x8A2C, 0x7460, 0xB176, +0x7351, 0x6754, 0xF2CF, 0xA81F, 0xFA64, 0x86F4, 0x5575, 0xD40B, 0x3988, 0x55C4, 0xF16F, 0x611D, 0x578E, 0x7ECC, 0xC697, 0xA040, +0x123C, 0x47AB, 0x19EF, 0x3BF6, 0x32B7, 0x11E2, 0x7770, 0x9CA3, 0x299E, 0xC670, 0x89F2, 0x6E91, 0xAC66, 0x5F43, 0x300E, 0xE4AE, +0x8CAE, 0xC0E9, 0x80C9, 0x41D0, 0x1174, 0xF669, 0xFDA1, 0x0121, 0xB1F1, 0xD4CB, 0x3EDC, 0x9774, 0x0D34, 0x5141, 0x8142, 0x87F7, +0xEBAC, 0x2E34, 0x4CD8, 0x82E7, 0x74B0, 0xFFC3, 0x8786, 0x310B, 0x551E, 0x5CA3, 0x0DAF, 0x9152, 0xE47F, 0x035C, 0xD7D3, 0x02E9, +0x9CA4, 0x3825, 0x16C3, 0x6B8A, 0x3C4F, 0x67CE, 0x14D6, 0x6E54, 0x3971, 0x47D1, 0x7E02, 0x9DC4, 0xE2FA, 0x21D6, 0x493D, 0xEF2E, +0xF117, 0x9495, 0xB381, 0x59DF, 0xBEB9, 0xDDAB, 0x8697, 0xD7F8, 0xD09E, 0xE3DD, 0x9143, 0x811C, 0x3C54, 0xE77D, 0xEFBF, 0x382B, +0x635B, 0x9F98, 0x64C5, 0x8245, 0xD75F, 0x1753, 0xBC02, 0xBB7E, 0xB108, 0xC6DE, 0xB1B1, 0x6BAD, 0xB840, 0x0E5B, 0x0EE8, 0xC899, +0x0887, 0xFD0A, 0xE6B6, 0xE0CE, 0xF8BE, 0x338A, 0x7661, 0x7A50, 0xAC1E, 0x790E, 0x151E, 0x7EDF, 0x744D, 0xBB62, 0x0862, 0xDE6C, +0xBCB0, 0xD9B6, 0x2ADC, 0x3F3E, 0x6639, 0x548B, 0xD633, 0xB0BE, 0x387A, 0x71EE, 0xFFBE, 0x88A4, 0x2D6D, 0xC0F8, 0xC9C8, 0x3E9C, +0xC461, 0xF1DC, 0x5D38, 0xFFA4, 0x3AA0, 0x997B, 0x84B5, 0x0A15, 0xCB95, 0x8D2A, 0xB890, 0xA180, 0x9C09, 0x3F34, 0x9F67, 0x4DAF, +0x434F, 0x7E0B, 0x58DA, 0xD6F1, 0x8D29, 0x2416, 0x7EE7, 0x6594, 0xB003, 0xF0E1, 0x300D, 0x7ECD, 0x77D7, 0xEF75, 0x8E1D, 0x192B, +0x3DF1, 0x9843, 0x080F, 0x46B5, 0x7CA7, 0x775A, 0x7443, 0xA7BD, 0xB715, 0x17F9, 0x3CCD, 0x5E43, 0xD410, 0x632B, 0x78BA, 0xABE8, +0x5345, 0x86C7, 0xCED0, 0xFCAB, 0xA012, 0xB5B1, 0x9790, 0x0AE1, 0x3883, 0x63FB, 0x70D3, 0x747D, 0x9819, 0x9FE2, 0x4662, 0x71F2, +0x274A, 0x22E2, 0xF756, 0x9D8D, 0xB6AE, 0x5532, 0x7552, 0x414E, 0x3295, 0xA887, 0xA021, 0x4E0D, 0x0C3B, 0x870A, 0x40D6, 0x912A, +0xACBA, 0x217A, 0xBCD6, 0x1564, 0x4B02, 0xC52C, 0x3F44, 0xDFCB, 0xB0FA, 0xE2F4, 0xBF60, 0x8214, 0xC2A3, 0xB06F, 0x01B7, 0x5645, +0xDEDA, 0x4B7D, 0xA261, 0x249C, 0xF0A9, 0xBB13, 0x85A4, 0xECE6, 0x4E15, 0x3254, 0x247C, 0xB1CE, 0x4422, 0xDB15, 0xA70B, 0x776D, +0xFC98, 0x0A9B, 0x52E2, 0x9656, 0xD2D5, 0x3201, 0x43F2, 0x1D61, 0x3A6C, 0x1D90, 0xECCD, 0xA264, 0xA248, 0x12AF, 0xD829, 0x8DF3, +0xAE8D, 0x3B4E, 0x9041, 0xA359, 0x2299, 0x10DB, 0x80F1, 0xA1C4, 0xFD83, 0x50C4, 0xEB36, 0xE0B8, 0xCCB8, 0x9FAD, 0x7ED7, 0xA6A7, +0x0367, 0xAD26, 0x20E4, 0x7F99, 0x39C5, 0x429C, 0xEB26, 0xC84B, 0xB215, 0x9C9F, 0x237E, 0x540D, 0xF8F2, 0x3D22, 0x9FFC, 0xAA44, +0x571D, 0x52D1, 0xC576, 0x1A48, 0x649E, 0xFEFA, 0x7007, 0x0C6C, 0x8103, 0xCA17, 0x6F6B, 0x1F7B, 0x84A1, 0xC3B2, 0x990A, 0x40E0, +0x136D, 0x55EA, 0xB6EE, 0x55C3, 0x14FE, 0xD33B, 0x0251, 0xA73E, 0x3A95, 0x0F85, 0x63A0, 0x5EBD, 0x173C, 0x4DB5, 0x5783, 0xC29D, +0x4DA6, 0xE870, 0x3A2F, 0xC170, 0xAE97, 0xDC92, 0x7116, 0xEA9F, 0x0483, 0x7569, 0xF387, 0x0F35, 0x5C8A, 0x2793, 0xA166, 0x7A22, +0xEC92, 0xF257, 0xC4E8, 0xBC0C, 0xFFEE, 0xA3A6, 0xAA85, 0x7214, 0xB2EC, 0x8E8A, 0xAC13, 0xA8D4, 0x4D86, 0x6238, 0x1056, 0xE52A, +0xB436, 0x81EF, 0x6F18, 0x7861, 0xE890, 0x32B3, 0x81E0, 0x4737, 0x7803, 0xEFBA, 0x77DA, 0xF0F6, 0x1493, 0x7B8C, 0x46BB, 0x9C65, +0x3379, 0xB479, 0x8AF1, 0x0177, 0x4E88, 0xE07E, 0xC0B4, 0x79D4, 0x3B9E, 0x39BA, 0xE21C, 0x4BDD, 0xD8AB, 0xAC9B, 0xD776, 0x132F, +0x78D0, 0x8D39, 0xD496, 0x670B, 0x2A8E, 0x9842, 0x7334, 0x3772, 0x1F88, 0x1B9E, 0xDA54, 0x2FA9, 0xFCD7, 0xFFDA, 0xD1BE, 0x0FA6, +0xCC86, 0x13C4, 0xF8F7, 0xE8B8, 0xA598, 0x90E3, 0x6860, 0xACFE, 0xB3E7, 0xB8B5, 0x2DAF, 0xBDB4, 0x8211, 0x8316, 0x90A3, 0x3498, +0x8140, 0xE4A6, 0x81A1, 0xDE1A, 0x6C89, 0x7663, 0x83C2, 0x9ADA, 0x6308, 0x814D, 0x5E09, 0xD06A, 0xB4CE, 0xA3C5, 0x3663, 0xE9E1, +0xDC8C, 0xEB08, 0x6EFD, 0xC2E2, 0x88A3, 0x0144, 0x8117, 0xC38B, 0x3B67, 0x2BAF, 0x6D71, 0xB704, 0x6DDF, 0xF381, 0x58DC, 0x5C41, +0x9BFB, 0x5E07, 0x7EF8, 0x0522, 0xA680, 0x540B, 0x82D3, 0x7C29, 0xE688, 0x3E33, 0xC2E5, 0xC024, 0x6CE5, 0x47E4, 0x0E0F, 0xD323, +0x2373, 0x4CB5, 0x1CFB, 0x2B2D, 0x63B3, 0x71D9, 0x29C3, 0x16A1, 0xB31E, 0xAAA0, 0xA2C2, 0x416D, 0x3765, 0xDC0C, 0x1F09, 0x7BF6, +0x626B, 0x3798, 0x2BCF, 0xBC33, 0xE087, 0xBA2A, 0x7225, 0xD181, 0x9A08, 0xA4E0, 0x46B8, 0x3FE7, 0x24FC, 0x1BFB, 0xE9D2, 0x3564, +0x63FA, 0x1BFD, 0x023C, 0x2DA9, 0x09C2, 0x0CD7, 0x2267, 0x4361, 0x31D0, 0xF437, 0xBCA3, 0xCA1D, 0x4B0C, 0x078D, 0x8113, 0x4DEA, +0xA987, 0x5DFE, 0x1C16, 0x5809, 0x5253, 0x1774, 0x6660, 0x13F1, 0xF1C6, 0x81D5, 0xD761, 0x7A7A, 0xFEA9, 0xFD31, 0x86D3, 0x7893, +0x9C05, 0xBC40, 0x703A, 0xC466, 0xE2D2, 0x7C4A, 0x8AB3, 0x964B, 0xB9A9, 0x7538, 0x7310, 0x3C74, 0x11B6, 0x2800, 0xC6C6, 0x6A5D, +0x5017, 0x3461, 0x4921, 0xE118, 0x1454, 0xF955, 0x9696, 0xBE59, 0x8D46, 0x1B06, 0x533C, 0x85B9, 0xB6B0, 0xA12E, 0x610E, 0x9ED4, +0x8C0F, 0x448C, 0xE630, 0xEE3C, 0xCFE9, 0xEDED, 0x63C4, 0xF93E, 0x3129, 0xE622, 0x33CE, 0x36C4, 0xFE78, 0x5897, 0x0EB9, 0x0284, +0x4AAC, 0x8EC0, 0xB678, 0x3A20, 0xDE5D, 0xDB3D, 0x9787, 0x58AA, 0x08C6, 0xA478, 0xCFD0, 0x95F7, 0x6E9B, 0x450F, 0x5962, 0xA416, +0x73F0, 0xE331, 0x9436, 0x07F3, 0x24F9, 0x9D70, 0xCB10, 0x2C14, 0xB950, 0x672D, 0xFC7D, 0xC0AD, 0xA4C2, 0x771A, 0x496C, 0x2533, +0xB33C, 0xE75F, 0xE34F, 0x8331, 0x985A, 0x351C, 0x6771, 0xF502, 0x7446, 0x3EAB, 0x4B8D, 0x6A34, 0x2682, 0x1910, 0xBEBF, 0x4251, +0xAC1B, 0xA51F, 0xDA2F, 0xBA88, 0x959F, 0xDEA8, 0xA121, 0x27D4, 0x3022, 0xD01D, 0xB272, 0x23A4, 0x31EF, 0xB9B9, 0x8E4C, 0xD336, +0x7FDA, 0xEB89, 0x58C1, 0x9C5B, 0x5A44, 0x9FED, 0x95A5, 0x8547, 0x13CD, 0xCA8F, 0xE603, 0xB56B, 0xCEC6, 0x9D46, 0x29BA, 0xD192, +0x53E4, 0x02A2, 0xA829, 0x5347, 0x7E8F, 0xAE35, 0x09F5, 0xF2FE, 0xB85B, 0x5112, 0x7DC1, 0xD5CD, 0x6B55, 0x9634, 0xC999, 0xF481, +0x864A, 0x8216, 0x0DF6, 0x254A, 0x1C43, 0x71CC, 0x6553, 0x28EF, 0x6F4D, 0x505C, 0x625E, 0x4AA8, 0x86DF, 0xC159, 0xCE67, 0x37D5, +0x43EE, 0xFA6E, 0x3E23, 0x791D, 0x53B4, 0x3F92, 0xE082, 0x9D8B, 0x30DB, 0xC208, 0x3D1F, 0xDF7D, 0x849B, 0xE6A3, 0x01E6, 0x9C58, +0x9CF1, 0x38B7, 0xF2AF, 0xFE72, 0xD64A, 0x53A4, 0x6442, 0xCE1C, 0xEACD, 0xEF22, 0xFEB2, 0x5AE6, 0x5EF4, 0x2578, 0xF60B, 0x0D17, +0xBC11, 0x5DD3, 0x4C25, 0x90D2, 0xB8A4, 0x4F0F, 0x4856, 0x48A1, 0xB8A2, 0x4307, 0xF2AC, 0x2914, 0xDE21, 0xC92E, 0x4633, 0xBBEF, +0x6561, 0x5128, 0xA798, 0x4763, 0x904D, 0xBD85, 0x94B4, 0x63B4, 0x964D, 0x75F1, 0x7AEF, 0xA525, 0x16ED, 0x7967, 0x11D6, 0xEB50, +0xEC33, 0x7632, 0xA211, 0x13E0, 0x2173, 0xB822, 0x34E0, 0x8A0B, 0x3234, 0xBC63, 0xA101, 0x0964, 0xBECA, 0x6BEE, 0x9FAD, 0x6059, +0x1536, 0x211B, 0x95B8, 0xC0A6, 0x427D, 0x164D, 0x91E1, 0x2E96, 0x25DB, 0x1761, 0xB5A5, 0xF453, 0x9E77, 0x3DDF, 0xC80A, 0x3A9A, +0x13CC, 0xD18F, 0xD017, 0xFA2F, 0xCA63, 0xC8BF, 0x9C34, 0x5F21, 0xBA4D, 0x3D6C, 0x6EB2, 0xFF0D, 0xE470, 0x4463, 0xD878, 0x47EE, +0xECA6, 0x4884, 0xC08F, 0x79B7, 0x047A, 0xF86C, 0x6117, 0x833E, 0x595B, 0x8DB2, 0x31F8, 0x0B90, 0xD66E, 0x61C0, 0x2FD7, 0xDCDD, +0x03C6, 0x2943, 0x461D, 0xD075, 0xE758, 0x5918, 0x7543, 0x3054, 0x32CD, 0xAE76, 0x2E6C, 0xF5BD, 0x0BBE, 0x34F4, 0x1007, 0x2F37, +0xF61D, 0xF225, 0x3FD6, 0xA28F, 0xCE73, 0xDA04, 0x6006, 0x65CD, 0xDCDB, 0x32CC, 0xAD14, 0x1BDE, 0x0E45, 0x85E1, 0x17BB, 0xE61F, +0xFC39, 0x8EFE, 0x341B, 0x39BA, 0x0C48, 0x2985, 0xDD97, 0xE57E, 0xBAB4, 0x2F79, 0xE1DF, 0x03D4, 0x5104, 0x1B79, 0x57D2, 0x0880, +0x0F8D, 0x9BBA, 0x6AE1, 0x1B9E, 0x8874, 0x3425, 0x90F0, 0xC865, 0xA05B, 0xA81F, 0x2949, 0xE41D, 0x465C, 0xD9FE, 0xF066, 0x0058, +0x23D2, 0xC8D0, 0x7A02, 0x84C1, 0xBD2E, 0x6A5D, 0xB7A6, 0xEEBE, 0x33C6, 0x9849, 0xAFD0, 0xE0DD, 0xC429, 0xD5DA, 0x90F2, 0xFE85, +0xC36B, 0x976C, 0xD16F, 0x04F4, 0x4A6A, 0x9ED4, 0x6224, 0xB820, 0xC7D0, 0x5C3B, 0x84C7, 0x3B42, 0xAE18, 0x5DA8, 0x6763, 0x939B, +0xDC2D, 0x6F6D, 0x0804, 0x6D0E, 0x563E, 0x1AC0, 0x1F72, 0x3B94, 0xBBBF, 0x1946, 0x6063, 0x16B4, 0x9E93, 0xFA57, 0xD727, 0xD932, +0x3AFB, 0xFEF3, 0x8458, 0xBDE5, 0x0C6D, 0x70F5, 0x92D2, 0x1588, 0xBB50, 0xC6E8, 0x009A, 0xC481, 0xE601, 0x01B7, 0x80BE, 0x75DC, +0xCC27, 0x97A1, 0x9E0E, 0x4754, 0x7B05, 0x8B67, 0xF605, 0x54E1, 0x333F, 0x8A5C, 0x20BD, 0x1C04, 0x715D, 0x8AC0, 0x1F58, 0xB1EB, +0x2040, 0x4452, 0x7B01, 0x66DD, 0xC664, 0x529D, 0x93C3, 0xF37B, 0x3ED0, 0x7996, 0x9C76, 0xD4CF, 0x3E2A, 0xE596, 0xB8D2, 0x4F1E, +0x33D8, 0x301C, 0xEC08, 0xAE9B, 0x9015, 0xFBFA, 0x5ED1, 0x81CB, 0xBB46, 0x0B53, 0xEF0E, 0xEA6D, 0x2BE7, 0xA54D, 0x588D, 0x965C, +0xD9D0, 0x2DCD, 0x2E36, 0xDFCC, 0x8063, 0xBCBC, 0x6335, 0x5ED3, 0x4250, 0xE345, 0x182B, 0x2B0C, 0x7633, 0xB989, 0x5F0F, 0xA959, +0x6C63, 0xC063, 0x526D, 0x513B, 0x58A0, 0x7536, 0x0F69, 0xC1BE, 0x3618, 0x649F, 0x87E7, 0x5CE4, 0xB08B, 0xDF4B, 0xBC6F, 0x168C, +0xC0EE, 0xA434, 0x1F41, 0x795C, 0x720F, 0x1506, 0x9969, 0x693F, 0x49F7, 0xBCB6, 0x12E9, 0x7623, 0x3F15, 0x6CE6, 0x1B61, 0xFC81, +0x939C, 0x67DE, 0x206B, 0xB8F4, 0xB3B0, 0x05AB, 0xA7BD, 0x1494, 0xBE61, 0xE590, 0x4854, 0xAA8D, 0xEA31, 0xF0C6, 0xFBBA, 0x313B, +0x397E, 0xCDAB, 0x4A76, 0xC04D, 0x3408, 0xFB27, 0x699F, 0xC497, 0x3577, 0x2665, 0x96B4, 0x89E0, 0x770C, 0x30F9, 0xFCBC, 0x1AC6, +0x8396, 0x9F12, 0xB661, 0x92AE, 0x9E8B, 0x940C, 0x4ECA, 0x7BE1, 0x36E1, 0x768A, 0x088A, 0xA03D, 0x05FF, 0x8051, 0x33C5, 0x59E2, +0x23C5, 0x770A, 0xB52F, 0x1B75, 0xFE01, 0xD94F, 0x688E, 0x2264, 0xB0F7, 0x991B, 0x0A58, 0x99AE, 0xAF27, 0xD4D8, 0xC4D0, 0x2004, +0x7C69, 0x38AF, 0xC467, 0x7B61, 0x759B, 0xE491, 0xE61E, 0xAECB, 0xBE98, 0xF785, 0xC739, 0x5654, 0x5F45, 0xAFDC, 0x7410, 0x7E55, +0xDA55, 0x1E95, 0xE018, 0xA264, 0xB806, 0x376E, 0x9878, 0x8FCC, 0xCC77, 0x03C8, 0x8E05, 0x666D, 0xE73E, 0x88C7, 0x230D, 0xC643, +0xA382, 0x7E81, 0x8A7E, 0xC61A, 0xC4FD, 0xA749, 0x8C2F, 0xA50B, 0x37EA, 0x40B5, 0x8936, 0xB55D, 0xCA68, 0x617F, 0xB330, 0x8850, +0x16B3, 0x1243, 0x5B96, 0xBD0E, 0x7A18, 0x9D9F, 0x6AAC, 0xFF89, 0xABFC, 0xF7EC, 0x238B, 0xB932, 0x0F7A, 0x0C91, 0xB408, 0x5580, +0x5C7D, 0xD93C, 0xF878, 0x2FD5, 0x2FED, 0xD7D4, 0x24FB, 0x7021, 0xBF93, 0xC1BA, 0x4685, 0x4334, 0x90D2, 0x4EF2, 0xF4E5, 0xAFE7, +0xEF23, 0x7BDC, 0x0EA1, 0x041F, 0x3C1F, 0x73BE, 0x9A5A, 0x5221, 0xD77C, 0x6D3F, 0xA7D6, 0x46F1, 0x4763, 0x508E, 0x53D5, 0xB3C7, +0x4C77, 0x21F0, 0x6E72, 0x058F, 0x02D6, 0x4673, 0xCD8C, 0x1F54, 0x3713, 0x52A0, 0x065B, 0x4984, 0x7F1C, 0x3E65, 0x3C9A, 0xC73E, +0xF598, 0xC17D, 0xF1F8, 0xDF27, 0xF616, 0x51D6, 0x9B4B, 0xB4D2, 0x52FC, 0xD241, 0x3B3A, 0x56BF, 0x9F48, 0xB4AF, 0x6BB9, 0x8905, +0xB388, 0x864D, 0x1C74, 0xEC40, 0xE9C6, 0x36EE, 0x6558, 0xCA7E, 0xBF6A, 0xD3AF, 0xC9E8, 0xBFED, 0x25A6, 0x11E8, 0x7B4F, 0xE089, +0x0C08, 0xA8E2, 0xA4CF, 0x6636, 0xB011, 0xBFF7, 0x6BBD, 0x197A, 0x2E7C, 0x4892, 0xBF67, 0xA97C, 0xD751, 0xE8B0, 0x8C64, 0x6F42, +0xE3AA, 0xADAC, 0xF240, 0x6F72, 0x7011, 0xC1C3, 0x19EE, 0x08D4, 0x35FC, 0x2CCB, 0x9A45, 0x9F9D, 0x454D, 0xB328, 0xA2D1, 0x3B3F, +0x7C5F, 0xD8D1, 0x96EF, 0xE1F3, 0x6221, 0x143F, 0x6EE8, 0x5458, 0x9DEA, 0x2A02, 0x702D, 0xF80A, 0x5FCB, 0xAC08, 0x55B8, 0xBE88, +0x1C55, 0x0A11, 0x8046, 0x86BD, 0x9B01, 0xB15E, 0xB13A, 0xDDFE, 0xBD85, 0xADC4, 0x55F6, 0x69F4, 0x1FF7, 0x9CA5, 0xE504, 0x1C88, +0x85CF, 0xB14E, 0xC3D8, 0x58E2, 0x2426, 0xFA1E, 0x9E1E, 0xF9F0, 0xE16A, 0xB0D1, 0xF470, 0x07C9, 0x17D2, 0xF017, 0xB265, 0x58CF, +0x0C5F, 0xF2DD, 0x164C, 0xACE7, 0xB63A, 0x20F9, 0x584D, 0xB28B, 0x3505, 0x3EDE, 0x1528, 0x6344, 0xF039, 0xEC32, 0x2D7B, 0x7451, +0x9F74, 0x0BEF, 0x3C81, 0x83DA, 0xEE2F, 0xD876, 0x9F0F, 0x1F03, 0x64EA, 0x0FAF, 0x689C, 0x1787, 0xCFF9, 0x1436, 0x8A09, 0x620D, +0xF3A0, 0x5560, 0x644A, 0x4528, 0x5D2A, 0x5064, 0xF099, 0x67A1, 0xBD7C, 0xBFD1, 0xDA9B, 0x952D, 0xAA83, 0xC3BF, 0x6AAE, 0x53E6, +0x66E4, 0x6270, 0x69B6, 0x3ACB, 0xA828, 0x3657, 0x6FF9, 0xB2AB, 0x186A, 0x957C, 0xECC1, 0xE844, 0x87E0, 0x4829, 0x6DD4, 0x844A, +0x2C4B, 0x134E, 0x2A53, 0xF853, 0xEC4C, 0x13BC, 0x9AA8, 0x6C61, 0x340E, 0x08E1, 0x9494, 0x7624, 0x3FAE, 0x0D1C, 0xAD8E, 0xA5E3, +0xAA02, 0x6EA6, 0xD238, 0x25A1, 0x6A36, 0x9CA6, 0x9D2D, 0xC2EE, 0x7FE1, 0x6158, 0x414F, 0x371B, 0x6FA4, 0xCC7F, 0xFAD1, 0x1789, +0xD3B4, 0xB4F3, 0x5855, 0x119C, 0x075C, 0x6321, 0x327C, 0xB94B, 0xBC77, 0x89EE, 0x5B27, 0x804D, 0x6514, 0x2291, 0xEA5B, 0x8254, +0x5392, 0x0739, 0x870F, 0x9CB0, 0x2C31, 0x7287, 0x6DDB, 0x6F46, 0x0361, 0xFB8B, 0xC512, 0xC8D8, 0x27BD, 0x9060, 0x1D0C, 0xF1CE, +0xC3BE, 0x4C3F, 0xCE5F, 0x3BC6, 0x2A67, 0xF286, 0xDB0B, 0xD63E, 0x34F7, 0x1AF4, 0x1BF9, 0x8AFD, 0x8ADA, 0x5206, 0x2224, 0xEA8D, +0x4929, 0xBD98, 0x7856, 0x4788, 0xE638, 0x50EF, 0x6CCA, 0x89B5, 0x86E1, 0x44F5, 0x59FE, 0xD896, 0xFF96, 0x7441, 0x2560, 0xCB0C, +0x3C41, 0xEB82, 0xBC59, 0xD209, 0xC177, 0x821B, 0x73DF, 0x0314, 0xBC8E, 0x9BFB, 0xD44A, 0x7C94, 0xD060, 0x7D8B, 0x65F1, 0xCD3A, +0xB0B9, 0xD407, 0x2D61, 0xFE99, 0xA03F, 0xBECE, 0x9C3C, 0x241D, 0xFA61, 0xDE26, 0xDDA3, 0x2755, 0xB78F, 0x285E, 0xC2BD, 0x2D4B, +0x42AC, 0xE2AF, 0xF3D1, 0x36CE, 0xFE85, 0x089A, 0xCC43, 0x7DBE, 0x2160, 0xA7DA, 0x273B, 0x8C16, 0x7208, 0xF50F, 0x0E1B, 0x86B5, +0xCEFA, 0x6954, 0x17E4, 0x9FF7, 0x939B, 0x1A58, 0x4440, 0x1D5E, 0x517D, 0x0E9F, 0x6A47, 0x53AC, 0x5B37, 0xA9DE, 0xFB62, 0x50E2, +0xBD53, 0x4512, 0x81D7, 0xDF01, 0x1595, 0x7807, 0x6497, 0xA894, 0xA919, 0x26D5, 0xE888, 0x7A7F, 0x28B2, 0xDA82, 0x49CE, 0xA102, +0x376A, 0x00CB, 0x42D3, 0x26E6, 0xD59C, 0xF479, 0xB4B6, 0xB0F6, 0x2DFD, 0x944C, 0xEE1A, 0xAC6F, 0x132E, 0xF5C1, 0x1CBF, 0xB6A5, +0xAD59, 0xBDDE, 0x17DD, 0xF55B, 0x38AE, 0xE9A0, 0x8DE0, 0xC7E1, 0x2199, 0xB5CF, 0xA856, 0x70CF, 0xC77C, 0xAA15, 0x81B1, 0xC9DB, +0x2DD1, 0xBA6A, 0xBD8A, 0xFDDE, 0x1F95, 0xD611, 0xB5A7, 0x5605, 0xA87D, 0x2B32, 0x72F6, 0xBC21, 0xCB05, 0x11E0, 0x24D3, 0x8C67, +0x52A6, 0x1A63, 0x65DB, 0x1C94, 0xD3BE, 0x993D, 0x2534, 0x12CB, 0xA9E0, 0x34C0, 0x67E5, 0x86A6, 0x9DC6, 0x8598, 0xC664, 0xEE6C, +0xD441, 0xD3F5, 0xE8BD, 0x44CF, 0x5992, 0x3830, 0x4551, 0xFBAD, 0xD4FD, 0xB1E1, 0xF6AB, 0x43E2, 0x831C, 0x4DFF, 0xC30E, 0x6A20, +0x8D4D, 0x5C4D, 0x2BC2, 0xA1EF, 0x62D8, 0xDAE5, 0x4F05, 0x190B, 0x2092, 0x83F0, 0x29EA, 0x65AF, 0x08EB, 0x4B3B, 0x0144, 0x1869, +0x18A7, 0xDF23, 0x5333, 0x5BA5, 0x9B8C, 0x92C1, 0xB785, 0x8BE8, 0xB376, 0x45C5, 0x5B25, 0x9CBD, 0x6B58, 0xC9A9, 0x540B, 0xF9E3, +0x72B2, 0xFBF0, 0x59C4, 0x4820, 0x89C8, 0xAA78, 0xE7D1, 0xCC21, 0xA8EB, 0x02FF, 0xE659, 0x93C6, 0x5251, 0x64B6, 0x4691, 0x3FDE, +0xE137, 0xB6BC, 0x0604, 0xE2B4, 0xDD8B, 0x7CE0, 0x4773, 0x2640, 0xCFF6, 0xDF16, 0xDF78, 0x637E, 0x2341, 0x95B6, 0xB3D6, 0x1FA4, +0x62B8, 0x033C, 0xCFCE, 0x627A, 0xA4F3, 0x3BDF, 0x0EA6, 0xA354, 0x206B, 0x91E5, 0xA687, 0x9976, 0xBD9F, 0x1421, 0x8EEE, 0x5707, +0xFB8C, 0x0C1D, 0xF95D, 0x398C, 0x1782, 0x5E88, 0x4662, 0xC0B3, 0x4A76, 0x6068, 0x4394, 0x7330, 0xFB6A, 0x7197, 0x8BBA, 0x2566, +0x9D47, 0xA481, 0xBDC8, 0x8BB5, 0x4FE3, 0x4B42, 0xA672, 0x767E, 0xA812, 0x10EA, 0x6934, 0x6F1F, 0xE725, 0x3BAC, 0xC93B, 0x70B0, +0x021C, 0x6582, 0xAC6A, 0x809D, 0x5185, 0xB0A9, 0xB694, 0x6D1B, 0x36F6, 0xFABB, 0xC7C9, 0x8CF3, 0xB373, 0x2D88, 0x6C67, 0xC321, +0xCD65, 0x8F60, 0x53FC, 0x0887, 0xD634, 0xBC6F, 0xDAC4, 0xB4D4, 0x2284, 0xEF8E, 0x3A99, 0x4F6F, 0x87CE, 0x996C, 0x10A5, 0xAB06, +0x724B, 0x15B1, 0x9E4A, 0x0758, 0x83B5, 0x1B61, 0xB3C1, 0x2039, 0x8560, 0x982B, 0x0883, 0xDD85, 0x3BE9, 0x6930, 0xB5BB, 0x12EB, +0x329A, 0x28DD, 0x21FA, 0xE148, 0x3D24, 0xCCF2, 0x7210, 0x61FE, 0xAAFD, 0x6E81, 0xF52A, 0xB906, 0xDD74, 0xB6E1, 0x5770, 0x8CB1, +0x8BDB, 0x7C2E, 0xCB7D, 0xBE49, 0xC5B2, 0xF540, 0x4337, 0x8D91, 0xF9E0, 0x02F8, 0x8CDE, 0x2246, 0x73F0, 0x352F, 0x5266, 0xF4AC, +0x2290, 0xD011, 0xB7F0, 0xCB12, 0x101F, 0x5D55, 0x9B67, 0x0E8B, 0x227D, 0xFD9B, 0xB5F4, 0xB3B6, 0x32BA, 0xC676, 0x9F0F, 0xE468, +0x9160, 0xC68F, 0x3424, 0x6571, 0x0FBB, 0xD728, 0x4226, 0x6B62, 0x7C60, 0xBD86, 0x1032, 0x3208, 0xABDB, 0xD10E, 0x6A0A, 0xCE6E, +0xDD6F, 0x77AC, 0xC5F6, 0x22DD, 0xFB0F, 0x2DC8, 0x33B3, 0xDBA1, 0xAA04, 0x7C94, 0x7A47, 0x45DF, 0x6800, 0xE9FB, 0xD8DA, 0xC3DF, +0x68F0, 0xAF10, 0x6113, 0xDC60, 0x49BC, 0x3909, 0xB2D0, 0xC6CA, 0x00E0, 0x2755, 0x946F, 0xCDCB, 0xE3C2, 0x8D11, 0x8DD7, 0x2829, +0x0284, 0x3182, 0x8BEF, 0x9FA6, 0x4A69, 0x6E10, 0x5982, 0xD061, 0x2376, 0xCBA4, 0x3448, 0xA6D6, 0xFD2D, 0x2758, 0x1FFA, 0x35DA, +0xA416, 0xA3C6, 0xDA9D, 0xC30A, 0x8BA2, 0x93F8, 0x4004, 0xB68F, 0x676B, 0xD371, 0x39E1, 0x1294, 0x0B86, 0x0947, 0x1AD2, 0xBBEA, +0xFD7B, 0x963F, 0xF9E9, 0x7669, 0xA179, 0x1E8D, 0xF156, 0x054B, 0xAB0F, 0x4AAB, 0xFBFB, 0x50BF, 0xA797, 0x08D5, 0x582F, 0x126D, +0x5D86, 0xCA59, 0x8FAA, 0x7A1B, 0xCDA5, 0x7DD9, 0xB0F2, 0x1B27, 0x1BEB, 0x49A2, 0xBDBC, 0xED57, 0x439F, 0x5558, 0xFD0F, 0x5DAD, +0xED71, 0x6EF3, 0x6FE3, 0x5C33, 0x8C42, 0x8F2A, 0x1821, 0x6A3E, 0x238F, 0xD9B1, 0xBB25, 0x5A0F, 0x4859, 0x7842, 0x9050, 0x7AB4, +0x473D, 0x70F8, 0x70F3, 0xA123, 0x07AC, 0x5FB1, 0xB1E3, 0xFDD4, 0x9E6B, 0xF6DC, 0x2150, 0xFD19, 0x9BB4, 0xB179, 0xC563, 0x676F, +0x128E, 0xC94E, 0x1DE5, 0xB5FC, 0x6752, 0xFFB7, 0xB0F5, 0xBF14, 0xABF6, 0x58BE, 0x7496, 0xAC66, 0x12E3, 0x57CF, 0xD785, 0x5D03, +0xBEAD, 0x1967, 0x25C4, 0x1832, 0x41AB, 0xB190, 0x4115, 0x507C, 0xE2EB, 0x6C0F, 0xA50D, 0x02DA, 0xD3AD, 0xED66, 0x22BE, 0x8128, +0x4D35, 0x3931, 0xA380, 0x4A5C, 0xAFE7, 0x717B, 0xE14D, 0xFF61, 0x26A8, 0x3772, 0x1C7F, 0x1AEF, 0x898F, 0x2DC9, 0x3367, 0xDDD3, +0xA793, 0x909E, 0x14B3, 0xBEA2, 0xB3C7, 0x182A, 0xBB49, 0x6790, 0xE94C, 0x33FC, 0xAFCF, 0x5FF5, 0x9A8B, 0x3809, 0x66D0, 0xD4F0, +0xB2CA, 0x9E8C, 0xD186, 0xA393, 0x44F7, 0x01E6, 0x4999, 0x2A4B, 0xAED1, 0xB67D, 0xD3CC, 0xEC86, 0xD335, 0x0244, 0x74B2, 0xFA64, +0x5E03, 0xF901, 0x4184, 0x07B3, 0xF5C0, 0xF60B, 0x4BBF, 0xCA38, 0x95CC, 0xA92F, 0x2B92, 0xA036, 0xD292, 0x6416, 0x810D, 0x32B7, +0xA2C0, 0x6640, 0x478C, 0x89C9, 0x69CC, 0x9041, 0xA0EE, 0x453E, 0x2651, 0x2567, 0x9312, 0xE636, 0x3CFB, 0x72D3, 0xBCCD, 0x92BD, +0x44B8, 0x43A0, 0xBEDD, 0xDC8B, 0x3FC9, 0xD463, 0x4AAE, 0x2CCB, 0x104C, 0x1651, 0xB77E, 0xB078, 0x0AB9, 0x8037, 0xB961, 0x0875, +0x5D3F, 0xC1FD, 0x358A, 0x6006, 0x82DC, 0xE0DC, 0x083A, 0x9014, 0xAE28, 0xA468, 0x5CA1, 0x105F, 0x6641, 0x5D5E, 0xFB18, 0xB50A, +0xBD28, 0x2A3F, 0xEBEA, 0x659A, 0x79CE, 0x3A42, 0xBA58, 0x8163, 0x6CCC, 0x8C82, 0x3323, 0x4FBB, 0x42A0, 0xDC28, 0x5EBC, 0xEE32, +0x82D4, 0x87D3, 0x7B93, 0xDD7D, 0x33BA, 0xA304, 0x620B, 0x9BD4, 0x275A, 0x1358, 0x12AE, 0xF356, 0xF36C, 0x93FD, 0x3C38, 0x430F, +0x71CE, 0x26E9, 0x5064, 0x7AF0, 0xBBD0, 0x90B3, 0x488C, 0xF126, 0x0B47, 0x78A6, 0x9EAD, 0x90E4, 0xAAE4, 0x587E, 0xC9B9, 0x7DF1, +0x7D2B, 0x206E, 0x0995, 0x34B2, 0xD8AA, 0xD399, 0xCADF, 0x4EFE, 0xAF23, 0x9257, 0xDD1D, 0x053F, 0xA9D6, 0xBC70, 0x7BED, 0x64B8, +0x885E, 0x4F76, 0x0553, 0xC3E1, 0xFDD7, 0x7E92, 0xB87A, 0x5C8E, 0x77C7, 0xE275, 0x1AF0, 0x6F27, 0xE2FD, 0x0461, 0x2E64, 0x9BB6, +0x6D21, 0xD8A2, 0x9F9F, 0x1EE8, 0xF591, 0x423E, 0x23A8, 0x218B, 0x27A3, 0x014D, 0x9DC3, 0x0F8F, 0x4618, 0xCCE7, 0xB392, 0x0C61, +0x92E5, 0xF5D7, 0xFA0A, 0x18D9, 0x37DE, 0x5CFA, 0xB96B, 0xBA7D, 0xF247, 0x5D0B, 0x861C, 0x7F69, 0x3AD6, 0xE040, 0x1608, 0xA174, +0x92DE, 0x7F1F, 0xED99, 0xF727, 0x1E81, 0x32A3, 0x8B7C, 0xF4A1, 0xAFDA, 0x8042, 0x5270, 0xF9E6, 0x1CA2, 0xE36A, 0xF447, 0x2BD6, +0x6B75, 0x9C48, 0xAF3D, 0xA1C8, 0x71D9, 0xB2DB, 0x499D, 0x17D5, 0x8EC7, 0xC7D8, 0x0241, 0x80AA, 0x72CF, 0xBC5F, 0xF1D5, 0x4733, +0xC2FC, 0x54FE, 0x03AD, 0x7415, 0x8756, 0xC58E, 0xF7CA, 0x360B, 0x254C, 0x7F26, 0x01DD, 0xD996, 0x7C49, 0x41AA, 0x2DD9, 0xF060, +0x1B22, 0xEC7B, 0x9D1D, 0x260D, 0xA3E9, 0x1913, 0x4CC8, 0x5AF7, 0x3D51, 0xA548, 0xCD0B, 0xD1DC, 0xFA55, 0xF8E7, 0x2809, 0x96F9, +0x3D03, 0xF343, 0x71AB, 0x9DDA, 0x6C46, 0xB513, 0x5F1E, 0xE321, 0xAD35, 0xFE29, 0xCE6E, 0x2FFF, 0x26F3, 0x6E27, 0x6A0C, 0xD7D7, +0xE2B2, 0x85E4, 0xC82A, 0x9F1C, 0xE5EE, 0xF732, 0xBC3E, 0xF75F, 0x41D1, 0x3F9B, 0x4956, 0x2E1F, 0xB24C, 0xA4F8, 0xCFD4, 0x70BE, +0x2D09, 0x0B8F, 0xE7A1, 0xB780, 0x417D, 0x24B4, 0xB669, 0x8C54, 0x25B5, 0x6D33, 0x8EB0, 0x254F, 0xC93D, 0x1EB0, 0xA273, 0xBF0E, +0xF809, 0x3F45, 0x3773, 0x4424, 0x2FE7, 0xD55A, 0xBD2F, 0x11AC, 0xC451, 0x80E5, 0xD5BA, 0x3E51, 0x6A67, 0x40D9, 0xF7B8, 0x4A7C, +0xD2F6, 0xAC32, 0x95A7, 0x5E4F, 0xAA6D, 0x5429, 0x1EBD, 0x597E, 0xADCC, 0xEC3C, 0x4103, 0xD326, 0x9387, 0x313D, 0xE5A6, 0x98B9, +0x0199, 0x56DA, 0x6244, 0xFD35, 0x69E0, 0x3B7B, 0x4DD9, 0xBC04, 0xB8D1, 0x1A36, 0x51E7, 0xC192, 0x227E, 0x1CC6, 0x1065, 0xAC3B, +0x0D1D, 0xEA1C, 0xDBBE, 0xE334, 0x1B0B, 0x17F1, 0x748C, 0x52BE, 0x24BE, 0x5B0C, 0x0F0C, 0x302F, 0x06AA, 0xFF9E, 0x2286, 0x6EBC, +0xCD7F, 0x5A0C, 0xD9CA, 0xE25F, 0xABFE, 0x918A, 0xBF0D, 0xCC41, 0xDF5A, 0xEE12, 0xFC69, 0x1ECD, 0xCA3A, 0x9890, 0x8760, 0x3FF8, +0xF2E2, 0x4DA1, 0xA9B8, 0x0AFB, 0xF01B, 0x676C, 0xDC58, 0x8794, 0xACC7, 0xDA03, 0xC0BF, 0xC646, 0x5C10, 0xD013, 0x6553, 0x490B, +0x34EF, 0x3393, 0x8CFD, 0x5B4E, 0xEDF9, 0x7FAB, 0x4FFB, 0x61E9, 0xA3DA, 0x74C1, 0x7834, 0xE10E, 0x8223, 0xC48F, 0x60BD, 0xD9BF, +0xE2E8, 0xB56D, 0x3FB2, 0x20A1, 0xDD20, 0xF6CB, 0x352F, 0xE8E1, 0x2447, 0x4919, 0x8061, 0xCCF6, 0xB3DE, 0xA084, 0xAD2C, 0x21D2, +0x2E54, 0x8932, 0x73A4, 0x8076, 0x27F0, 0x5DC3, 0x4EEA, 0x871A, 0x265A, 0xCBBF, 0xE4D8, 0xF140, 0x5A08, 0x20AE, 0x58D1, 0xE37D, +0x1D17, 0x12D0, 0x4DB4, 0xC96E, 0x3630, 0x8656, 0x9DFB, 0x3DCB, 0xAC3E, 0xC816, 0x4FD2, 0x3A9F, 0xE964, 0x8F09, 0xEAF9, 0x0665, +0xD7C4, 0xE0AD, 0x2693, 0x3967, 0x61F7, 0xB3E2, 0xBE1C, 0x2AB2, 0x5ADA, 0x516C, 0x6085, 0x0E83, 0x1211, 0x7CB1, 0xBF0C, 0x053A, +0x5D9E, 0x4598, 0x5373, 0xCFEA, 0x5C41, 0xFB58, 0x965F, 0x680B, 0x2EF0, 0x9681, 0x51B3, 0xB1EF, 0x950D, 0x5488, 0x74E3, 0x3079, +0x1C28, 0x8ACB, 0x114A, 0xDD5D, 0xD323, 0x1EBC, 0xAA59, 0xE8C2, 0x3114, 0x7459, 0xF15C, 0x4B1E, 0xC844, 0x9A7B, 0xD00D, 0x48CD, +0xA261, 0xE225, 0x2175, 0x2625, 0xB751, 0x8BC5, 0x3E8B, 0xBD21, 0xA689, 0x178E, 0x9E00, 0x4786, 0xCFB7, 0x7B05, 0x3336, 0x17CE, +0xE5B8, 0xE354, 0x447D, 0x644C, 0x9524, 0xF09D, 0x5AAF, 0x456A, 0x4D94, 0xEE8A, 0x7501, 0xB4DD, 0x805D, 0xC664, 0x37D0, 0xAE8A, +0xB26B, 0x1AE9, 0xB77F, 0x0C7F, 0x9A6A, 0x1A62, 0xD7FC, 0xD254, 0x2E09, 0x8494, 0xDEDE, 0x4D36, 0x2079, 0x0B92, 0xFB49, 0x7F17, +0xFF03, 0x59F5, 0xBB24, 0xBF74, 0x5F2D, 0xD2F5, 0x5BBE, 0xA399, 0xC814, 0x51F4, 0xE9ED, 0xA493, 0x5876, 0x2245, 0x0FBC, 0x9448, +0x4D94, 0xBD54, 0xC579, 0xE5B0, 0x717A, 0x6AFF, 0x7F28, 0x077E, 0xA670, 0x059B, 0x116D, 0xBB5F, 0x7AC3, 0x241F, 0xBC9C, 0x58A0, +0x0693, 0x306A, 0xEE13, 0x0665, 0x192A, 0x3CD4, 0xAB48, 0x0E31, 0xB494, 0xCB27, 0x6DB0, 0x5B50, 0x106F, 0x7E5A, 0xE861, 0x720F, +0x927F, 0xFB7A, 0x8B60, 0x58CB, 0xC01C, 0x2927, 0x1519, 0x0CBE, 0x2F02, 0xB2AB, 0x5F62, 0x5856, 0xEFEE, 0xEABC, 0x7BBC, 0xAEA5, +0xCA75, 0x3CBC, 0x559D, 0x190F, 0xDB34, 0x9625, 0x599C, 0x7E74, 0xD31F, 0x3F03, 0xC03E, 0x840F, 0xF82B, 0xFA0C, 0x7F64, 0xE1CC, +0x6D80, 0x5CC7, 0xF966, 0xB104, 0x2B0C, 0x59BA, 0xBDCD, 0xD994, 0xA77B, 0x33A4, 0x90D1, 0xAE3F, 0xB554, 0xC531, 0x3C69, 0x8912, +0x33E5, 0x5523, 0x00AA, 0xA01E, 0x9D33, 0x7804, 0xA96A, 0xD3DC, 0xAF9F, 0xA5D0, 0x4463, 0x7BCC, 0xB032, 0xA613, 0x98B9, 0x078B, +0x7D8A, 0xA40B, 0x6F6C, 0x9B5E, 0x0637, 0xC81D, 0x54BA, 0xB6E1, 0x2FFB, 0xA0BE, 0xD00F, 0xA48F, 0x5A9A, 0xB5A6, 0xF416, 0xE1CB, +0x295E, 0xEF82, 0xFFF3, 0x7B26, 0x573A, 0x5A6C, 0xA87B, 0x352F, 0x2A1F, 0x1AAE, 0xD88F, 0x6B82, 0x6819, 0x4232, 0xA0D5, 0x3D49, +0x8275, 0x03B6, 0x1D6A, 0x7291, 0xED27, 0xB880, 0xFC6E, 0x63CB, 0xA782, 0x21B1, 0x1FBC, 0x52E6, 0x0020, 0x9A2B, 0xB3C3, 0xC67C, +0xD0CE, 0x861D, 0xAAC4, 0xC237, 0x113D, 0xB44D, 0x588D, 0x9887, 0x569F, 0x807D, 0x5CD2, 0x9441, 0x2000, 0x1E2D, 0x4708, 0xDB0E, +0xD257, 0x2857, 0xF35E, 0xF1A3, 0x74F0, 0x4FAD, 0x80D8, 0xA161, 0x2D14, 0xDED5, 0x4C11, 0x7296, 0x60CB, 0x38EB, 0x6A5D, 0x1DCA, +0xA099, 0xF62E, 0x98E4, 0x45F2, 0xC30D, 0x1F85, 0x5DD8, 0xD5A5, 0xE509, 0xE2ED, 0x9398, 0xC537, 0xA89A, 0x5A95, 0x9ED4, 0x0AC4, +0x2DA8, 0x8FEA, 0x8158, 0x186C, 0x9FE0, 0x3F30, 0x280C, 0x744B, 0xA56D, 0x5FDA, 0x83A2, 0x84FF, 0x3A71, 0x1766, 0x2D88, 0x3A7D, +0x5909, 0x9FB1, 0xCDD3, 0xFCE3, 0x850A, 0xF1A4, 0xAD2E, 0x780D, 0x9989, 0x783E, 0x17C5, 0x3AF4, 0xE083, 0x068A, 0x7909, 0xEC83, +0x3DA2, 0x7726, 0x1752, 0x3236, 0xB2DB, 0xAE97, 0xC17B, 0x1B3E, 0x2DED, 0xCCC0, 0xC37C, 0x8E4F, 0xD5BF, 0x67F1, 0xE5F7, 0x52A4, +0x43B2, 0x2510, 0x328A, 0x27DB, 0x4F03, 0xD3CC, 0xAC3F, 0x9EFE, 0x1C09, 0xC740, 0x8B29, 0x2ABA, 0x38A8, 0xE2AB, 0x4165, 0xD641, +0xC25D, 0xD09B, 0x6554, 0xDBF9, 0x59CB, 0xDE0A, 0x69AF, 0xCE14, 0xA594, 0x4DCF, 0x0CCF, 0x7826, 0x8F05, 0x487C, 0xA222, 0x7513, +0xBA22, 0x4C8F, 0x67BD, 0x9ECA, 0x0904, 0x3DED, 0x5CC9, 0x3356, 0x6089, 0x5D93, 0x0F74, 0xD579, 0x70B1, 0xBEB4, 0xA6B8, 0x3006, +0x1DB6, 0x96B5, 0x2B4D, 0x6682, 0xE8AD, 0x9DD2, 0x039E, 0xC5D4, 0x2CE6, 0xFAFF, 0x42C0, 0x9B2F, 0x1A28, 0x86DF, 0x6502, 0x8316, +0x76C4, 0x4059, 0xDC33, 0x81A0, 0xCB1A, 0x971C, 0xAE1D, 0x4313, 0x0702, 0xA9B7, 0xA2FA, 0x0A26, 0x98F5, 0x3AE2, 0x31BD, 0xA3C5, +0xE249, 0x3108, 0x594B, 0x8F4D, 0x03BD, 0xED4F, 0xAB4A, 0x10FE, 0xA49F, 0x7BF0, 0x8D73, 0x6D46, 0x4092, 0xA952, 0x22D7, 0xA4A1, +0x8F54, 0x29C6, 0x8904, 0x38B1, 0x8D1D, 0x793D, 0x5EEB, 0xEEBB, 0x7B82, 0x3364, 0x26A7, 0xF5E5, 0xD0EC, 0x66FD, 0xD660, 0x4582, +0xF243, 0xC9C4, 0xCF41, 0xA517, 0x2E86, 0x7CE8, 0x423D, 0x7F8B, 0x2C1F, 0xE8EA, 0xCDAD, 0x67F6, 0xAF5C, 0xD9C5, 0xEAA8, 0xCC78, +0x95EF, 0x9367, 0x765D, 0xE389, 0x4714, 0x5B55, 0x5FFA, 0x0848, 0xFE02, 0x8C1A, 0xBA4B, 0xE5AB, 0x08C7, 0x82DC, 0xEE0C, 0x7F40, +0x0DBC, 0x6E79, 0xBD47, 0x4CD8, 0xC596, 0x0C75, 0xEAE9, 0xAAA1, 0xA466, 0x69E5, 0x021E, 0x919F, 0xF5E6, 0xF648, 0xAD7D, 0xEBCF, +0x6C7F, 0xFAF8, 0x236A, 0x5A98, 0x0113, 0xB574, 0xAF0C, 0xA5E0, 0x8282, 0x16C9, 0x3E16, 0x1A68, 0x40DE, 0xDEC3, 0x09D1, 0x9907, +0x5207, 0x9E06, 0x0322, 0xB378, 0x0D23, 0x82B9, 0xBB51, 0xEAD4, 0x2938, 0x0629, 0x6AF7, 0x2716, 0x6E8A, 0x8C4E, 0x499F, 0x6B1F, +0x7541, 0x7301, 0x121D, 0xFC08, 0xF37F, 0x1CCE, 0x5550, 0x920C, 0x8925, 0x493A, 0x34D4, 0x4747, 0x09F8, 0x0BAC, 0x4DBF, 0xCCDF, +0xADF8, 0x39BB, 0x7124, 0x5AB7, 0xE633, 0xF224, 0x1385, 0x3FFE, 0xA141, 0x8726, 0xA544, 0xD17F, 0x3430, 0xA3C3, 0x0E4A, 0x4CA8, +0x8CD1, 0x1A9E, 0x472A, 0x4519, 0xB578, 0xF2EF, 0xA5A6, 0x3FA4, 0xF5A5, 0xD3E9, 0xB089, 0xB884, 0x41E1, 0x57B3, 0xAA62, 0x2A98, +0xBDF2, 0xC177, 0xE72E, 0x70ED, 0xCB08, 0x6383, 0xFAF2, 0x508B, 0x29C1, 0x143C, 0xE59A, 0xDBCF, 0xDBFE, 0xD354, 0xC635, 0x2471, +0x966A, 0xA03F, 0xB873, 0x9E21, 0x7F71, 0xD087, 0xA4B7, 0xD957, 0x7025, 0x6C97, 0x2C65, 0xA8CA, 0x99CA, 0xB392, 0x920E, 0x105A, +0x420D, 0x66CA, 0x9528, 0x9922, 0x2018, 0x131E, 0x5226, 0x85A1, 0xA1B8, 0x9533, 0x2A29, 0x2DA6, 0x8144, 0xFCD9, 0x81E0, 0x03C6, +0x6FFA, 0xC9A0, 0xED44, 0x2730, 0x3976, 0x3EA6, 0x5441, 0x74FF, 0x0CA5, 0xF644, 0xA838, 0x5709, 0xD1D3, 0xEF8D, 0x75D3, 0xF61D, +0x9DE6, 0x20E4, 0xDB31, 0x2459, 0x917E, 0x50C6, 0x3817, 0x8E61, 0x28CA, 0x2203, 0x6426, 0xCEAF, 0x1469, 0x327A, 0x46C0, 0xF5C3, +0xA31C, 0xC576, 0x56CA, 0x385A, 0xFB68, 0x9457, 0xA695, 0x04BA, 0x6B2E, 0x0260, 0x05B6, 0x8856, 0x3997, 0x6BDB, 0xE2D6, 0x65DE, +0x6219, 0x8759, 0xA937, 0xCD96, 0x7A6E, 0x205B, 0x90C3, 0x5B4B, 0xA0B3, 0xA30C, 0xAB95, 0x38C6, 0x4ED3, 0x1DF7, 0x0115, 0xD274, +0x5A8C, 0xACE9, 0x03FD, 0x814B, 0xBD6F, 0x7A76, 0x5663, 0xA912, 0x17AE, 0x98B3, 0x81EB, 0x7795, 0x718E, 0x37C4, 0x050B, 0x8399, +0x7213, 0x7F95, 0x3F3D, 0xE7CC, 0x5755, 0xB1FC, 0x79B4, 0x343E, 0x2833, 0x3016, 0xEB4B, 0x3276, 0xA11D, 0x6D60, 0xC96A, 0xBAAD, +0x4037, 0x1648, 0xFCA4, 0x5A73, 0x7766, 0x581E, 0x5772, 0x4FE1, 0x922E, 0x27CD, 0x1D07, 0x67DB, 0xA9A5, 0xD3E5, 0x3D67, 0xB95B, +0x8DEC, 0xD828, 0x4D3B, 0x0E03, 0xBC45, 0xC161, 0xD160, 0xE114, 0xA04A, 0xB119, 0x24F8, 0xC41F, 0xFBA7, 0x42ED, 0x8EBF, 0x9D1A, +0xB9A7, 0x7FD7, 0xA993, 0xE362, 0x3161, 0xB63F, 0xA784, 0xE249, 0xEEAE, 0xBD1E, 0x995A, 0x9818, 0xE1BC, 0x8FFA, 0xDABA, 0x5F1C, +0xDDCE, 0xF3C9, 0xA30F, 0x8D31, 0x2592, 0x364C, 0xADD6, 0x23BE, 0x2ADC, 0x4E7D, 0x7755, 0xE46F, 0x9B4C, 0xE02D, 0x5721, 0x46AC, +0xC9F0, 0x0FE4, 0x9BB3, 0x64A7, 0xE351, 0x1DF7, 0xA2D1, 0xAF6B, 0x5D38, 0xDF8E, 0x5610, 0xC96E, 0x6926, 0xCB42, 0x0366, 0x8ED6, +0x2231, 0x5474, 0xD109, 0x64FE, 0xCE82, 0x46D1, 0x0502, 0xF694, 0xA2A5, 0xCF72, 0xB8E6, 0x1206, 0xC1F6, 0xCFA0, 0x10F4, 0x611B, +0x3060, 0x667B, 0xCE84, 0xDDB6, 0xA556, 0xF3D6, 0x5227, 0x02C3, 0x21B8, 0x455D, 0xD24D, 0x36AD, 0x213F, 0x975D, 0xE4BB, 0x6891, +0x323B, 0xACB8, 0x4703, 0x4EA4, 0xE3B9, 0xD776, 0xEC75, 0x99E1, 0x2A25, 0x5C68, 0xF838, 0x18B6, 0x2E38, 0xBF37, 0xD88B, 0x09C2, +0x2ADB, 0xDCDA, 0x31DD, 0x068E, 0x6F5F, 0xD1BE, 0x5336, 0xE430, 0xA438, 0xFA23, 0x4EA1, 0x26E3, 0xF914, 0x737C, 0xDCD7, 0x5253, +0xCDC4, 0x0B05, 0x3505, 0xA76B, 0x08A9, 0xA7EB, 0x44A1, 0x4CCB, 0xA25C, 0xDD67, 0x378B, 0xEEDF, 0x7482, 0x90BA, 0x9F5E, 0x2E75, +0xD34B, 0xB545, 0x64EA, 0xBF9F, 0x2958, 0x3F9F, 0xA3C0, 0x4998, 0xD8B8, 0x60F0, 0xCAFC, 0xD920, 0xB10D, 0x2F63, 0x3B0A, 0xB414, +0x122F, 0x4D2B, 0x7B1C, 0x1A10, 0xB9CF, 0xE433, 0x2E90, 0x470B, 0x2B2E, 0x6A57, 0x7984, 0x0DD6, 0xE1AF, 0x5E19, 0x587E, 0xD870, +0x1FAD, 0xB993, 0xDF64, 0xA0F5, 0xEB46, 0x956E, 0x5114, 0x39DD, 0xBF33, 0x94D4, 0x6772, 0x067F, 0x5949, 0xAB35, 0xAC0F, 0x27D7, +0xEDD0, 0xEA96, 0x091A, 0xF3DF, 0x52DF, 0x94AE, 0x8644, 0x9221, 0xA357, 0xEB58, 0xB637, 0xFBBF, 0xBB15, 0x7194, 0x1FAB, 0xFFC7, +0xE63D, 0xD00C, 0x8A53, 0x19E4, 0xAD41, 0x7B4F, 0xA1E2, 0x9475, 0xC3B3, 0x0E07, 0xE32F, 0xF9BC, 0x1150, 0xF72A, 0x4BD2, 0xC190, +0xFDDA, 0x125A, 0x9F10, 0xD985, 0x7FE4, 0x0509, 0x6F33, 0xFD54, 0x2BD7, 0x7842, 0xF6E9, 0xF10F, 0x54DB, 0x0103, 0xD7D4, 0x971E, +0xFC86, 0x6AAD, 0x750A, 0xC2DC, 0x6748, 0x5927, 0xA0F3, 0x7286, 0x4633, 0xB179, 0x7FC3, 0xE9F2, 0xC97B, 0x130B, 0x73BE, 0xFB52, +0x0225, 0xB5E7, 0xED16, 0x304A, 0x94F4, 0x7594, 0xC7E7, 0x287E, 0xA3AE, 0xF94D, 0x395A, 0x0766, 0x0E61, 0x2E8E, 0x9001, 0xB0A9, +0x0516, 0x0332, 0x203D, 0x7BCD, 0x214F, 0xB706, 0x5005, 0xDF2E, 0x3AB3, 0x2BAA, 0xFB9E, 0x1631, 0x8162, 0x4F14, 0x9463, 0x1D15, +}; \ No newline at end of file diff --git a/CUETools.AVX/CUETools.AVX.vcxproj b/CUETools.AVX/CUETools.AVX.vcxproj new file mode 100644 index 0000000..986d83f --- /dev/null +++ b/CUETools.AVX/CUETools.AVX.vcxproj @@ -0,0 +1,133 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {CC022842-F2E9-4016-82B8-65A264B642D5} + ManagedCProj + CUEToolsAVX + + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + false + Unicode + + + DynamicLibrary + false + Unicode + true + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Level3 + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + + + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + + + true + + + + + + + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + + + true + + + + + + + Level3 + _AMD64_;WIN32;NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + false + false + /arch:AVX %(AdditionalOptions) + + + + + true + false + + + + + + + + + \ No newline at end of file diff --git a/CUETools.AccurateRip/AccurateRip.cs b/CUETools.AccurateRip/AccurateRip.cs index 59faac1..5bd66b4 100644 --- a/CUETools.AccurateRip/AccurateRip.cs +++ b/CUETools.AccurateRip/AccurateRip.cs @@ -13,7 +13,7 @@ namespace CUETools.AccurateRip { public class AccurateRipVerify : IAudioDest { - public const int maxNpar = 8; + public const int maxNpar = 16; public AccurateRipVerify(CDImageLayout toc, IWebProxy proxy) { @@ -314,21 +314,68 @@ namespace CUETools.AccurateRip _CRCLOG[iTrack] = value; } - public unsafe byte[] GetParity(int npar = maxNpar) + public unsafe ushort[,] GetSyndrome(int npar = maxNpar, int strides = -1, int offset = 0) { - if (npar == maxNpar) - return this.parity; - - var synShort = this.GetSyndrome(npar); - return ParityToSyndrome.Syndrome2Parity(synShort); - } - - public unsafe ushort[,] GetSyndrome(int npar = maxNpar) - { + // We can only use offset if Abs(offset * 2) < stride, + // else we might need to add/remove more than one sample + // from syndrome calculations, and that would be too difficult + // and will probably require longer leadin/leadout. if (!calcParity) throw new InvalidOperationException(); - return ParityToSyndrome.Parity2Syndrome(stride, npar, maxNpar, parity); - } + if (strides == -1) + strides = stride; + var syn = ParityToSyndrome.Parity2Syndrome(strides, stride, npar, maxNpar, parity, 0, -offset * 2); + var galois = Galois16.instance; + for (int part2 = 0; part2 < strides; part2++) + { + int part = (part2 + offset * 2 + stride) % stride; + if (part < offset * 2) + { + for (int i = 0; i < npar; i++) + { + int synI = syn[part2, i]; + synI = galois.mulExp(synI, i); + synI ^= leadout[laststride - part - 1] ^ galois.mulExp(leadin[stride + part], (i * stridecount) % galois.Max); + syn[part2, i] = (ushort)synI; + } + } + if (part >= stride + offset * 2) + { + for (int i = 0; i < npar; i++) + { + int synI = syn[part2, i]; + synI ^= leadout[laststride + stride - part - 1] ^ galois.mulExp(leadin[part], (i * stridecount) % galois.Max); + synI = galois.divExp(synI, i); + syn[part2, i] = (ushort)synI; + } + } + } + //for (int part = 0; part < offset * 2; part++) + //{ + // int part2 = (part - offset * 2 + stride) % stride; + // if (part2 < strides) + // for (int i = 0; i < npar; i++) + // { + // int synI = syn[part2, i]; + // synI = galois.mulExp(synI, i); + // synI ^= leadout[laststride - part - 1] ^ galois.mulExp(leadin[stride + part], (i * stridecount) % galois.Max); + // syn[part2, i] = (ushort)synI; + // } + //} + //for (int part = stride + offset * 2; part < stride; part++) + //{ + // int part2 = (part - offset * 2 + stride) % stride; + // if (part2 < strides) + // for (int i = 0; i < npar; i++) + // { + // int synI = syn[part2, i]; + // synI ^= leadout[laststride + stride - part - 1] ^ galois.mulExp(leadin[part], (i * stridecount) % galois.Max); + // synI = galois.divExp(synI, i); + // syn[part2, i] = (ushort)synI; + // } + //} + return syn; + } private byte[] parity; internal ushort[, ,] encodeTable; @@ -401,69 +448,37 @@ namespace CUETools.AccurateRip return CTDBCRC(0, offset, stride / 2, laststride / 2); } - //private unsafe static void CalcPar8(ushort* pt, ushort* wr, uint lo) - //{ - // uint wrlo = wr[0] ^ lo; - // ushort* ptiblo0 = pt + (wrlo & 255) * 16; - // ushort* ptiblo1 = pt + (wrlo >> 8) * 16 + 8; - // ((ulong*)wr)[0] = ((ulong*)(wr + 1))[0] ^ ((ulong*)ptiblo0)[0] ^ ((ulong*)ptiblo1)[0]; - // ((ulong*)wr)[1] = (((ulong*)(wr))[1] >> 16) ^ ((ulong*)ptiblo0)[1] ^ ((ulong*)ptiblo1)[1]; - //} + // pt = &encodeTable + private unsafe delegate void SyndromeCalc(ushort* pt, ushort* wr, ushort lo); - private unsafe static void CalcPar(ushort* pt, ushort* wr, uint lo, uint hi) - { - // pt = &encodeTable -#if !sdfs - uint wrlo = wr[0] ^ lo; - uint wrhi = wr[maxNpar] ^ hi; - ushort* ptiblo0 = pt + (wrlo & 255) * maxNpar * 2; + private unsafe static void SyndromeCalcDummy(ushort* pt, ushort* wr, ushort lo) + { + } + + private unsafe static void SyndromeCalc8(ushort* pt, ushort* wr, ushort lo) + { + ushort wrlo = (ushort)(wr[0] ^ lo); + ushort* ptiblo0 = pt + (wrlo & 255) * maxNpar * 2; ushort* ptiblo1 = pt + (wrlo >> 8) * maxNpar * 2 + maxNpar; - ushort* ptibhi0 = pt + (wrhi & 255) * maxNpar * 2; - ushort* ptibhi1 = pt + (wrhi >> 8) * maxNpar * 2 + maxNpar; - wr[maxNpar] = 0; - if (maxNpar == 16) - { - ((ulong*)wr)[0] = ((ulong*)(wr + 1))[0] ^ ((ulong*)ptiblo0)[0] ^ ((ulong*)ptiblo1)[0]; - ((ulong*)wr)[1] = ((ulong*)(wr + 1))[1] ^ ((ulong*)ptiblo0)[1] ^ ((ulong*)ptiblo1)[1]; - ((ulong*)wr)[2] = ((ulong*)(wr + 1))[2] ^ ((ulong*)ptiblo0)[2] ^ ((ulong*)ptiblo1)[2]; - ((ulong*)wr)[3] = ((ulong*)(wr + 1))[3] ^ ((ulong*)ptiblo0)[3] ^ ((ulong*)ptiblo1)[3]; - ((ulong*)wr)[4] = ((ulong*)(wr + 1))[4] ^ ((ulong*)ptibhi0)[0] ^ ((ulong*)ptibhi1)[0]; - ((ulong*)wr)[5] = ((ulong*)(wr + 1))[5] ^ ((ulong*)ptibhi0)[1] ^ ((ulong*)ptibhi1)[1]; - ((ulong*)wr)[6] = ((ulong*)(wr + 1))[6] ^ ((ulong*)ptibhi0)[2] ^ ((ulong*)ptibhi1)[2]; - ((ulong*)wr)[7] = (((ulong*)(wr))[7] >> 16) ^ ((ulong*)ptibhi0)[3] ^ ((ulong*)ptibhi1)[3]; - } - else if (maxNpar == 8) - { - ((ulong*)wr)[0] = ((ulong*)(wr + 1))[0] ^ ((ulong*)ptiblo0)[0] ^ ((ulong*)ptiblo1)[0]; - ((ulong*)wr)[1] = ((ulong*)(wr + 1))[1] ^ ((ulong*)ptiblo0)[1] ^ ((ulong*)ptiblo1)[1]; - ((ulong*)wr)[2] = ((ulong*)(wr + 1))[2] ^ ((ulong*)ptibhi0)[0] ^ ((ulong*)ptibhi1)[0]; - ((ulong*)wr)[3] = (((ulong*)(wr))[3] >> 16) ^ ((ulong*)ptibhi0)[1] ^ ((ulong*)ptibhi1)[1]; - } - else - throw new InvalidOperationException(); -#else - const int npar = 8; + ((ulong*)wr)[0] = ((ulong*)(wr + 1))[0] ^ ((ulong*)ptiblo0)[0] ^ ((ulong*)ptiblo1)[0]; + ((ulong*)wr)[1] = (((ulong*)(wr))[1] >> 16) ^ ((ulong*)ptiblo0)[1] ^ ((ulong*)ptiblo1)[1]; + } - uint s = wr[0] ^ lo; - ushort* ptib0 = pt + (s & 255) * 16; - ushort* ptib1 = pt + (s >> 8) * 16 + 8; - for (int i = 0; i < npar - 1; i++) - wr[i] = (ushort)(wr[i + 1] ^ ptib0[i] ^ ptib1[i]); - wr[npar - 1] = (ushort)(ptib0[npar - 1] ^ ptib1[npar - 1]); + //[System.Runtime.InteropServices.DllImport("CUETools.AVX.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)] + //private unsafe static extern void SyndromeCalc16AVX(ushort* table, ushort* parity, ushort* samples, int n); - wr += 8; - - s = wr[0] ^ hi; - ptib0 = pt + (s & 255) * 16; - ptib1 = pt + (s >> 8) * 16 + 8; - for (int i = 0; i < npar - 1; i++) - wr[i] = (ushort)(wr[i + 1] ^ ptib0[i] ^ ptib1[i]); - wr[npar - 1] = (ushort)(ptib0[npar - 1] ^ ptib1[npar - 1]); -#endif - } + private unsafe static void SyndromeCalc16(ushort* pt, ushort* wr, ushort lo) + { + ushort wrlo = (ushort)(wr[0] ^ lo); + ushort* ptiblo0 = pt + (wrlo & 255) * maxNpar * 2; + ushort* ptiblo1 = pt + (wrlo >> 8) * maxNpar * 2 + maxNpar; + ((ulong*)wr)[0] = ((ulong*)(wr + 1))[0] ^ ((ulong*)ptiblo0)[0] ^ ((ulong*)ptiblo1)[0]; + ((ulong*)wr)[1] = ((ulong*)(wr + 1))[1] ^ ((ulong*)ptiblo0)[1] ^ ((ulong*)ptiblo1)[1]; + ((ulong*)wr)[2] = ((ulong*)(wr + 1))[2] ^ ((ulong*)ptiblo0)[2] ^ ((ulong*)ptiblo1)[2]; + ((ulong*)wr)[3] = (((ulong*)(wr))[3] >> 16) ^ ((ulong*)ptiblo0)[3] ^ ((ulong*)ptiblo1)[3]; + } - - /// + /// /// This function calculates three different CRCs and also /// collects some additional information for the purposes of /// offset detection. @@ -481,6 +496,7 @@ namespace CUETools.AccurateRip { int currentStride = ((int)_sampleCount * 2) / stride; bool doPar = currentStride >= 1 && currentStride <= stridecount && calcParity; + SyndromeCalc syndromeCalc = doPar ? maxNpar == 8 ? (SyndromeCalc)SyndromeCalc8 : (SyndromeCalc)SyndromeCalc16 : (SyndromeCalc)SyndromeCalcDummy; int crcTrack = _currentTrack + (_samplesDoneTrack == 0 && _currentTrack > 0 ? -1 : 0); uint crcar = _CRCAR[_currentTrack, 0]; @@ -491,6 +507,8 @@ namespace CUETools.AccurateRip uint crcv2 = _CRCV2[_currentTrack, 0]; int peak = _Peak[_currentTrack]; + //if (doPar) SyndromeCalc16AVX(pte, wr, (ushort*)pSampleBuff, count * 2); + for (int i = 0; i < count; i++) { if (offs >= 0) @@ -518,12 +536,9 @@ namespace CUETools.AccurateRip crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (lo >> 8))]; crcnl++; } + syndromeCalc(pte, wr + i * maxNpar * 2, (ushort)lo); uint hi = sample >> 16; - if (doPar) CalcPar(pte, wr + i * maxNpar * 2, lo, hi); - //if (doPar) CalcPar8(pte, wr + i * 16, lo); - //uint hi = sample >> 16; - crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ hi)]; crc32 = (crc32 >> 8) ^ t[(byte)(crc32 ^ (hi >> 8))]; if (hi != 0) @@ -532,7 +547,7 @@ namespace CUETools.AccurateRip crcwn = (crcwn >> 8) ^ t[(byte)(crcwn ^ (hi >> 8))]; crcnl++; } - //if (doPar) CalcPar8(pte, wr + i * 16 + 8, hi); + syndromeCalc(pte, wr + i * maxNpar * 2 + maxNpar, (ushort)hi); int pk = ((int)(lo << 16)) >> 16; peak = Math.Max(peak, (pk << 1) ^ (pk >> 31)); diff --git a/CUETools.AccurateRip/CDRepair.cs b/CUETools.AccurateRip/CDRepair.cs index 968e515..180c67d 100644 --- a/CUETools.AccurateRip/CDRepair.cs +++ b/CUETools.AccurateRip/CDRepair.cs @@ -56,7 +56,15 @@ namespace CUETools.AccurateRip return stride; } } - } + + public int LastStride + { + get + { + return laststride; + } + } + } public class CDRepairEncode : CDRepair { @@ -85,16 +93,18 @@ namespace CUETools.AccurateRip } } - public string TrackCRCs - { - get - { - var sb = new StringBuilder(); - for (int i = 1; i <= ar.TOC.AudioTracks; i++) - sb.AppendFormat(" {0:x8}", ar.CTDBCRC(i, 0, stride / 2, laststride / 2)); - return sb.ToString().Substring(1); - } - } + public string GetTrackCRCs(int oi) + { + var sb = new StringBuilder(); + for (int i = 1; i <= ar.TOC.AudioTracks; i++) + sb.AppendFormat(" {0:x8}", this.TrackCRC(i, oi)); + return sb.ToString().Substring(1); + } + + public uint TrackCRC(int iTrack, int oi) + { + return this.ar.CTDBCRC(iTrack, oi, this.stride / 2, this.laststride / 2); + } public unsafe bool FindOffset(ushort[,] syn2, uint expectedCRC, out int actualOffset, out bool hasErrors) { @@ -107,56 +117,44 @@ namespace CUETools.AccurateRip throw new Exception("ar.Position != ar.FinalSampleCount"); var rs = new RsDecode16(npar, this.galois); - int part2 = 0; - // find offset - fixed (ushort* chT = rs.chienTable, syn2part = &syn2[part2, 0]) + fixed (ushort* syn2part = syn2) { int* _sigma = stackalloc int[npar]; int* _errpos = stackalloc int[npar]; int* syn = stackalloc int[npar]; - bool foundOffset = false; - var arSyndrome = ar.GetSyndrome(npar); + int bestOffset = 0; + int bestOffsetErrors = npar / 2; - for (int allowed_errors = 0; allowed_errors < npar / 2 && !foundOffset; allowed_errors++) + // fast search + for (int offset = 1 - stride / 2; offset < stride / 2; offset++) { - // We can only use offset if Abs(offset * 2) < stride, - // else we might need to add/remove more than one sample - // from syndrome calculations, and that would be too difficult - // and will probably require longer leadin/leadout. - for (int offset = 1 - stride / 2; offset < stride / 2; offset++) + var syn1 = ar.GetSyndrome(npar, 1, -offset); + int err = 0; + for (int i = 0; i < npar; i++) { - int err = 0; - int part = (part2 + stride - offset * 2) % stride; - - for (int i = 0; i < npar; i++) - { - int synI = arSyndrome[part, i]; - - // offset < 0 - if (part < -offset * 2) - { - synI ^= galois.mulExp(ar.leadin[stride + part], (i * (stridecount - 1)) % galois.Max); - synI = ar.leadout[laststride - part - 1] ^ galois.mulExp(synI, i); - } - // offset > 0 - if (part >= stride - offset * 2) - { - synI = galois.divExp(synI ^ ar.leadout[laststride + stride - part - 1], i); - synI ^= galois.mulExp(ar.leadin[part], (i * (stridecount - 1)) % galois.Max); - } - - synI = galois.mulExp(synI ^ syn2part[i], i * npar); - syn[i] = synI; - err |= synI; - } - int err_count = err == 0 ? 0 : rs.calcSigmaMBM(_sigma, syn); - if (err_count == allowed_errors && (err_count == 0 || rs.chienSearch(_errpos, stridecount + npar, err_count, _sigma, chT))) - { - actualOffset = offset; - hasErrors = err_count != 0 || ar.CTDBCRC(-offset) != expectedCRC; - return true; - } + int synI = syn1[0, i] ^ syn2part[i]; + syn[i] = synI; + err |= synI; } + if (err == 0) + { + actualOffset = offset; + hasErrors = ar.CTDBCRC(-offset) != expectedCRC; + return true; + } + int err_count = rs.calcSigmaMBM(_sigma, syn); + if (err_count > 0 && err_count < bestOffsetErrors && rs.chienSearch(_errpos, stridecount, err_count, _sigma)) + { + bestOffset = offset; + bestOffsetErrors = err_count; + } + } + + if (bestOffsetErrors < npar / 2) + { + actualOffset = bestOffset; + hasErrors = true; + return true; } } actualOffset = 0; @@ -164,99 +162,92 @@ namespace CUETools.AccurateRip return false; } - public unsafe CDRepairFix VerifyParity(ushort[,] syn2, int actualOffset) + public unsafe CDRepairFix VerifyParity(ushort[,] syn2, uint crc, int actualOffset) { int npar2 = syn2.GetLength(1); int npar = Math.Min(AccurateRipVerify.maxNpar, npar2); - - CDRepairFix fix = new CDRepairFix(this, npar); - fix.actualOffset = actualOffset; - fix.correctableErrors = 0; - fix.hasErrors = false; - fix.canRecover = true; - - fix.sigma = new int[stride, npar / 2 + 2]; - fix.omega = new int[stride, npar / 2 + 1]; - fix.errpos = new int[stride, npar / 2]; - //fix.erroff = new int[stride, npar / 2]; - fix.errors = new int[stride]; - - var syn1 = ar.GetSyndrome(npar); + var erroff = new int[stride * npar / 2]; + var forney = new ushort[stride * npar / 2]; + var syn1 = ar.GetSyndrome(npar, -1, -actualOffset); var rs = new RsDecode16(npar, this.galois); + CDRepairFix fix = new CDRepairFix(this, npar); - //fixed (byte* par = &parity2[pos]) - fixed (ushort* exp = galois.ExpTbl, log = galois.LogTbl, chT = rs.chienTable, psyn2 = syn2, psyn1 = syn1) - fixed (int* sf = fix.sigma, of = fix.omega, ef = fix.errpos) + fix.actualOffset = actualOffset; + fix.correctableErrors = 0; + fix.hasErrors = false; + fix.canRecover = true; + + fixed (ushort *psyn2 = syn2, psyn1 = syn1) { - int sfLen = fix.sigma.GetLength(1); - int ofLen = fix.omega.GetLength(1); - int efLen = fix.errpos.GetLength(1); + int sfLen = npar / 2 + 2; + int ofLen = npar / 2 + 1; + int efLen = npar / 2; + int* _sigma = stackalloc int[npar / 2 + 2]; + int* _omega = stackalloc int[npar / 2 + 1]; + int* _errpos = stackalloc int[npar / 2]; int* syn = stackalloc int[npar]; int offset = fix.actualOffset; - for (int part = 0; part < stride; part++) + for (int part2 = 0; part2 < stride; part2++) { - int part2 = (part + offset * 2 + stride) % stride; - ushort* syn1part = psyn1 + part * npar; + ushort* syn1part = psyn1 + part2 * npar; ushort* syn2part = psyn2 + part2 * npar; int err = 0; for (int i = 0; i < npar; i++) { - int synI = syn1part[i]; - - // offset < 0 - if (part < -offset * 2) - { - synI ^= galois.mulExp(ar.leadin[stride + part], (i * (stridecount - 1)) % galois.Max); - synI = ar.leadout[laststride - part - 1] ^ galois.mulExp(synI, i); - } - // offset > 0 - if (part >= stride - offset * 2) - { - synI = galois.divExp(synI ^ ar.leadout[laststride + stride - part - 1], i); - synI ^= galois.mulExp(ar.leadin[part], (i * (stridecount - 1)) % galois.Max); - } - - synI = galois.mulExp(synI ^ syn2part[i], i * npar); + var synI = syn1part[i] ^ syn2part[i]; syn[i] = synI; err |= synI; } - //for (int j = 0; j < npar; j++) - // if (wr[j] != 0) - // { - // ushort* myexp = exp + log[wr[j]]; - // syn[0] ^= wr[j]; - // for (int i = 1; i < npar; i++) - // syn[i] ^= myexp[(npar - j - 1) * i]; - // } + if (err != 0) + { + int errcount = rs.calcSigmaMBM(_sigma, syn); + fix.hasErrors = true; + if (errcount <= 0 || errcount > efLen || !rs.chienSearch(_errpos, stridecount, errcount, _sigma)) + { + fix.canRecover = false; + return fix; + } - //for (int i = 0; i < npar; i++) - // err |= syn[i]; + galois.mulPoly(_omega, _sigma, syn, ofLen, sfLen, npar); - if (err != 0) - { - int* s = sf + part * sfLen; - int* o = of + part * ofLen; - int* e = ef + part * efLen; - //fixed (int* s = &fix.sigma[part, 0], o = &fix.omega[part, 0], e = &fix.errpos[part, 0]) - { - fix.errors[part] = rs.calcSigmaMBM(s, syn); - fix.hasErrors = true; - fix.correctableErrors += fix.errors[part]; - if (fix.errors[part] <= 0 || !rs.chienSearch(e, stridecount + npar, fix.errors[part], s, chT)) - fix.canRecover = false; - else - galois.mulPoly(o, s, syn, ofLen, sfLen, npar); - } - } - else - fix.errors[part] = 0; + for (int i = 0; i < errcount; i++) + { + int pos = galois.toPos(stridecount, _errpos[i]) * stride + part2; + int erroffi = stride + pos - actualOffset * 2; + ushort diff = (ushort)this.galois.doForney(errcount, _errpos[i], _sigma, _omega); + if (erroffi < 0 || erroffi >= finalSampleCount * 2) + { + fix.canRecover = false; + return fix; + } + crc ^= Crc32.Combine(Crc32.ComputeChecksum(Crc32.ComputeChecksum(0, (byte)diff), (byte)(diff >> 8)), 0, (stridecount * stride - pos - 1) * 2); + erroff[fix.correctableErrors] = erroffi; + forney[fix.correctableErrors] = diff; + fix.correctableErrors++; + } + } } + + crc ^= ar.CTDBCRC(-actualOffset); + if (crc != 0) + { + fix.canRecover = false; + return fix; + } } - return fix; + fix.erroffsorted = new int[fix.correctableErrors]; + fix.forneysorted = new ushort[fix.correctableErrors]; + for (int i = 0; i < fix.correctableErrors; i++) + { + fix.erroffsorted[i] = erroff[i]; + fix.forneysorted[i] = forney[i]; + } + Array.Sort(fix.erroffsorted, fix.forneysorted, 0, fix.correctableErrors); + return fix; } public string OffsetSafeCRC @@ -273,15 +264,10 @@ namespace CUETools.AccurateRip internal bool hasErrors = false, canRecover = true; internal int actualOffset = 0; internal int correctableErrors = 0; - internal int[,] sigma; - internal int[,] omega; - internal int[,] errpos; - internal int[] erroffsorted; + internal int[] erroffsorted; internal ushort[] forneysorted; - internal int erroffcount; - internal int[] errors; private BitArray affectedSectorArray; - private int nexterroff; + private int nexterroff = 0; private int npar; uint crc = 0; @@ -289,29 +275,13 @@ namespace CUETools.AccurateRip : base(decode) { this.npar = npar; - } + } public string AffectedSectors { get { - StringBuilder sb = new StringBuilder(); - SortErrors(); - for (int i = 0; i < erroffcount; i++) - { - int j; - for (j = i + 1; j < erroffcount; j++) - if (erroffsorted[j] - erroffsorted[j - 1] > 2 * 588 * 5) - break; - uint sec1 = (uint)erroffsorted[i] / 2 / 588; - uint sec2 = (uint)erroffsorted[j - 1] / 2 / 588; - if (sb.Length != 0) sb.Append(","); - sb.Append(CDImageLayout.TimeToString(sec1)); - if (sec1 != sec2) sb.Append("-"); - if (sec1 != sec2) sb.Append(CDImageLayout.TimeToString(sec2)); - i = j - 1; - } - return sb.ToString(); + return this.GetAffectedSectors(0, finalSampleCount); } } @@ -322,43 +292,46 @@ namespace CUETools.AccurateRip if (affectedSectorArray == null) { affectedSectorArray = new BitArray(finalSampleCount / 588 + 1); - SortErrors(); - for (int i = 0; i < erroffcount; i++) + for (int i = 0; i < correctableErrors; i++) affectedSectorArray[erroffsorted[i] / 2 / 588] = true; } return affectedSectorArray; } } - private int GetErrOff(int part, int i) - { - return (2 + galois.toPos(stridecount + npar, errpos[part, i]) - (stride + part + ActualOffset * 2) / stride) * stride + part; - } + public int GetAffectedSectorsCount(int min, int max) + { + min = Math.Max(2 * min, stride - 2 * ActualOffset); + max = Math.Min(2 * max, 2 * finalSampleCount - laststride - 2 * ActualOffset); + int count = 0; + for (int i = 0; i < correctableErrors; i++) + if (erroffsorted[i] >= min && erroffsorted[i] < max) + count++; + return count; + } - private unsafe void SortErrors() - { - if (erroffsorted != null) - return; - erroffcount = 0; - erroffsorted = new int[errpos.GetLength(0) * errpos.GetLength(1)]; - forneysorted = new ushort[errpos.GetLength(0) * errpos.GetLength(1)]; - for (int part = 0; part < stride; part++) - { - fixed (int* s = &sigma[part, 0], o = &omega[part, 0]) - for (int i = 0; i < errors[part]; i++) - { - erroffsorted[erroffcount] = GetErrOff(part, i); - if (erroffsorted[erroffcount] >= 0 && erroffsorted[erroffcount] < finalSampleCount * 2) - { - forneysorted[erroffcount] = (ushort)this.galois.doForney(errors[part], errpos[part, i], s, o); - erroffcount++; - } - } - } - Array.Sort(erroffsorted, forneysorted, 0, erroffcount); - // assert erroffcount == CorrectableErrors - nexterroff = 0; - } + public string GetAffectedSectors(int min, int max) + { + min = Math.Max(2 * min, stride - 2 * ActualOffset); + max = Math.Min(2 * max, 2 * finalSampleCount - laststride - 2 * ActualOffset); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < correctableErrors; i++) + if (erroffsorted[i] >= min && erroffsorted[i] < max) + { + int j; + for (j = i + 1; j < correctableErrors; j++) + if (erroffsorted[j] - erroffsorted[j - 1] > 2 * 588 * 5) + break; + uint sec1 = (uint)(erroffsorted[i] - min) / 2 / 588; + uint sec2 = (uint)(erroffsorted[j - 1] - min) / 2 / 588; + if (sb.Length != 0) sb.Append(","); + sb.Append(CDImageLayout.TimeToString(sec1)); + if (sec1 != sec2) sb.Append("-"); + if (sec1 != sec2) sb.Append(CDImageLayout.TimeToString(sec2)); + i = j - 1; + } + return sb.ToString(); + } public unsafe void Write(AudioBuffer sampleBuffer) { @@ -370,15 +343,13 @@ namespace CUETools.AccurateRip int firstPos = Math.Max(0, stride - sampleCount * 2 - ActualOffset * 2); int lastPos = Math.Min(sampleBuffer.ByteLength >> 1, (finalSampleCount - sampleCount) * 2 - laststride - ActualOffset * 2); - SortErrors(); - fixed (byte* bytes = sampleBuffer.Bytes) fixed (uint* t = Crc32.table) { ushort* data = (ushort*)bytes; for (int pos = firstPos; pos < lastPos; pos++) { - if (sampleCount * 2 + pos == erroffsorted[nexterroff] && nexterroff < erroffsorted.Length) + if (nexterroff < erroffsorted.Length && sampleCount * 2 + pos == erroffsorted[nexterroff]) data[pos] ^= forneysorted[nexterroff++]; ushort dd = data[pos]; diff --git a/CUETools.CDImage/CDImage.cs b/CUETools.CDImage/CDImage.cs index a68e6a6..0b5f936 100644 --- a/CUETools.CDImage/CDImage.cs +++ b/CUETools.CDImage/CDImage.cs @@ -453,7 +453,7 @@ namespace CUETools.CDImage return new CDImageLayout(trackcount, audiotracks, firstaudio, string.Join(" ", ids)); } - public string ToString() + public override string ToString() { StringBuilder mbSB = new StringBuilder(); for (int iTrack = 0; iTrack < TrackCount; iTrack++) diff --git a/CUETools.CTDB.Converter/CUETools.CTDB.Converter.csproj b/CUETools.CTDB.Converter/CUETools.CTDB.Converter.csproj new file mode 100644 index 0000000..0feff43 --- /dev/null +++ b/CUETools.CTDB.Converter/CUETools.CTDB.Converter.csproj @@ -0,0 +1,73 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {F8C29953-A697-4462-82DC-DA7146654A64} + Exe + Properties + CUETools.CTDB.Converter + CUETools.CTDB.Converter + v2.0 + + + 512 + + + true + bin\Debug\ + DEBUG;TRACE + full + AnyCPU + bin\Debug\CUETools.CTDB.Converter.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + false + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + + + ..\bin\Release\ + TRACE + true + pdbonly + AnyCPU + bin\Release\CUETools.CTDB.Converter.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + false + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + + + + + + + + + + + + + {ECEB839C-171B-4535-958F-9899310A0342} + CUETools.Parity + + + + + \ No newline at end of file diff --git a/CUETools.CTDB.Converter/Program.cs b/CUETools.CTDB.Converter/Program.cs new file mode 100644 index 0000000..eb91005 --- /dev/null +++ b/CUETools.CTDB.Converter/Program.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Text; +using CUETools.Parity; +using System.IO; +using System.Net; + +namespace CUETools.CTDB.Converter +{ + public class ReadDB + { + private byte[] contents; + public int pos; + + public ReadDB(byte[] contents) + { + this.contents = contents; + this.pos = 0; + } + + public string ReadHDR(out int end) + { + int size = this.ReadInt(); + string res = Encoding.ASCII.GetString(contents, pos, 4); + this.pos += 4; + end = pos + size - 8; + return res; + } + + public int ReadInt() + { + int value = + (this.contents[this.pos + 3] + + (this.contents[this.pos + 2] << 8) + + (this.contents[this.pos + 1] << 16) + + (this.contents[this.pos + 0] << 24)); + this.pos += 4; + return value; + } + + public uint ReadUInt() + { + uint value = + ((uint)this.contents[this.pos + 3] + + ((uint)this.contents[this.pos + 2] << 8) + + ((uint)this.contents[this.pos + 1] << 16) + + ((uint)this.contents[this.pos + 0] << 24)); + this.pos += 4; + return value; + } + } + + class DBHDR : IDisposable + { + private long lenOffs; + private MemoryStream stream; + + public DBHDR(MemoryStream stream, string name) + { + this.stream = stream; + lenOffs = stream.Position; + Write(0); + Write(name); + } + + public void Dispose() + { + long fin = stream.Position; + stream.Position = lenOffs; + Write((int)(fin - lenOffs)); + stream.Position = fin; + } + + public void Write(int value) + { + byte[] temp = new byte[4]; + temp[3] = (byte)(value & 0xff); + temp[2] = (byte)((value >> 8) & 0xff); + temp[1] = (byte)((value >> 16) & 0xff); + temp[0] = (byte)((value >> 24) & 0xff); + Write(temp); + } + + public void Write(uint value) + { + byte[] temp = new byte[4]; + temp[3] = (byte)(value & 0xff); + temp[2] = (byte)((value >> 8) & 0xff); + temp[1] = (byte)((value >> 16) & 0xff); + temp[0] = (byte)((value >> 24) & 0xff); + Write(temp); + } + + public void Write(string value) + { + Write(Encoding.UTF8.GetBytes(value)); + } + + public void Write(byte[] value) + { + stream.Write(value, 0, value.Length); + } + + public DBHDR HDR(string name) + { + return new DBHDR(stream, name); + } + } + + class Program + { + const int stride = 588 * 10 * 2; + + private static byte[] Unparse(ushort[,] syndrome, int version) + { + if (version == 1) + { + return ParityToSyndrome.Syndrome2Bytes(syndrome); + } + + var output = ParityToSyndrome.Syndrome2Parity(syndrome); + var newcontents = new MemoryStream(); + using (DBHDR FTYP = new DBHDR(newcontents, "ftyp")) + FTYP.Write("CTDB"); + using (DBHDR CTDB = new DBHDR(newcontents, "CTDB")) + { + using (DBHDR HEAD = CTDB.HDR("HEAD")) + { + using (DBHDR VERS = HEAD.HDR("VERS")) VERS.Write(0x101); + } + using (DBHDR DISC = CTDB.HDR("DISC")) + { + using (DBHDR CONF = DISC.HDR("CONF")) CONF.Write(1); + using (DBHDR NPAR = DISC.HDR("NPAR")) NPAR.Write(8); + using (DBHDR CRC_ = DISC.HDR("CRC ")) CRC_.Write(0); + using (DBHDR PAR_ = DISC.HDR("PAR ")) PAR_.Write(output); + } + } + return newcontents.ToArray(); + } + + private static ushort[,] Parse(byte[] contents, int version) + { + if (version == 2) + { + int npar = contents.Length / stride / 2; + if (npar < 8 || npar > 32 || contents.Length != npar * stride * 2) + throw new Exception("invalid parity length"); + return ParityToSyndrome.Bytes2Syndrome(stride, 8, contents); + } + + if (contents.Length < 8 * stride * 2 + || contents.Length > 8 * stride * 4) + throw new Exception("invalid length"); + + ReadDB rdr = new ReadDB(contents); + + int end; + string hdr = rdr.ReadHDR(out end); + uint magic = rdr.ReadUInt(); + if (hdr != "ftyp" || magic != 0x43544442 || end != rdr.pos) + throw new Exception("invalid CTDB file"); + hdr = rdr.ReadHDR(out end); + if (hdr != "CTDB" || end != contents.Length) + throw new Exception("invalid CTDB file"); + hdr = rdr.ReadHDR(out end); + if (hdr != "HEAD") + throw new Exception("invalid CTDB file"); + int endHead = end; + while (rdr.pos < endHead) + { + hdr = rdr.ReadHDR(out end); + rdr.pos = end; + } + rdr.pos = endHead; + while (rdr.pos < contents.Length) + { + hdr = rdr.ReadHDR(out end); + if (hdr != "DISC") + { + rdr.pos = end; + continue; + } + int endDisc = end; + int parPos = 0, parLen = 0; + while (rdr.pos < endDisc) + { + hdr = rdr.ReadHDR(out end); + if (hdr == "PAR ") + { + parPos = rdr.pos; + parLen = end - rdr.pos; + } + rdr.pos = end; + } + if (parPos != 0) + { + if (parLen != 8 * stride * 2) + throw new Exception("invalid parity length"); + return ParityToSyndrome.Parity2Syndrome(stride, stride, 8, 8, contents, parPos); + } + } + throw new Exception("invalid CTDB file"); + } + + static byte[] Fetch(string url) + { + var req = WebRequest.Create(url); + var resp = (HttpWebResponse)req.GetResponse(); + if (resp.StatusCode != HttpStatusCode.OK) + throw new Exception(resp.ToString()); + return new BinaryReader(resp.GetResponseStream()).ReadBytes((int)resp.ContentLength); + } + + static void Main(string[] args) + { + if (args.Length == 2 && (0 == string.Compare(args[0], "upconvert", true) || 0 == string.Compare(args[0], "downconvert", true))) + { + int id = int.Parse(args[1]); + var version = 0 == string.Compare(args[0], "upconvert", true) ? 1 : 2; + var contents = Fetch("http://p.cuetools.net/" + id.ToString()); + var syndrome = Parse(contents, version); + var stdout = System.Console.OpenStandardOutput(); + var output = Unparse(syndrome, version); + stdout.Write(output, 0, output.Length); + } + else if (args.Length == 2 && 0 == string.Compare(args[0], "p2s", true)) + { + var p = ParityToSyndrome.Parity2Syndrome(1, 1, 8, 8, Convert.FromBase64String(args[1])); + var output = ParityToSyndrome.Syndrome2Bytes(p); + System.Console.Write(Convert.ToBase64String(output)); + } + else + throw new Exception("Usage: upconvert | downconvert | p2s "); + } + } +} diff --git a/CUETools.CTDB.Converter/Properties/AssemblyInfo.cs b/CUETools.CTDB.Converter/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0acd0f7 --- /dev/null +++ b/CUETools.CTDB.Converter/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CUETools.CTDB.Converter")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CUETools.CTDB.Converter")] +[assembly: AssemblyCopyright("Copyright © 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b6155a69-7207-4214-ad24-7737b8b1868a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CUETools.CTDB.EACPlugin/Plugin.cs b/CUETools.CTDB.EACPlugin/Plugin.cs index e70a56d..f1bcf68 100644 --- a/CUETools.CTDB.EACPlugin/Plugin.cs +++ b/CUETools.CTDB.EACPlugin/Plugin.cs @@ -223,29 +223,10 @@ namespace AudioDataPlugIn form.ShowDialog(); sw.WriteLine("[CTDB TOCID: {0}] {1}{2}", TOC.TOCID, - ctdb.DBStatus ?? "found", - (ctdb.SubStatus == null) ? "" : (", Submit result: " + ctdb.SubStatus)); - foreach (DBEntry entry in ctdb.Entries) - { - string confFormat = (ctdb.Total < 10) ? "{0:0}/{1:0}" : - (ctdb.Total < 100) ? "{0:00}/{1:00}" : "{0:000}/{1:000}"; - string conf = string.Format(confFormat, entry.conf, ctdb.Total); - string dataTrackInfo = !entry.toc[entry.toc.TrackCount].IsAudio ? string.Format("CD-Extra data track length {0}", entry.toc[entry.toc.TrackCount].LengthMSF) : - !entry.toc[1].IsAudio ? string.Format("Playstation type data track length {0}", entry.toc[1].LengthMSF) : "Has no data track"; - string status = - entry.toc.Pregap != TOC.Pregap ? string.Format("Has pregap length {0}", CDImageLayout.TimeToString(entry.toc.Pregap)) : - entry.toc.AudioLength != TOC.AudioLength ? string.Format("Has audio length {0}", CDImageLayout.TimeToString(entry.toc.AudioLength)) : - ((entry.toc.TrackOffsets != TOC.TrackOffsets) ? dataTrackInfo + ", " : "") + - ((!entry.hasErrors) ? "Accurately ripped" : - //((!entry.hasErrors) ? string.Format("Accurately ripped, offset {0}", -entry.offset) : - entry.canRecover ? string.Format("Differs in {0} samples @{1}", entry.repair.CorrectableErrors, entry.repair.AffectedSectors) : - (entry.httpStatus == 0 || entry.httpStatus == HttpStatusCode.OK) ? "No match" : - entry.httpStatus.ToString()); - sw.WriteLine("[{0:x8}] ({1}) {2}", - entry.crc, - conf, - status); - } + ctdb.DBStatus ?? "found"); + if (ctdb.SubStatus != null) + sw.WriteLine("Submit result: " + ctdb.SubStatus); + ctdb.GenerateLog(sw, false); bool canFix = false; if (ctdb.QueryExceptionStatus == WebExceptionStatus.Success) { diff --git a/CUETools.CTDB/CTDBResponseEntry.cs b/CUETools.CTDB/CTDBResponseEntry.cs index b286d88..ff6b3f7 100644 --- a/CUETools.CTDB/CTDBResponseEntry.cs +++ b/CUETools.CTDB/CTDBResponseEntry.cs @@ -21,6 +21,10 @@ namespace CUETools.CTDB [XmlAttribute] public string parity { get; set; } [XmlAttribute] + public string syndrome { get; set; } + [XmlAttribute] + public string trackcrcs { get; set; } + [XmlAttribute] public string toc { get; set; } } } diff --git a/CUETools.CTDB/CTDBSubmitResponse.cs b/CUETools.CTDB/CTDBSubmitResponse.cs new file mode 100644 index 0000000..c92b145 --- /dev/null +++ b/CUETools.CTDB/CTDBSubmitResponse.cs @@ -0,0 +1,28 @@ +using System; +using System.Xml.Serialization; + +namespace CUETools.CTDB +{ + [Serializable] + [XmlRoot(ElementName = "ctdb", Namespace = "http://db.cuetools.net/ns/mmd-1.0#")] + public class CTDBSubmitResponse + { + [XmlIgnore] + public bool ParityNeeded + { + get + { + return this.status == "parity needed"; + } + } + + [XmlAttribute] + public string status { get; set; } + + [XmlAttribute] + public string message { get; set; } + + [XmlAttribute] + public int npar { get; set; } + } +} diff --git a/CUETools.CTDB/CUETools.CTDB.csproj b/CUETools.CTDB/CUETools.CTDB.csproj index 907075b..fea9498 100644 --- a/CUETools.CTDB/CUETools.CTDB.csproj +++ b/CUETools.CTDB/CUETools.CTDB.csproj @@ -59,6 +59,7 @@ + @@ -67,9 +68,7 @@ - - diff --git a/CUETools.CTDB/CUEToolsDB.cs b/CUETools.CTDB/CUEToolsDB.cs index a04fecb..d14545c 100644 --- a/CUETools.CTDB/CUEToolsDB.cs +++ b/CUETools.CTDB/CUEToolsDB.cs @@ -65,7 +65,7 @@ namespace CUETools.CTDB HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlbase + "/lookup2.php" - + "?ctdb=" + (ctdb ? "1" : "0") + + "?ctdb=" + (ctdb ? "2" : "0") + "&fuzzy=" + (fuzzy ? 1 : 0) + "&metadata=" + (metadataSearch == CTDBMetadataSearch.None ? "none" : metadataSearch == CTDBMetadataSearch.Fast ? "fast" : metadataSearch == CTDBMetadataSearch.Default ? "default" : "extensive") + "&toc=" + toc.ToString()); @@ -98,24 +98,8 @@ namespace CUETools.CTDB { if (ctdbRespEntry.toc == null) continue; - - var parity = Convert.FromBase64String(ctdbRespEntry.parity); - var entry_toc = CDImageLayout.FromString(ctdbRespEntry.toc); - this.total += ctdbRespEntry.confidence; - - if (parity.Length != ctdbRespEntry.npar * 2) - throw new Exception("invalid parity length"); - //if (verify.Stride != ctdbRespEntry.stride * 2) - // throw new Exception("invalid stride length"); - var syndrome = ParityToSyndrome.Parity2Syndrome(1, ctdbRespEntry.npar, ctdbRespEntry.npar, parity); - var entry = new DBEntry( - syndrome, - ctdbRespEntry.confidence, - ctdbRespEntry.stride * 2, - uint.Parse(ctdbRespEntry.crc32, NumberStyles.HexNumber), - ctdbRespEntry.id, - entry_toc, - ctdbRespEntry.hasparity); + this.total += ctdbRespEntry.confidence; + var entry = new DBEntry(ctdbRespEntry); entries.Add(entry); } if (ctdbResp.musicbrainz != null && ctdbResp.musicbrainz.Length != 0) @@ -146,66 +130,84 @@ namespace CUETools.CTDB } } - public void FetchDB(DBEntry entry) + public ushort[,] FetchDB(DBEntry entry, int npar, ushort[,] syn) { string url = entry.hasParity[0] == '/' ? urlbase + entry.hasParity : entry.hasParity; HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); + int prevLen = syn == null ? 0 : syn.GetLength(1) * entry.stride * 2; req.Method = "GET"; req.Proxy = proxy; req.UserAgent = this.userAgent; req.Timeout = connectTimeout; req.ReadWriteTimeout = socketTimeout; req.AutomaticDecompression = DecompressionMethods.None; - - if (uploadHelper.onProgress != null) - uploadHelper.onProgress(url, new UploadProgressEventArgs(req.RequestUri.AbsoluteUri, 0.0)); + req.AddRange(prevLen, npar * entry.stride * 2 - 1); currentReq = req; - try - { - using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse()) - { - entry.httpStatus = resp.StatusCode; + try + { + using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse()) + { + if (resp.StatusCode != HttpStatusCode.OK && resp.StatusCode != HttpStatusCode.PartialContent) + { + entry.httpStatus = resp.StatusCode; + return null; + } + if (resp.StatusCode == HttpStatusCode.OK && resp.ContentLength == entry.Npar * entry.stride * 2) + { + npar = entry.Npar; + prevLen = 0; + syn = null; + } + else if (resp.StatusCode != HttpStatusCode.PartialContent || (resp.ContentLength + prevLen) != npar * entry.stride * 2) + { + entry.httpStatus = HttpStatusCode.PartialContent; + return null; + } - if (entry.httpStatus == HttpStatusCode.OK) - { - if (resp.ContentLength < entry.Npar * entry.stride * 2 || - resp.ContentLength > entry.Npar * entry.stride * 4) - { - entry.httpStatus = HttpStatusCode.PartialContent; - } - } + using (Stream responseStream = resp.GetResponseStream()) + { + byte[] contents = syn == null ? null : ParityToSyndrome.Syndrome2Bytes(syn); + Array.Resize(ref contents, prevLen + (int)resp.ContentLength); + int pos = prevLen, count = 0; + do + { + if (uploadHelper.onProgress != null) + uploadHelper.onProgress(url, new UploadProgressEventArgs(req.RequestUri.AbsoluteUri, ((double)pos) / (entry.Npar * entry.stride * 2))); + count = responseStream.Read(contents, pos, Math.Min(contents.Length - pos, 32768)); + pos += count; + } while (count != 0); - if (entry.httpStatus == HttpStatusCode.OK) - { - using (Stream responseStream = resp.GetResponseStream()) - { - byte[] contents = new byte[resp.ContentLength]; - int pos = 0, count = 0; - do - { - count = responseStream.Read(contents, pos, Math.Min(contents.Length - pos, 32768)); - pos += count; - if (uploadHelper.onProgress != null) - uploadHelper.onProgress(url, new UploadProgressEventArgs(req.RequestUri.AbsoluteUri, ((double)pos) / contents.Length)); - } while (count != 0); - if (!Parse(contents, entry)) - entry.httpStatus = HttpStatusCode.NoContent; - } - } - } - } - catch (WebException ex) - { - if (ex.Status == WebExceptionStatus.ProtocolError) - entry.httpStatus = ((HttpWebResponse)ex.Response).StatusCode; - else - entry.httpStatus = HttpStatusCode.BadRequest; - } + if (pos != contents.Length) + { + entry.httpStatus = HttpStatusCode.PartialContent; + return null; + } + + syn = ParityToSyndrome.Bytes2Syndrome(entry.stride, npar, contents); + for (int i = 0; i < npar; i++) + if (syn[0, i] != entry.syndrome[0, i]) + { + entry.httpStatus = HttpStatusCode.Conflict; + return null; + } + entry.httpStatus = HttpStatusCode.OK; + return syn; + } + } + } + catch (WebException ex) + { + if (ex.Status == WebExceptionStatus.ProtocolError) + entry.httpStatus = ((HttpWebResponse)ex.Response).StatusCode; + else + entry.httpStatus = HttpStatusCode.BadRequest; + } finally { currentReq = null; } + return null; } static string uuidInfo = null; @@ -232,182 +234,124 @@ namespace CUETools.CTDB if (this.QueryExceptionStatus != WebExceptionStatus.Success && (this.QueryExceptionStatus != WebExceptionStatus.ProtocolError || this.QueryResponseStatus != HttpStatusCode.NotFound)) return this.DBStatus; - int npar = AccurateRipVerify.maxNpar; - var parity = verify.AR.GetParity(npar); + CTDBSubmitResponse resp = null; + subResult = ""; var confirms = this.MatchingEntries; if (confirms.Count > 0) { confidence = 1; foreach (var confirm in confirms) { - subResult = null; - DoSubmit(confidence, quality, artist, title, barcode, false, confirm, parity, npar); - if (subResult == "parity needed") - DoSubmit(confidence, quality, artist, title, barcode, true, confirm, parity, npar); + resp = DoSubmit(confidence, quality, artist, title, barcode, false, confirm, AccurateRipVerify.maxNpar); + if (resp.ParityNeeded) + resp = DoSubmit(confidence, quality, artist, title, barcode, true, confirm, Math.Min(AccurateRipVerify.maxNpar, resp.npar)); + subResult = subResult + (subResult == "" ? "" : ", ") + resp.message; } return subResult; } - DoSubmit(confidence, quality, artist, title, barcode, false, null, parity, npar); - if (subResult == "parity needed") - DoSubmit(confidence, quality, artist, title, barcode, true, null, parity, npar); - return subResult; + resp = DoSubmit(confidence, quality, artist, title, barcode, false, null, AccurateRipVerify.maxNpar); + if (resp.ParityNeeded) + resp = DoSubmit(confidence, quality, artist, title, barcode, true, null, Math.Min(AccurateRipVerify.maxNpar, resp.npar)); + subResult = resp.message; + return subResult; } - protected string DoSubmit(int confidence, int quality, string artist, string title, string barcode, bool upload, DBEntry confirm, byte[] parity, int npar) - { - UploadFile[] files; - if (upload) - { - MemoryStream newcontents = new MemoryStream(); - using (DBHDR FTYP = new DBHDR(newcontents, "ftyp")) - FTYP.Write("CTDB"); - using (DBHDR CTDB = new DBHDR(newcontents, "CTDB")) - { - using (DBHDR HEAD = CTDB.HDR("HEAD")) - { - using (DBHDR VERS = HEAD.HDR("VERS")) VERS.Write(0x101); - } - using (DBHDR DISC = CTDB.HDR("DISC")) - { - using (DBHDR CONF = DISC.HDR("CONF")) CONF.Write(confidence); - using (DBHDR NPAR = DISC.HDR("NPAR")) NPAR.Write(npar); - using (DBHDR CRC_ = DISC.HDR("CRC ")) CRC_.Write(verify.CRC); - using (DBHDR PAR_ = DISC.HDR("PAR ")) PAR_.Write(parity); - } - } - newcontents.Position = 0; - files = new UploadFile[1] { new UploadFile(newcontents, "parityfile", "data.bin", "image/binary") }; - } - else - { - files = new UploadFile[0]; - } - + protected CTDBSubmitResponse DoSubmit(int confidence, int quality, string artist, string title, string barcode, bool upload, DBEntry confirm, int npar) + { + var files = new List(); long maxId = 0; foreach (var e in this.entries) { maxId = Math.Max(maxId, e.id); } - HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlbase + "/submit2.php"); - req.Proxy = proxy; - req.UserAgent = this.userAgent; - req.Timeout = connectTimeout; - req.ReadWriteTimeout = socketTimeout; - NameValueCollection form = new NameValueCollection(); - if (upload) - form.Add("parityfile", "1"); - if (confirm != null) - form.Add("confirmid", confirm.id.ToString()); + HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlbase + "/submit2.php"); + req.Proxy = proxy; + req.UserAgent = this.userAgent; + req.Timeout = connectTimeout; + req.ReadWriteTimeout = socketTimeout; + NameValueCollection form = new NameValueCollection(); + int offset = 0; + if (confirm != null) + { + offset = -confirm.offset; + + // Optional sanity check: should be done by server + + if (verify.AR.CTDBCRC(offset) != confirm.crc) + throw new Exception("crc mismatch"); + + if (confirm.trackcrcs != null) + { + bool crcEquals = true; + for (int i = 0; i < confirm.trackcrcs.Length; i++) + crcEquals &= verify.TrackCRC(i + 1, offset) == confirm.trackcrcs[i]; + if (!crcEquals) + throw new Exception("track crc mismatch"); + } + + var syn2 = verify.AR.GetSyndrome(confirm.Npar, 1, offset); + bool equals = true; + for (int i = 0; i < confirm.Npar; i++) + equals &= confirm.syndrome[0, i] == syn2[0, i]; + if (!equals) + throw new Exception("syndrome mismatch"); + } + if (upload) + { + files.Add(new UploadFile(new MemoryStream(ParityToSyndrome.Syndrome2Bytes(verify.AR.GetSyndrome(npar, -1, offset))), "parityfile", "data.bin", "application/octet-stream")); + form.Add("parityfile", "1"); + } + form.Add("parity", Convert.ToBase64String(ParityToSyndrome.Syndrome2Parity(verify.AR.GetSyndrome(8, 1, offset)))); + form.Add("syndrome", Convert.ToBase64String(ParityToSyndrome.Syndrome2Bytes(verify.AR.GetSyndrome(npar, 1, offset)))); + if (confirm != null) + form.Add("confirmid", confirm.id.ToString()); + form.Add("ctdb", "2"); + form.Add("npar", npar.ToString()); form.Add("maxid", maxId.ToString()); - form.Add("toc", toc.ToString()); - form.Add("crc32", ((int)verify.CRC).ToString()); - form.Add("trackcrcs", verify.TrackCRCs); - form.Add("parity", Convert.ToBase64String(parity, 0, npar * 2)); - form.Add("confidence", confidence.ToString()); - form.Add("userid", GetUUID()); - form.Add("quality", quality.ToString()); - if (driveName != null && driveName != "") form.Add("drivename", driveName); - if (barcode != null && barcode != "") form.Add("barcode", barcode); - if (artist != null && artist != "") form.Add("artist", artist); - if (title != null && title != "") form.Add("title", title); + form.Add("toc", toc.ToString()); + form.Add("crc32", ((int)verify.AR.CTDBCRC(offset)).ToString()); + form.Add("trackcrcs", verify.GetTrackCRCs(offset)); + form.Add("confidence", confidence.ToString()); + form.Add("userid", GetUUID()); + form.Add("quality", quality.ToString()); + if (driveName != null && driveName != "") form.Add("drivename", driveName); + if (barcode != null && barcode != "") form.Add("barcode", barcode); + if (artist != null && artist != "") form.Add("artist", artist); + if (title != null && title != "") form.Add("title", title); - var ExceptionStatus = WebExceptionStatus.Pending; - string ExceptionMessage = null; - HttpStatusCode ResponseStatus = HttpStatusCode.OK; - currentReq = req; - try - { - using (HttpWebResponse resp = uploadHelper.Upload(req, files, form)) - { - ExceptionStatus = WebExceptionStatus.ProtocolError; - ResponseStatus = resp.StatusCode; - if (ResponseStatus == HttpStatusCode.OK) - { - ExceptionStatus = WebExceptionStatus.Success; - using (Stream s = resp.GetResponseStream()) - using (StreamReader sr = new StreamReader(s)) - subResult = sr.ReadToEnd(); - return subResult; - } - } - } - catch (WebException ex) - { - ExceptionStatus = ex.Status; - ExceptionMessage = ex.Message; - if (ExceptionStatus == WebExceptionStatus.ProtocolError) - ResponseStatus = (ex.Response as HttpWebResponse).StatusCode; - } - finally - { - currentReq = null; - } - subResult = ExceptionStatus == WebExceptionStatus.Success ? null : - ExceptionStatus != WebExceptionStatus.ProtocolError ? ("database access error: " + (ExceptionMessage ?? ExceptionStatus.ToString())) : - ResponseStatus != HttpStatusCode.NotFound ? "database access error: " + ResponseStatus.ToString() : - "disk not present in database"; - return subResult; - } - - private bool Parse(byte[] contents, DBEntry entry) - { - if (contents.Length == entry.Npar * entry.stride * 2) - { - entry.syndrome = ParityToSyndrome.Parity2Syndrome(entry.stride, entry.Npar, entry.Npar, contents); - return true; - } - - ReadDB rdr = new ReadDB(contents); - - int end; - string hdr = rdr.ReadHDR(out end); - uint magic = rdr.ReadUInt(); - if (hdr != "ftyp" || magic != 0x43544442 || end != rdr.pos) - throw new Exception("invalid CTDB file"); - hdr = rdr.ReadHDR(out end); - if (hdr != "CTDB" || end != contents.Length) - throw new Exception("invalid CTDB file"); - hdr = rdr.ReadHDR(out end); - if (hdr != "HEAD") - throw new Exception("invalid CTDB file"); - int endHead = end; - while (rdr.pos < endHead) - { - hdr = rdr.ReadHDR(out end); - rdr.pos = end; - } - rdr.pos = endHead; - while (rdr.pos < contents.Length) - { - hdr = rdr.ReadHDR(out end); - if (hdr != "DISC") - { - rdr.pos = end; - continue; - } - int endDisc = end; - int parPos = 0, parLen = 0; - while (rdr.pos < endDisc) - { - hdr = rdr.ReadHDR(out end); - if (hdr == "PAR ") - { - parPos = rdr.pos; - parLen = end - rdr.pos; - } - rdr.pos = end; - } - if (parPos != 0) - { - if (parLen != entry.Npar * entry.stride * 2) - return false; - entry.syndrome = ParityToSyndrome.Parity2Syndrome(entry.stride, entry.Npar, entry.Npar, contents, parPos); - return true; - } - } - return false; - } + currentReq = req; + try + { + using (HttpWebResponse resp = uploadHelper.Upload(req, files.ToArray(), form)) + { + if (resp.StatusCode == HttpStatusCode.OK) + { + using (Stream s = resp.GetResponseStream()) + { + var serializer = new XmlSerializer(typeof(CTDBSubmitResponse)); + return serializer.Deserialize(s) as CTDBSubmitResponse; + } + } + else + { + return new CTDBSubmitResponse() { status = "database access error", message = resp.StatusCode.ToString() }; + } + } + } + catch (WebException ex) + { + return new CTDBSubmitResponse() { status = "database access error", message = ex.Message ?? ex.Status.ToString() }; + } + catch (Exception ex) + { + return new CTDBSubmitResponse() { status = "database access error", message = ex.Message }; + } + finally + { + currentReq = null; + } + } public void DoVerify() { @@ -429,14 +373,24 @@ namespace CUETools.CTDB entry.canRecover = false; else { - FetchDB(entry); - if (entry.httpStatus != HttpStatusCode.OK) - entry.canRecover = false; - else - { - entry.repair = verify.VerifyParity(entry.syndrome, entry.offset); - entry.canRecover = entry.repair.CanRecover; - } + ushort[,] syn = null; + for (int npar = 4; npar <= Math.Min(entry.Npar, AccurateRipVerify.maxNpar); npar *= 2) + { + syn = FetchDB(entry, npar, syn); + if (entry.httpStatus != HttpStatusCode.OK) + { + entry.canRecover = false; + break; + } + npar = syn.GetLength(1); + entry.repair = verify.VerifyParity(syn, entry.crc, entry.offset); + entry.canRecover = entry.repair.CanRecover; + if (entry.canRecover) + { + // entry.syndrome = syn; + break; + } + } } } } @@ -512,6 +466,102 @@ namespace CUETools.CTDB } } + public void GenerateLog(TextWriter sw, bool old) + { + if (this.DBStatus != null || this.Total == 0) + return; + + if (old) + { + sw.WriteLine(" [ CTDBID ] Status"); + foreach (DBEntry entry in this.Entries) + { + string confFormat = (this.Total < 10) ? "{0:0}/{1:0}" : + (this.Total < 100) ? "{0:00}/{1:00}" : "{0:000}/{1:000}"; + string conf = string.Format(confFormat, entry.conf, this.Total); + string dataTrackInfo = !entry.toc[entry.toc.TrackCount].IsAudio ? string.Format("CD-Extra data track length {0}", entry.toc[entry.toc.TrackCount].LengthMSF) : + !entry.toc[1].IsAudio ? string.Format("Playstation type data track length {0}", entry.toc[entry.toc.FirstAudio].StartMSF) : "Has no data track"; + string status = + entry.toc.Pregap != this.TOC.Pregap ? string.Format("Has pregap length {0}", CDImageLayout.TimeToString(entry.toc.Pregap)) : + entry.toc.AudioLength != this.TOC.AudioLength ? string.Format("Has audio length {0}", CDImageLayout.TimeToString(entry.toc.AudioLength)) : + ((entry.toc.TrackOffsets != this.TOC.TrackOffsets) ? dataTrackInfo + ", " : "") + + ((!entry.hasErrors) ? "Accurately ripped" : + //((!entry.hasErrors) ? string.Format("Accurately ripped, offset {0}", -entry.offset) : + entry.canRecover ? string.Format("Differs in {0} samples @{1}", entry.repair.CorrectableErrors, entry.repair.AffectedSectors) : + (entry.httpStatus == 0 || entry.httpStatus == HttpStatusCode.OK) ? "No match" : + entry.httpStatus.ToString()); + sw.WriteLine(" [{0:x8}] ({1}) {2}", entry.crc, conf, status); + } + } + + const int _arOffsetRange = 5 * 588 - 1; + sw.WriteLine("Track | CTDB Status"); + string ifmt = this.Total < 10 ? "1" : this.Total < 100 ? "2" : "3"; + for (int iTrack = 0; iTrack < this.TOC.AudioTracks; iTrack++) + { + int conf = 0; + List resConfidence = new List(); + List resStatus = new List(); + foreach (DBEntry entry in this.Entries) + { + if (!entry.hasErrors) + { + conf += entry.conf; + continue; + } + if (entry.canRecover) + { + var tri = this.TOC[this.TOC.FirstAudio + iTrack]; + var tr0 = this.TOC[this.TOC.FirstAudio]; + var min = (int)(tri.Start - tr0.Start) * 588; + var max = (int)(tri.End + 1 - tr0.Start) * 588; + var diffCount = entry.repair.GetAffectedSectorsCount(min, max); + if (diffCount == 0) + { + conf += entry.conf; + continue; + } + + resConfidence.Add(entry.conf); + resStatus.Add(string.Format("differs in {0} samples @{1}", diffCount, entry.repair.GetAffectedSectors(min, max))); + continue; + } + if (entry.trackcrcs != null) + { + if (this.verify.TrackCRC(iTrack + 1, -entry.offset) == entry.trackcrcs[iTrack]) + { + conf += entry.conf; + continue; + } + for (int oi = -_arOffsetRange; oi <= _arOffsetRange; oi++) + { + if (this.verify.TrackCRC(iTrack + 1, oi) == entry.trackcrcs[iTrack]) + { + conf += entry.conf; + break; + } + } + } + } + if (conf > 0) + { + resConfidence.Insert(0, conf); + resStatus.Insert(0, "accurately ripped"); + } + if (resStatus.Count == 0) + { + resConfidence.Add(0); + resStatus.Add("no match"); + } + resStatus[0] = string.Format("({0," + ifmt + "}/{1}) {2}", resConfidence[0], this.Total, char.ToUpper(resStatus[0][0]) + resStatus[0].Substring(1)); + for (int i = 1; i < resStatus.Count; i++) + { + resStatus[i] = string.Format("({0}/{1}) {2}", resConfidence[i], this.Total, resStatus[i]); + } + sw.WriteLine(string.Format(" {0,2} | {1}", iTrack + 1, string.Join(", or ", resStatus.ToArray()))); + } + } + public CDRepairEncode Verify { get diff --git a/CUETools.CTDB/DBEntry.cs b/CUETools.CTDB/DBEntry.cs index 29dccaf..6379f20 100644 --- a/CUETools.CTDB/DBEntry.cs +++ b/CUETools.CTDB/DBEntry.cs @@ -1,12 +1,16 @@ -using System.Net; +using System; +using System.Globalization; +using System.Net; using CUETools.AccurateRip; using CUETools.CDImage; +using CUETools.Parity; namespace CUETools.CTDB { public class DBEntry { public ushort[,] syndrome; + public uint[] trackcrcs; public int conf; public int stride; public int offset; @@ -19,15 +23,29 @@ namespace CUETools.CTDB public CDImageLayout toc; public string hasParity; - public DBEntry(ushort[,] syndrome, int conf, int stride, uint crc, long id, CDImageLayout toc, string hasParity) + public DBEntry(CTDBResponseEntry ctdbRespEntry) { - this.syndrome = syndrome; - this.id = id; - this.conf = conf; - this.crc = crc; - this.stride = stride; - this.toc = toc; - this.hasParity = hasParity; + this.syndrome = ctdbRespEntry.syndrome == null + ? ParityToSyndrome.Parity2Syndrome(1, 1, 8, 8, Convert.FromBase64String(ctdbRespEntry.parity)) + : ParityToSyndrome.Bytes2Syndrome(1, Math.Min(AccurateRipVerify.maxNpar, ctdbRespEntry.npar), Convert.FromBase64String(ctdbRespEntry.syndrome)); + this.conf = ctdbRespEntry.confidence; + this.stride = ctdbRespEntry.stride * 2; + this.crc = uint.Parse(ctdbRespEntry.crc32, NumberStyles.HexNumber); + this.id = ctdbRespEntry.id; + this.toc = CDImageLayout.FromString(ctdbRespEntry.toc); + this.hasParity = ctdbRespEntry.hasparity; + if (ctdbRespEntry.trackcrcs != null) + { + var crcs = ctdbRespEntry.trackcrcs.Split(' '); + if (crcs.Length == this.toc.AudioTracks) + { + this.trackcrcs = new uint[crcs.Length]; + for (int i = 0; i < this.trackcrcs.Length; i++) + { + this.trackcrcs[i] = uint.Parse(crcs[i], NumberStyles.HexNumber); + } + } + } } public int Npar diff --git a/CUETools.CTDB/DBHDR.cs b/CUETools.CTDB/DBHDR.cs deleted file mode 100644 index 553fd27..0000000 --- a/CUETools.CTDB/DBHDR.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.IO; -using System.Text; - -namespace CUETools.CTDB -{ - class DBHDR : IDisposable - { - private long lenOffs; - private MemoryStream stream; - - public DBHDR(MemoryStream stream, string name) - { - this.stream = stream; - lenOffs = stream.Position; - Write(0); - Write(name); - } - - public void Dispose() - { - long fin = stream.Position; - stream.Position = lenOffs; - Write((int)(fin - lenOffs)); - stream.Position = fin; - } - - public void Write(int value) - { - byte[] temp = new byte[4]; - temp[3] = (byte)(value & 0xff); - temp[2] = (byte)((value >> 8) & 0xff); - temp[1] = (byte)((value >> 16) & 0xff); - temp[0] = (byte)((value >> 24) & 0xff); - Write(temp); - } - - public void Write(uint value) - { - byte[] temp = new byte[4]; - temp[3] = (byte)(value & 0xff); - temp[2] = (byte)((value >> 8) & 0xff); - temp[1] = (byte)((value >> 16) & 0xff); - temp[0] = (byte)((value >> 24) & 0xff); - Write(temp); - } - - public void Write(string value) - { - Write(Encoding.UTF8.GetBytes(value)); - } - - public void Write(byte[] value) - { - stream.Write(value, 0, value.Length); - } - - public DBHDR HDR(string name) - { - return new DBHDR(stream, name); - } - } -} diff --git a/CUETools.CTDB/ReadDB.cs b/CUETools.CTDB/ReadDB.cs deleted file mode 100644 index 5f6defa..0000000 --- a/CUETools.CTDB/ReadDB.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Text; - -namespace CUETools.CTDB -{ - class ReadDB - { - private byte[] contents; - public int pos; - - public ReadDB(byte[] contents) - { - this.contents = contents; - this.pos = 0; - } - - public string ReadHDR(out int end) - { - int size = this.ReadInt(); - string res = Encoding.ASCII.GetString(contents, pos, 4); - this.pos += 4; - end = pos + size - 8; - return res; - } - - public int ReadInt() - { - int value = - (this.contents[this.pos + 3] + - (this.contents[this.pos + 2] << 8) + - (this.contents[this.pos + 1] << 16) + - (this.contents[this.pos + 0] << 24)); - this.pos += 4; - return value; - } - - public uint ReadUInt() - { - uint value = - ((uint)this.contents[this.pos + 3] + - ((uint)this.contents[this.pos + 2] << 8) + - ((uint)this.contents[this.pos + 1] << 16) + - ((uint)this.contents[this.pos + 0] << 24)); - this.pos += 4; - return value; - } - } -} diff --git a/CUETools.Codecs.ALAC/ALACWriter.cs b/CUETools.Codecs.ALAC/ALACWriter.cs index a13135e..ebcfa11 100644 --- a/CUETools.Codecs.ALAC/ALACWriter.cs +++ b/CUETools.Codecs.ALAC/ALACWriter.cs @@ -549,7 +549,84 @@ namespace CUETools.Codecs.ALAC for (int i = 1; i <= order; i++) res[i] = smp[i] - smp[i - 1]; - /* general case */ +#if aaa + // contains errors: if (resval * orig_sign <= 0) continue; is not the same as sign(resval) * sign(orig), because 0x80000000 * 0xffffffff < 0! + // probably should be if (resval == 0 || sign_only(resval) != orig_sign) + // sign_only(d0 ^ resval); is the same as sign_only(d0) * sign_only(resval); + // but sign_only(d0) * orig_sign is not the same (when d0 == 0x80000000) + switch (order) + { + case 8: + { + const int constOrder = 8; + int c0 = coefs[0], c1 = coefs[1], c2 = coefs[2], c3 = coefs[3], c4 = coefs[4], c5 = coefs[5], c6 = coefs[6], c7 = coefs[7]; + int denhalf = 1 << (shift - 1); + for (int i = constOrder + 1; i < n; i++) + { + int sample = *(smp++); + int d0 = smp[0] - sample, d1 = smp[1] - sample, d2 = smp[2] - sample, d3 = smp[3] - sample, d4 = smp[4] - sample, d5 = smp[5] - sample, d6 = smp[6] - sample, d7 = smp[7] - sample; + int sum = denhalf + d0 * c0 + d1 * c1 + d2 * c2 + d3 * c3 + d4 * c4 + d5 * c5 + d6 * c6 + d7 * c7; + int resval = extend_sign32(smp[constOrder] - sample - (int)(sum >> shift), bps); + res[i] = resval; + + if (resval == 0) continue; + int orig_sign = sign_only(resval); + + int sign = sign_only(d0 ^ resval); + c0 += sign; + resval -= (d0 * sign >> shift) * (0 + 1); + if (resval * orig_sign <= 0) continue; + + sign = sign_only(d1 ^ resval); + c1 += sign; + resval -= (d1 * sign >> shift) * (1 + 1); + if (resval * orig_sign <= 0) continue; + + sign = sign_only(d2 ^ resval); + c2 += sign; + resval -= (d2 * sign >> shift) * (2 + 1); + if (resval * orig_sign <= 0) continue; + + sign = sign_only(d3 ^ resval); + c3 += sign; + resval -= (d3 * sign >> shift) * (3 + 1); + if (resval * orig_sign <= 0) continue; + + sign = sign_only(d4 ^ resval); + c4 += sign; + resval -= (d4 * sign >> shift) * (4 + 1); + if (resval * orig_sign <= 0) continue; + + sign = sign_only(d5 ^ resval); + c5 += sign; + resval -= (d5 * sign >> shift) * (5 + 1); + if (resval * orig_sign <= 0) continue; + + sign = sign_only(d6 ^ resval); + c6 += sign; + resval -= (d6 * sign >> shift) * (6 + 1); + if (resval * orig_sign <= 0) continue; + + sign = sign_only(d7 ^ resval); + c7 += sign; + resval -= (d7 * sign >> shift) * (7 + 1); + } + + coefs[0] = c0; + coefs[1] = c1; + coefs[2] = c2; + coefs[3] = c3; + coefs[4] = c4; + coefs[5] = c5; + coefs[6] = c6; + coefs[7] = c7; + res[n] = 1; // Stop byte to help alac_entropy_coder; + return; + } + } +#endif + + /* general case */ for (int i = order + 1; i < n; i++) { int sample = *(smp++); @@ -633,43 +710,43 @@ namespace CUETools.Codecs.ALAC return size; } - unsafe int alac_entropy_coder(int* res, int n, int bps, int modifier) - { - int history = initial_history; - int sign_modifier = 0; - int rice_historymult = modifier * history_mult / 4; - int size = 0; - int* fin = res + n; + //unsafe int alac_entropy_coder(int* res, int n, int bps, int modifier) + //{ + // int history = initial_history; + // int sign_modifier = 0; + // int rice_historymult = modifier * history_mult / 4; + // int size = 0; + // int* fin = res + n; - while (res < fin) - { - int k = BitReader.log2i((history >> 9) + 3); - int x = *(res++); - x = (x << 1) ^ (x >> 31); + // while (res < fin) + // { + // int k = BitReader.log2i((history >> 9) + 3); + // int x = *(res++); + // x = (x << 1) ^ (x >> 31); - size += encode_scalar(x - sign_modifier, Math.Min(k, k_modifier), bps); + // size += encode_scalar(x - sign_modifier, Math.Min(k, k_modifier), bps); - history += x * rice_historymult - ((history * rice_historymult) >> 9); + // history += x * rice_historymult - ((history * rice_historymult) >> 9); - sign_modifier = 0; - if (x > 0xFFFF) - history = 0xFFFF; + // sign_modifier = 0; + // if (x > 0xFFFF) + // history = 0xFFFF; - if (history < 128 && res < fin) - { - k = 7 - BitReader.log2i(history) + ((history + 16) >> 6); - int* res1 = res; - while (*res == 0) // we have a stop byte, so need not check if res < fin - res++; - int block_size = (int)(res - res1); - size += encode_scalar(block_size, Math.Min(k, k_modifier), 16); - //sign_modifier = (block_size <= 0xFFFF) ? 1 : 0; //never happens - sign_modifier = 1; - history = 0; - } - } - return size; - } + // if (history < 128 && res < fin) + // { + // k = 7 - BitReader.log2i(history) + ((history + 16) >> 6); + // int* res1 = res; + // while (*res == 0) // we have a stop byte, so need not check if res < fin + // res++; + // int block_size = (int)(res - res1); + // size += encode_scalar(block_size, Math.Min(k, k_modifier), 16); + // //sign_modifier = (block_size <= 0xFFFF) ? 1 : 0; //never happens + // sign_modifier = 1; + // history = 0; + // } + // } + // return size; + //} /// /// Crude estimation of entropy length diff --git a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.vcxproj b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.vcxproj index a27b372..ddd45e8 100644 --- a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.vcxproj +++ b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.vcxproj @@ -41,6 +41,7 @@ Unicode true true + v90 DynamicLibrary diff --git a/CUETools.Parity/Parity2Syndrome.cs b/CUETools.Parity/Parity2Syndrome.cs index 9733757..95308d2 100644 --- a/CUETools.Parity/Parity2Syndrome.cs +++ b/CUETools.Parity/Parity2Syndrome.cs @@ -39,14 +39,35 @@ namespace CUETools.Parity erasure_diff = Galois16.instance.gfdiff(erasure_loc_pol); } - public static unsafe string ToBase64String(ushort[,] inArray, int offset, int length) + public static unsafe byte[] Syndrome2Bytes(ushort[,] inArray) { - var outBuf = new byte[inArray.GetLength(1) * length * 2]; - fixed (ushort* inPtr = &inArray[offset, 0]) + int stride = inArray.GetLength(0); + int npar = inArray.GetLength(1); + var outBuf = new byte[npar * stride * 2]; fixed (byte* outPtr = outBuf) - for (int i = 0; i < inArray.GetLength(1) * length; i++) - ((ushort*)outPtr)[i] = inPtr[i]; - return Convert.ToBase64String(outBuf); + { + var ppar = (ushort*)outPtr; + for (int i = 0; i < npar; i++) + for (int j = 0; j < stride; j++) + ppar[j + i * stride] = inArray[j, i]; + } + return outBuf; + } + + public static unsafe ushort[,] Bytes2Syndrome(int stride, int npar, byte[] parity) + { + if (parity.Length < npar * stride * 2) + throw new Exception("invalid parity length"); + var syndrome = new ushort[stride, npar]; + fixed (byte* pbpar = parity) + fixed (ushort* psyn = syndrome) + { + var ppar = (ushort*)pbpar; + for (int i = 0; i < npar; i++) + for (int j = 0; j < stride; j++) + psyn[i + j * npar] = ppar[j + i * stride]; + } + return syndrome; } public static unsafe byte[] Syndrome2Parity(ushort[,] syndrome, byte[] parity = null) @@ -66,25 +87,20 @@ namespace CUETools.Parity return parity; } - public static unsafe ushort[,] Parity2Syndrome(int stride, int npar, int npar2, byte[] parity, int pos = 0) + public static unsafe ushort[,] Parity2Syndrome(int stride, int stride2, int npar, int npar2, byte[] parity, int pos = 0, int offset = 0) { + if (npar > npar2 || stride > stride2) + throw new InvalidOperationException(); var syndrome = new ushort[stride, npar]; fixed (byte* pbpar = &parity[pos]) - fixed (ushort* psyn = syndrome) - Parity2Syndrome((ushort*)pbpar, psyn, stride, npar, npar2); - return syndrome; - } - - public static unsafe void Parity2Syndrome(ushort *ppar, ushort *psyn, int stride, int npar, int npar2) - { - if (npar > npar2) - throw new InvalidOperationException(); - fixed (ushort *plog = Galois16.instance.LogTbl, pexp = Galois16.instance.ExpTbl) + fixed (ushort* psyn = syndrome, plog = Galois16.instance.LogTbl, pexp = Galois16.instance.ExpTbl) { + var ppar = (ushort*)pbpar; for (int y = 0; y < stride; y++) { + int y1 = (y - offset + stride2) % stride2; ushort* syn = psyn + y * npar; - ushort* par = ppar + y * npar2; + ushort* par = ppar + y1 * npar2; for (int x1 = 0; x1 < npar2; x1++) { ushort lo = par[x1]; @@ -97,6 +113,7 @@ namespace CUETools.Parity } } } + return syndrome; } public unsafe void Syndrome2Parity(ushort* syndrome, ushort* parity) diff --git a/CUETools.Parity/RsDecode.cs b/CUETools.Parity/RsDecode.cs index b055289f38cc7f16061447ea030cdca3ce40b17d..306d77208c882acc4b6ce3520955703749486bd5 100644 GIT binary patch literal 28946 zcmezWuau#fA(J7GA)P^iA()|(p_rkBA(bJQ!J2`Wfr|l`tR90iLq0eKLo!1N zLncE$LmophgC2uBLn=caLn=cNLncEqK~q8)QW+{3N}%dMHs&!TGUPI(G88iuFeEZ0 zGo&&oFgP=WGPp8?Fyw>n1lbb6kO;P+grO4b&T25p$)L}m#h?XcD==s=C@}0dSYmL( z;I)Ajg91YkLomZ;gFgl*4SpLOHvq8?7=Y~LWB{o}uoM^^7!nyu8A=#381fm47!(+M z84?+a84?*P8A=(l88X2lnGBT-i40W?iC__A-5Cre3?&Q&3|0*K4EhYk4EYSD3`JnS zq=C&#XGmqxW5{ACV9;kMU?^h9XUKwvV=;q1LlHwNLn=cGSYHl9K0_`zZ1s_R1!EU5 zlrkhSoDMRi6+!1oD2xR zaDw9r&C!S+Mq8kE{V@vFdK!%)mn%8<*D z3r>}l40d2uAp1b_`ry<8iib>wG=@xY+$u0Qf%6C`|73$xd;x>M?+z z0>feEXof5XP)wCF#A5XyD9;yx!vix6ar+IFM^YI;v4_oXCyDl(ApyUg1pDnI*l#D9 zQT=uj$#1$0hE(-mF+(Lo9s@SNZ8!LAaMIwd!5@PM2B26&kBwpmP;3-4fMTPV0oBFD z4AJoXLavKJWmO5dbOV+Cm~mzY&W8pJpwjm+bDn`>c0nq-8&er_7(i(rq-KS|OM^eq zG8s94K}tnzHldb*rQlj9ks%FSZ@@~XWN=xQ%n;0w$pFa%z6?$bz6`L^2UJghYC(t` zD8)i_Lc~E~kGb$SerY2Bp3LiD@%vGa%v} zwZ?&@O$7#(Ak`rL_(=vFUDK-(_QB#&fguIzDo73n#eOV`>p2-P-3Dr1fNC#LXn@iU zsD1(QVI?O_9Nm4Oum{-}2hMY#(hydg>oMdqlrrQnXnC&vEY&!;VuORU2rOm zWzdAW5Y<0v4507>nXd>o-vA|S&_f3i0w6b}!@~j9RV57h3_c9`4CxFS3@LDXLH>YX z++hQWH&95~fL)WvU=4OXwlLvj0HyqB29Td2u?|b05Ro_r1#sN~aw({8f`yhVLj^+t zG|UVbAo@XN14tdnN3d{$xD`ag(qb041qF(;JO)U(=0d|1qzZyTZ2?e-Le$zZAaa8t zTF7FCExuHP9x||00~5y{LWn#K2@{apQR6CwA(Nqu0Xa;N(-H14;beg2OjuaJTm(wT z$Y~4|E(keDOo2iNlAA%YFbq=#D>tyIg0$3NI*1K1P`-z>LGYy~)bs-iD?|!IbuFqZ zaHnU4k0ACcFo047EY5TpbTQHd$PKVm2?;BN2qev+*DZ)RMwH7S8<67w;SNwbLG}x> zPhe>mWFsgQz;uCZ1i1wiBIxAGYv0QdMR88pECAV?bzlm{U; zLs+2t8N`CMRTUUOEpAwQ71Z)U#455n)clJ(Za`rKD~BOHK~TR?kHHsQTWi4EP^k7o z+FCF-f$RdA0SZ;*It3Ibur>*#gaL)00!lfJ91EzShzNIt8c00B;*=V#qiAp~j;(zJ zkwLV+L7@vN10gby+6CcX(0UZrE>JHCl-AJgK`${O zZc+gEtU-NSkRIG^!eVgEScy>|!BRaa4nU^B+P0cF>JQ|!3-SZZTo4P19v1yeP z>=RgP80IfT8sKDrqykXs2Vud|1M>I?WYj}}fg#fKe0%X^ct}X+R8IWG2Y>;>mK2!3rm~hc~X! z2$})|YF{J?I(h}l+o=pC3_jqoni2+Ah9d9?P!R(ty%fXSsGvRoB%DF%1(t&Iz-bf4 zgM|e490p6TsO2hhn+u^IRNsJdMIKr`gB)%O3~Atg6sWIe%>ZiwAF2KnCKj1xkY|u? zfEqfW5CNqVhgZ-Y*QEQ3IU9)kh{Mrc@N7@*sTJ+Fc4jy#4E22i<*oca_P zK>mUG7n1Kl;{c2X$S%Mft%2lO2ei>5m@Sw#zL6+C_j z5<#vJ36%n{a7UCApt1uIj@U~FP)z{yHLNB;%@-OBh77t48=2!6G8weMqk{;MEDVus zs0g~5$m6G=5(dNH$0_a53mMU^3wHljzDbP)~T( zGs!?RNTW2|AkBc$;JU#<1BUd>31Y$M{(_ZckTL{hJ}7@Pf^&MHK|HubQOssF$S@F% zcLCetZxC#dVE`$iK%=WY@gTS48^BBgxd%~JLHv!VU66a!pt%Upm^mmk5b+Edk3lY3 zVKo3Og@D`&(u3N=L~fPAN_EgUosWSbLzY3OK>^%_J_fPi@JlyvLMkUgIRZ6LfoceR zH5?*EL+UeF2!LA2h;W9K`ykU{eut!M&`cG`7x>575Pk-wHc-z5Ib<+f`=C?=G8NP> z0rkbvM_oYuvMdH{?e}yB(5NEto`K4kit*_ZPy}P3mSz1xdG&F zP_IaV0kw2rV({7ExWQqA^#(h^wGJq}knuSg#>Vc#8t^C)sMm;yD^P5M`gZty4a-4_4A{+8V^CvI zK$?F-ZEJyM4IwcMv8#e14GJM;GB)>v#2`5m#KMP@!SjNkTmY*n6~J`~Xch`$s{(@o zLj{8&gCTEp2Y={*+z7(Ng%U_52-800fouU`(%c2o0m7(hQvo~^3o2O< z;-C@+R61xdXfS|ED^O_&YOgCWs4_re8j-pnwIe9@VPeF^J;)`<7-2gk_8=q3usj4x z`^a{HdcvU67FCrUcr441!3^G`Mz#ST8&U({Q-Lf8D_udO!l3*H8WYBsw~_UN*yZ5d z1DcTqjmv^efsDZsml{DPfG~Nn4|97m1E`e`3F}N~9|&YBDVTmK9p)N1)1=n=w z>n!vbK)njk+Jig>H|WR%B$tBx0x8o$EQJ4HEfQFp3}y$hG%Q7fM#drO8PuvFB|pM! zqJMgZ*$i zHIXvc2kO;jV)W`DDF|W~s7DN2Q3w%%j3dFuO7bw~{vq<^3W=0-!(??N{EQ5$8nA;F(7UDCQd4^Dz!1zXBz6OIQ zgBF7k1E`LL_`w)S+!!v7+if5pLrg(-7o?Sk9BRm8FR&2^1@Kw|SSUiuK$srN>nWH? zkQEECQW?>%pp|{7=^ZpD3F>)(MlT>fMeW^Tt^|P8hoJTYqQwLA3nXvCc(8IGTipj! zgYFtwOQL|G4BGERbx#RHK73t5Cb-1~G6^zX0n4Qje?Uh1ky9Wiyu^itHpmvx>;}jT z5Qdlot0_Tae5d>%qxs3uQ9jXlf0P`DnD>CxA&}Y)xgLesf$9!e$RO(hxf+xwU^ODh zJrIl@Mxas()Zzq{C_V-Zeklf!kvm2r#_m8SqL#bV8NUOWiyHgLJY+T`j1luUu-OLC z980zV>RbluY>Kx5C>9VQiRusZ`UBx2m=1jNSzqaG*HhUHUrz28lfw4__!kTnt(Xm(Sn^Ui}W*9ROO<0h2+t1twO&0GTa^@In4X_zL7# zgg9bF0QT^Ms8nF6f{v(w@)Y`dFHk=ZG-9TUF_RA}TOcD-8Vn#efqFxru!LYpx~*c! zGuUac8oqKB7Amkj30r@R-co?MEFWI3A^ZYqcOsYf#MLgKk!#S1Tq$@xTo!?r4a87%y+M@pp!Ni$)e32ufJ%PINEE6`kg$b?8zjUa_G*KBJ|~$$y;e{R zgJyuT7!aX{n#N$Ed6-$90c5u(L!N<30A%H*1_P{|&ofAh=Z|kGTNlq3gh&sF+B*dv z)`;|kId6hHtc{@I3Yr~24{K061(g3lZ4-nqkn=Jp1H^v9A&%@i&{!X+r30G70HuA9 z?@0}LNVr36hlD$%y{64z2p*jyF8q<(!H`%7%}p?MC1)!zxH5p|2_d-))WU+rDlGLw zR=OZ!4-rBLlR#@n@(e&L3i1sQbNYD(83w)v*#>w0ZMs4YdcbpO-Qe{Gj7aq^#FSuz zV1sl6h;GmvNw`6lfeV@{)q&s@Gn6xAGL(Qvra&XE_}u~1hu=Lg zRiM>fpjHfMzls&OOo7P|qKPvf-4sMPAg|g7wW2|}7JoRPn+4+|n+aOY2r64Z@f^)y z1fN%gsU?<9VaO*bG+^eE7b-B_AXh{BoFG4tI}V6!8Yny<8O?Lw?- zm^#!s0#KVClF~uzr$BQs3Jj1LK@IS}#sUV&cp)eafch5-D59WP1odJe>*+yr^5mrx zQ0PMHFi7bO;*%T3Aia?Eg)ocM5GE~TlfY{kL3=2P^F1PG8#9dNY*@NP)Dxf>G=}z* zLF{M-oi13B5Kp_eWT}atuOy&$7X*mR9Gic-qv{DQ6o8)wrH^O^P>3N)cv4ddZA*C2 zX&j(&Y0!S$lF>4L2$u24^@b@*y?tdhm`c7mMON95jN%u$?@psgJK7wpZu7Cl{dJ@gw2q~ghA~R z*fL6op*i$;h zT-Z)n&P(wt(;DMC?C@jIo3Ca)ND0 z0ZxD#sx+YFP}(@-Xuu@(^1#WI#4TX6UpS5Mcr{4k?YBjiMK=vJVh1{35wwyVHcpGI9+cA%rj<_( zMahTgromblxJ)8uk1b@)2+Ra*z5~tcf@Wh0`3*5ojn6dl_v#{_I)GRmfzK}dXS5+! z{DIDiLfspTm>0%BKU>C-&yWc|(FoMuMlMk`7?Kz&!Mp!KVG3IF0!c@pG9A{!M@|jM z;;?u{h(XMN#1*0_IrWOA+%2FGEfNso!$T{2`3qVTmV|NjcF=ql|IB|kQ!dUzYWN0 zkjoV0wkOP$pfUm!CZN+nL9Ia2%MXM}nBfdcrJ%ECL8~$#IUO_u4T=ZQskWdMeK5Bo z+K`~U2RZ8vImbY9G2+yk8ipDM&>lt5S-TR^b@ss%wO-h$T0 zgH{59XwW({&`G}q@RNi!7?c>$+tZ+UDF>gG0;)|>ZC8TlLWEtQGl)Sp6~Rwq1C>c2 zc@PG<1=L0cwF;0=(S)ohL#Tj+8>B3ToHGO|k6>33TQ$=oCCeje#8gpqPZ%4q9V`a2@(dK!{z~p!HTDzd_QwVj(2GBXmMm zgdzJJbaKjJ<_v?A%;@K)fYJo4gaMsj13Q@se@K8_09t@W%wCPK5XqJw3u)i9J0kf>&KZ_5-4>X@-~y3Ip`? z2Qv{QhX_0T=@Gl{VYxz)0kg~k^=BYy6BGvEGL?Y~e98?dM`6~?uv!r0DtspZ0X$BCUKT=3LX_I5 zW}>SGnFBjf1~C=^@;&lM1L~@1 z3TNCSCLrIAj+cOX)VO=hqvIu`<0a&+*M_yak$dK_GMGL+5l}raI$l!DP>OVpKekvw z)NJ_TWnjlk(ATTOQWB_cg0v7(+xf`iu=*Gw25F@uYI=wX5K+`xA6W(wPKde&QG<<+ zn1E_rP#A;8Jy1tXkYjIj)C88xAZ;^H4GS7q1C>^zqb86RJfxHYg$Q}0Cb-T}1g)t7 zorVRXHNbZkA)i=9Oqnt|iUP{zqoXKA44_l$5&byO7{=%*3TW3D=x!*`h}Ga2MS+#E zuo1k`@e|NU1n4fW;W&N*i*3|V4&rJ9!XxUi`T@P&h}rU_T`i#jzDW->t_>=OLA%Hl z7(hG16c`{YrO;1+0I33vZG%S7VIzOk97PA!(daE-SV)3eH83`8)=-TB7K+hu79>1D z_sPKG4`eDRox)CHN1y#bue&wj^Qn-zHstX=(0l`Ez6N$?KKdLJsKpAK`#>JcLmuUW Lj84JU2tjxNCOyvr delta 1692 zcmbRAh;hb7#tl(SlheY5bW0hE88R618HyN67@`?;7!(+E7-AU|7?K$>7%~}B8S)rH z7!nzh7;+d=8LTHK#%WJ(U|PV*$pC`-4EmGfBgH4j$@1BnF_pGAhR_XFbxM;4zd6gJaEG& z&t~@L&SNNGNMtBtP-3u~EX!uhY{Q^G*`7^uvRJTydKp7LLncEC*pc`=zn)3a6Pu?M z7(gD(V@PEvXHZ~3jVL1qQwB4Ta~X`lBs`!e_h*Su=Hl1jM2HCT%1{1a$X5>+!5X>I z43MCOkccoaV6aAtP~<4Z=4O~F;GjebNdpG!$rGhOE)!8rVu1L}kinWkfgzIt#J6Ek zV1W1uDmMAPq5R}1EMIRyqA29QY>lM6Yu zCx6i3LkR`N$zEInhJ-=^WFIJ=;o&ejTTWiqm7#*6fFT5&5uzD#81fm?!LBi2P+-uW zoG&LmIZl>?S(ia!^2QKRqV0f(5?(tDvDhIzIf0jF@*F9y$#J0qn;n>!h)9AQjhsjn z7_`6<9Wr@6llWvE6Oqk)60?{%;Yud2mQqLJU6rck*FZ^Snv(;iODA6w<`aaaa!|a1 z(xk;?c~0rcdAw4SKWL~;_TZA5Y@{tUc@CGz&ICS9?~HM)G0Lv+n1cjy{SPU91rET$I$*XPA0AkK;60tJR*hIEE328GGq-?3~CGt-~u6yA&o(k0TdJp3>Hw@2o#M%?*aRhpBD4Sj3xh>LKFnf>-5jVho7p{$A(Nqk zAr)Mbp@uyqTtVeP2sBTF*yz=UCZznBoX96W`Io*CCn%wU)P;bG{mpg;Dy);!Vl6gH I`2JD`0GTmFssI20 diff --git a/CUETools.Processor/CUESheet.cs b/CUETools.Processor/CUESheet.cs index 51fdd8a..05e5e15 100644 --- a/CUETools.Processor/CUESheet.cs +++ b/CUETools.Processor/CUESheet.cs @@ -2263,26 +2263,7 @@ namespace CUETools.Processor return; if (_CUEToolsDB.SubStatus != null) sw.WriteLine("CUETools DB: {0}.", _CUEToolsDB.SubStatus); - if (_CUEToolsDB.DBStatus == null) - sw.WriteLine(" [ CTDBID ] Status"); - foreach (DBEntry entry in _CUEToolsDB.Entries) - { - string confFormat = (_CUEToolsDB.Total < 10) ? "{0:0}/{1:0}" : - (_CUEToolsDB.Total < 100) ? "{0:00}/{1:00}" : "{0:000}/{1:000}"; - string conf = string.Format(confFormat, entry.conf, _CUEToolsDB.Total); - string dataTrackInfo = !entry.toc[entry.toc.TrackCount].IsAudio ? string.Format("CD-Extra data track length {0}", entry.toc[entry.toc.TrackCount].LengthMSF) : - !entry.toc[1].IsAudio ? string.Format("Playstation type data track length {0}", entry.toc[entry.toc.FirstAudio].StartMSF) : "Has no data track"; - string status = - entry.toc.Pregap != _toc.Pregap ? string.Format("Has pregap length {0}", CDImageLayout.TimeToString(entry.toc.Pregap)) : - entry.toc.AudioLength != _toc.AudioLength ? string.Format("Has audio length {0}", CDImageLayout.TimeToString(entry.toc.AudioLength)) : - ((entry.toc.TrackOffsets != _toc.TrackOffsets) ? dataTrackInfo + ", " : "") + - ((!entry.hasErrors) ? "Accurately ripped" : - //((!entry.hasErrors) ? string.Format("Accurately ripped, offset {0}", -entry.offset) : - entry.canRecover ? string.Format("Differs in {0} samples @{1}", entry.repair.CorrectableErrors, entry.repair.AffectedSectors) : - (entry.httpStatus == 0 || entry.httpStatus == HttpStatusCode.OK) ? "No match" : - entry.httpStatus.ToString()); - sw.WriteLine(" [{0:x8}] ({1}) {2}", entry.crc, conf, status); - } + _CUEToolsDB.GenerateLog(sw, true); } public string GenerateAccurateRipStatus() diff --git a/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs b/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs index b5156d1..31e67cc 100644 --- a/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs +++ b/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs @@ -15,7 +15,7 @@ namespace CUETools.TestHelpers private int tempOffs; private int nextError; - public NoiseAndErrorsGenerator(AudioPCMConfig pcm, long sampleCount, int seed, int offset, int errors) + public NoiseAndErrorsGenerator(AudioPCMConfig pcm, long sampleCount, int seed, int offset, int errors, int maxStrideErrors = 0) { if (offset < 0) throw new ArgumentOutOfRangeException("offset", "offset cannot be negative"); @@ -35,8 +35,15 @@ namespace CUETools.TestHelpers rnd.NextBytes(new byte[byteOff % temp.Length]); this.errors = new int[errors]; this.rnd2 = new Random(seed); - for (int i = 0; i < errors; i++) - this.errors[i] = this.rnd2.Next(0, (int)sampleCount); + var strideErrors = new int[10 * 588]; + for (int i = 0; i < errors; i++) + { + do + { + this.errors[i] = this.rnd2.Next(0, (int)sampleCount); + } while (maxStrideErrors > 0 && strideErrors[this.errors[i] % (10 * 588)] >= maxStrideErrors); + strideErrors[this.errors[i] % (10 * 588)]++; + } this.rnd2 = new Random(seed); Array.Sort(this.errors); this.nextError = 0; diff --git a/CUETools.TestHelpers/TestImageGenerator.cs b/CUETools.TestHelpers/TestImageGenerator.cs index 2c2ab12..e16fd80 100644 --- a/CUETools.TestHelpers/TestImageGenerator.cs +++ b/CUETools.TestHelpers/TestImageGenerator.cs @@ -10,9 +10,9 @@ namespace CUETools.TestHelpers public class TestImageGenerator { public CDImageLayout toc; - public int seed, offset, start, end, errors; + public int seed, offset, start, end, errors, maxStrideErrors; - public TestImageGenerator(CDImageLayout toc, int seed, int offset, int errors, int start, int end) + public TestImageGenerator(CDImageLayout toc, int seed, int offset, int errors, int maxStrideErrors, int start, int end) { this.toc = toc; this.seed = seed; @@ -20,20 +20,21 @@ namespace CUETools.TestHelpers this.start = start; this.end = end; this.errors = errors; + this.maxStrideErrors = maxStrideErrors; } - public TestImageGenerator(string trackoffsets, int seed, int offset, int errors, int start, int end) - : this (new CDImageLayout(trackoffsets), seed, offset, errors, start, end) + public TestImageGenerator(string trackoffsets, int seed, int offset, int errors, int maxStrideErrors, int start, int end) + : this(new CDImageLayout(trackoffsets), seed, offset, errors, maxStrideErrors, start, end) { } - public TestImageGenerator(CDImageLayout toc, int seed, int offset, int errors) - : this(toc, seed, offset, errors, 0, (int)toc.AudioLength * 588) + public TestImageGenerator(CDImageLayout toc, int seed, int offset, int errors = 0, int maxStrideErrors = 0) + : this(toc, seed, offset, errors, maxStrideErrors, 0, (int)toc.AudioLength * 588) { } - public TestImageGenerator(string trackoffsets, int seed, int offset, int errors) - : this(new CDImageLayout(trackoffsets), seed, offset, errors) + public TestImageGenerator(string trackoffsets, int seed, int offset = 0, int errors = 0, int maxStrideErrors = 0) + : this(new CDImageLayout(trackoffsets), seed, offset, errors, maxStrideErrors) { } @@ -45,13 +46,14 @@ namespace CUETools.TestHelpers this.start = copy.start; this.end = copy.end; this.errors = copy.errors; + this.maxStrideErrors = copy.maxStrideErrors; } public void Write(IAudioDest dest) { if (start < 0 || start > end || end > toc.AudioLength * 588) throw new ArgumentOutOfRangeException(); - var src = new NoiseAndErrorsGenerator(AudioPCMConfig.RedBook, end - start, seed, offset + start, errors); + var src = new NoiseAndErrorsGenerator(AudioPCMConfig.RedBook, end - start, seed, offset + start, errors, maxStrideErrors); var buff = new AudioBuffer(src, 588 * 10); var rnd = new Random(seed); //dest.Position = start; @@ -82,13 +84,13 @@ namespace CUETools.TestHelpers public static AccurateRipVerify CreateAccurateRipVerify(string trackoffsets, int seed, int offset, int start, int end) { - var generator = new TestImageGenerator(trackoffsets, seed, offset, 0, start, end); + var generator = new TestImageGenerator(trackoffsets, seed, offset, 0, 0, start, end); return generator.CreateAccurateRipVerify(); } public static AccurateRipVerify CreateAccurateRipVerify(string trackoffsets, int seed, int offset) { - var generator = new TestImageGenerator(trackoffsets, seed, offset, 0); + var generator = new TestImageGenerator(trackoffsets, seed, offset, 0, 0); return generator.CreateAccurateRipVerify(); } } diff --git a/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs b/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs index 5485470..3727fb6 100644 --- a/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs +++ b/CUETools/CUETools.TestParity/CDRepairDecodeTest.cs @@ -35,9 +35,11 @@ namespace CUETools.TestParity private static TestImageGenerator generator; private static CDRepairEncode encode; - private static string[] encodeSyndrome = new string[33]; + private static string encodeSyndrome; + private static string encodeSyndromePosOffset; + private static string encodeSyndromeNegOffset; + private static string encodeSyndrome1; private static string[] encodeParity = new string[33]; - private static string[] encodeParity1 = new string[33]; private TestContext testContextInstance; /// @@ -66,13 +68,12 @@ namespace CUETools.TestParity { generator = new TestImageGenerator("0 9801", seed, 32 * 588, 0); encode = generator.CreateCDRepairEncode(stride); - encodeSyndrome[4] = "DP7tAM2tuWBe7kb/A3o5hcS+o59uoT1ckHh9Am+wZxA="; - encodeSyndrome[8] = "DP7tAM2tuWCBRjyLjt6a+l7uRv8DejmFzRtv3ofeEWzEvqOfbqE9XFOz/6WaYU+lkHh9Am+wZxCw3m1Y7zKctw=="; - encodeSyndrome[16] = "DP7tAM2tuWCBRjyLjt6a+lr7hvwnJWrfZ0MGKOYwFmVe7kb/A3o5hc0bb96H3hFsIcjxCpERbjnJjVvLc5NDJcS+o59uoT1cU7P/pZphT6WaQ4f3L/ImdyD5psk3fWRvkHh9Am+wZxCw3m1Y7zKct8QUsJHnLA6wcmxT/LmmQdE="; + encodeSyndrome = "DP5e7sS+kHjtAEb/o599As2tA3puoW+wuWA5hT1cZxCBRs0bU7Ow3jyLb97/pW1Yjt6H3pph7zKa+hFsT6Wct1r7IciaQ8QUhvzxCof3sJEnJZERL/LnLGrfbjkmdw6wZ0PJjSD5cmwGKFvLpslT/OYwc5M3fbmmFmVDJWRvQdE="; + encodeSyndromePosOffset = "x5gK5qlKM0HjrEEWOVHQX5VRqD0FtDWGqO/JP2ArcdR0yxE04pdR6B06J3iXbKv9CghrqvNiq+AlMAVWr/pm7bp5s3s+v5Bo3oYpQymmtd0FDKaZ4GQhi9yDu0Vm22j0Cllf5fLPFixhRMCBN/3S3t8IeHtVfmo5Vw0icN7OTHo="; + encodeSyndromeNegOffset = "wDLTEG5XPVhGlH8fuucGl8St2G/jGLyN3dByVGzOWeZ0CzI1M9jJq4DLj8A3XsMh8u80yvCq36SHXU+iO5cpVcfyiu08pqO1PjPUynqQa/aOcjbFhwjaEZePD42rQCBVdhViBeBEYzMhCTKroorw/Tt0AFC+NlRCMOsUmzSlsRU="; + encodeSyndrome1 = "YJNmzBE8sVjyo1l59bs/6I+Kqb4PRwEWY34ZHS/yKY5P+AzgGYtQrDplinhvvDKkjMpKOJm6iYplMDQ6OnR0ZwrzJv39czortUxnzOsjIxmzYtdszjDV6jFf/lA8+3lTS2veoTxIJ1a46z9+5hIbAthejftqYB8h9/PAk5PfWDk="; encodeParity[8] = "jvR9QJ1cSWpqbyP0I0tBrBkQRjCDTDDQkttZGj14ROvsXyg+AnnxVKxL7gwLZbrQmTw5ZPps1Q3744g94qaOOQ=="; encodeParity[16] = "gwln1GxlYWH/Jn74PreMLv4aFF2glkScSWVFlxMBx94v5D3/3wPx+2guRLquED0s9tOFikPLiSnAv0Xq8aIQ6Q=="; - encodeParity1[8] = "CWgEDNLjSi22nIOyaeyp+12R3UCVWlzIb+nbv8XWXg9YEhkHxYr8xqrr1+hIbFwKNEXnj0esJrKbiW3XGbHsYw=="; - encodeParity1[16] = "BdvaDZCGCVEggrcfscGQWdfSXnCSrOcpD6NfKZGYraK80J2a+v/zkDPWePOQ9k0u0WdWNJ9hQKvPJD0wf2MN+g=="; } // //Use ClassCleanup to run code after all tests in a class have run @@ -100,11 +101,20 @@ namespace CUETools.TestParity { for (int n = 4; n <= AccurateRipVerify.maxNpar; n *= 2) { - Assert.AreEqual(encodeSyndrome[n], ParityToSyndrome.ToBase64String(encode.AR.GetSyndrome(n), 0, 4)); + Assert.AreEqual(Convert.ToBase64String(Convert.FromBase64String(encodeSyndrome), 0, n * 2 * 4), Convert.ToBase64String(ParityToSyndrome.Syndrome2Bytes(encode.AR.GetSyndrome(n, 4))), "syndrome mismatch"); + Assert.AreEqual(Convert.ToBase64String(Convert.FromBase64String(encodeSyndromePosOffset), 0, n * 2 * 4), Convert.ToBase64String(ParityToSyndrome.Syndrome2Bytes(encode.AR.GetSyndrome(n, 4, offset))), "syndrome with offset mismatch"); + Assert.AreEqual(Convert.ToBase64String(Convert.FromBase64String(encodeSyndromeNegOffset), 0, n * 2 * 4), Convert.ToBase64String(ParityToSyndrome.Syndrome2Bytes(encode.AR.GetSyndrome(n, 4, -offset))), "syndrome with neg offset mismatch"); } Assert.AreEqual(377539636, encode.CRC); } + [TestMethod()] + public unsafe void CDRepairSyndrome2BytesTest() + { + var syndrome = encode.AR.GetSyndrome(); + CollectionAssert.AreEqual(syndrome, ParityToSyndrome.Bytes2Syndrome(stride, AccurateRipVerify.maxNpar, ParityToSyndrome.Syndrome2Bytes(syndrome))); + } + /// ///A test for Write /// @@ -113,7 +123,7 @@ namespace CUETools.TestParity { for (int n = 8; n <= AccurateRipVerify.maxNpar; n *= 2) { - Assert.AreEqual(encodeParity[n], Convert.ToBase64String(encode.AR.GetParity(n), 0, 64)); + Assert.AreEqual(encodeParity[n], Convert.ToBase64String(ParityToSyndrome.Syndrome2Parity(encode.AR.GetSyndrome(n)), 0, 64)); } Assert.AreEqual(377539636, encode.CRC); } @@ -135,24 +145,6 @@ namespace CUETools.TestParity Assert.AreEqual(0, actualOffset, "wrong offset"); } - /// - ///Verifying rip that is accurate with pregap - /// - [TestMethod()] - public void CDRepairDecodeOriginalWithPregapTest() - { - var generator2 = new TestImageGenerator("32 9833", seed, 0, 0); - var decode = generator2.CreateCDRepairEncode(stride); - int actualOffset; - bool hasErrors; - Assert.IsTrue(decode.FindOffset(encode.AR.GetSyndrome(), encode.CRC, out actualOffset, out hasErrors)); - Assert.IsTrue(hasErrors, "doesn't have errors"); - Assert.AreEqual(-1176, actualOffset, "wrong offset"); - CDRepairFix fix = decode.VerifyParity(encode.AR.GetSyndrome(), actualOffset); - Assert.IsTrue(fix.HasErrors, "doesn't have errors"); - Assert.IsTrue(fix.CanRecover, "cannot recover"); - } - /// ///Verifying rip that has errors /// @@ -166,7 +158,7 @@ namespace CUETools.TestParity Assert.IsTrue(decode.FindOffset(encode.AR.GetSyndrome(), encode.CRC, out actualOffset, out hasErrors)); Assert.IsTrue(hasErrors, "doesn't have errors"); Assert.AreEqual(0, actualOffset, "wrong offset"); - CDRepairFix fix = decode.VerifyParity(encode.AR.GetSyndrome(), actualOffset); + CDRepairFix fix = decode.VerifyParity(encode.AR.GetSyndrome(), encode.CRC, actualOffset); Assert.IsTrue(fix.HasErrors, "doesn't have errors"); Assert.IsTrue(fix.CanRecover, "cannot recover"); generator2.Write(fix); @@ -217,7 +209,7 @@ namespace CUETools.TestParity Assert.IsTrue(decode.FindOffset(syn, encode.CRC, out actualOffset, out hasErrors)); Assert.IsTrue(hasErrors, "doesn't have errors"); Assert.AreEqual(offset, actualOffset, "wrong offset"); - CDRepairFix fix = decode.VerifyParity(syn, actualOffset); + CDRepairFix fix = decode.VerifyParity(syn, encode.CRC, actualOffset); Assert.IsTrue(fix.HasErrors, "doesn't have errors"); Assert.IsTrue(fix.CanRecover, "cannot recover"); generator2.Write(fix); @@ -237,7 +229,7 @@ namespace CUETools.TestParity Assert.IsTrue(decode.FindOffset(encode.AR.GetSyndrome(), encode.CRC, out actualOffset, out hasErrors), "couldn't find offset"); Assert.IsTrue(hasErrors, "doesn't have errors"); Assert.AreEqual(-offset, actualOffset, "wrong offset"); - var fix = decode.VerifyParity(encode.AR.GetSyndrome(), actualOffset); + var fix = decode.VerifyParity(encode.AR.GetSyndrome(), encode.CRC, actualOffset); Assert.IsTrue(fix.HasErrors, "doesn't have errors"); Assert.IsTrue(fix.CanRecover, "cannot recover"); generator2.Write(fix); @@ -245,7 +237,7 @@ namespace CUETools.TestParity if (AccurateRipVerify.maxNpar > 8) { - fix = decode.VerifyParity(encode.AR.GetSyndrome(8), actualOffset); + fix = decode.VerifyParity(encode.AR.GetSyndrome(8), encode.CRC, actualOffset); Assert.IsTrue(fix.HasErrors, "doesn't have errors"); Assert.IsTrue(fix.CanRecover, "cannot recover"); generator2.Write(fix); @@ -304,12 +296,12 @@ namespace CUETools.TestParity var splits = new int[] { 1, 13 * 588 - 1, 13 * 588, 13 * 588 + 1, 30 * 588 - 1, 30 * 588, 30 * 588 + 1, 68 * 588 - 1, 68 * 588, 68 * 588 + 1 }; foreach (int split in splits) { - var ar1 = new TestImageGenerator("13 68 99 136", seed, 0, 0, 0, split).CreateCDRepairEncode(stride); - var ar2 = new TestImageGenerator("13 68 99 136", seed, 0, 0, split, (int)ar0.FinalSampleCount).CreateCDRepairEncode(stride); + var ar1 = new TestImageGenerator("13 68 99 136", seed, 0, 0, 0, 0, split).CreateCDRepairEncode(stride); + var ar2 = new TestImageGenerator("13 68 99 136", seed, 0, 0, 0, split, (int)ar0.FinalSampleCount).CreateCDRepairEncode(stride); ar1.AR.Combine(ar2.AR, split, (int)ar0.FinalSampleCount); string message = "split = " + CDImageLayout.TimeToString((uint)split / 588) + "." + (split % 588).ToString(); Assert.AreEqual(ar0.CRC, ar1.CRC, "CRC was not set correctly, " + message); - CollectionAssert.AreEqual(ar0.AR.GetParity(), ar1.AR.GetParity(), "Parity was not set correctly, " + message); + CollectionAssert.AreEqual(ar0.AR.GetSyndrome(), ar1.AR.GetSyndrome(), "Parity was not set correctly, " + message); } } @@ -321,8 +313,8 @@ namespace CUETools.TestParity { var seed = 723722; var split = 20 * 588; - var ar1 = new TestImageGenerator("13 68 99 136", seed, 0, 0, 0, split).CreateCDRepairEncode(stride); - var ar2 = new TestImageGenerator("13 68 99 136", seed, 0, 0, split, (int)ar1.FinalSampleCount).CreateCDRepairEncode(stride); + var ar1 = new TestImageGenerator("13 68 99 136", seed, 0, 0, 0, 0, split).CreateCDRepairEncode(stride); + var ar2 = new TestImageGenerator("13 68 99 136", seed, 0, 0, 0, split, (int)ar1.FinalSampleCount).CreateCDRepairEncode(stride); for (int i = 0; i < 20; i++) ar1.AR.Combine(ar2.AR, split, (int)ar1.FinalSampleCount); } @@ -333,18 +325,19 @@ namespace CUETools.TestParity [TestMethod()] public unsafe void CDRepairSyndrome2ParitySpeedTest() { - byte[] parityCopy = new byte[encode.AR.GetParity().Length]; var syndrome = encode.AR.GetSyndrome(); + byte[] parityCopy = ParityToSyndrome.Syndrome2Parity(syndrome); for (int t = 0; t < 100; t++) ParityToSyndrome.Syndrome2Parity(syndrome, parityCopy); - CollectionAssert.AreEqual(encode.AR.GetParity(), parityCopy); + CollectionAssert.AreEqual(syndrome, ParityToSyndrome.Parity2Syndrome(syndrome.GetLength(0), syndrome.GetLength(0), syndrome.GetLength(1), syndrome.GetLength(1), parityCopy)); } [TestMethod] public unsafe void CDRepairEncodeSynParTest() { - var parityCopy = ParityToSyndrome.Syndrome2Parity(encode.AR.GetSyndrome()); - CollectionAssert.AreEqual(encode.AR.GetParity(), parityCopy); + var syndrome = encode.AR.GetSyndrome(); + var parityCopy = ParityToSyndrome.Syndrome2Parity(syndrome); + CollectionAssert.AreEqual(syndrome, ParityToSyndrome.Parity2Syndrome(syndrome.GetLength(0), syndrome.GetLength(0), syndrome.GetLength(1), syndrome.GetLength(1), parityCopy)); } [TestMethod] @@ -352,19 +345,43 @@ namespace CUETools.TestParity { var generator = new TestImageGenerator("0 75000", seed, 0, 0); var encode = generator.CreateCDRepairEncode(stride); - Assert.AreEqual(encodeParity1[AccurateRipVerify.maxNpar], Convert.ToBase64String(encode.AR.GetParity(), 0, 64), "parity mismatch"); + Assert.AreEqual(Convert.ToBase64String(Convert.FromBase64String(encodeSyndrome1), 0, AccurateRipVerify.maxNpar * 2 * 4), + Convert.ToBase64String(ParityToSyndrome.Syndrome2Bytes(encode.AR.GetSyndrome(AccurateRipVerify.maxNpar, 4))), "syndrome mismatch"); } + /// + /// Verifying a very long rip. + /// + [TestMethod()] + [Ignore] + public void CDRepairVerifyParityLongTest() + { + var generator1 = new TestImageGenerator("0 655000", seed); + var encode1 = generator1.CreateCDRepairEncode(stride); + var generator2 = new TestImageGenerator("0 655000", seed, 0, stride / 2 * 3, 7); + var decode = generator2.CreateCDRepairEncode(stride); + int actualOffset; + bool hasErrors; + var syndrome = encode1.AR.GetSyndrome(); + Assert.IsTrue(decode.FindOffset(syndrome, encode1.CRC, out actualOffset, out hasErrors)); + Assert.IsTrue(hasErrors, "doesn't have errors"); + Assert.AreEqual(0, actualOffset, "wrong offset"); + CDRepairFix fix = decode.VerifyParity(syndrome, encode1.CRC, actualOffset); + Assert.IsTrue(fix.HasErrors, "doesn't have errors"); + Assert.IsTrue(fix.CanRecover, "cannot recover"); + } + /// ///Verifying rip that has errors /// [TestMethod()] - [Ignore] + //[Ignore] public void CDRepairVerifyParitySpeedTest() { - var generator1 = new TestImageGenerator("0 98011", seed, 32 * 588, 0); + var generator1 = new TestImageGenerator("0 98011", seed, 32 * 588); var encode1 = generator1.CreateCDRepairEncode(stride); - var generator2 = new TestImageGenerator("0 98011", seed, 32 * 588, errors/2); + var generator2 = new TestImageGenerator("0 98011", seed, 32 * 588, stride / 2 * 3, 7); + //var generator2 = new TestImageGenerator("0 98011", seed, 32 * 588, stride, 7); var decode = generator2.CreateCDRepairEncode(stride); int actualOffset; bool hasErrors; @@ -372,13 +389,28 @@ namespace CUETools.TestParity Assert.IsTrue(decode.FindOffset(syndrome, encode1.CRC, out actualOffset, out hasErrors)); Assert.IsTrue(hasErrors, "doesn't have errors"); Assert.AreEqual(0, actualOffset, "wrong offset"); - for (int t = 0; t < 1000; t++) - decode.VerifyParity(syndrome, actualOffset); - CDRepairFix fix = decode.VerifyParity(syndrome, actualOffset); + for (int t = 0; t < 100; t++) + decode.VerifyParity(syndrome, encode1.CRC, actualOffset); + CDRepairFix fix = decode.VerifyParity(syndrome, encode1.CRC, actualOffset); Assert.IsTrue(fix.HasErrors, "doesn't have errors"); Assert.IsTrue(fix.CanRecover, "cannot recover"); - generator2.Write(fix); - Assert.AreEqual(encode1.CRC, fix.CRC); - } + //generator2.Write(fix); + //Assert.AreEqual(encode1.CRC, fix.CRC); + + + //var encodeTable = Galois16.instance.makeEncodeTable(16); + //using (StreamWriter sr = new StreamWriter(@"D:\Work\cuetoolsnet\CUETools\x64\Release\ddd")) + //{ + // for (int i = 0; i < encodeTable.GetLength(0) * encodeTable.GetLength(1) * encodeTable.GetLength(2); i++) + // { + // if ((i % 16) == 0) + // sr.WriteLine(); + // sr.Write(string.Format("0x{0:X4}, ", pte[i])); + // } + // sr.Close(); + // throw new Exception("aa"); + //} + + } } } diff --git a/CUETools/localtestrun.testrunconfig b/CUETools/localtestrun.testrunconfig index 601a019..df05dd9 100644 --- a/CUETools/localtestrun.testrunconfig +++ b/CUETools/localtestrun.testrunconfig @@ -1,7 +1,6 @@ - - + + This is a default test run configuration for a local test run. - @@ -11,17 +10,26 @@ - - - - -
-
-
-
- - - - - - \ No newline at end of file + + + + + + +
+
+
+
+ + + + + + + + + + + + + \ No newline at end of file