/* devoc.c -- decode VOC files generated by RCA digital voice recorders. Tested with the RP5022B. Copyright (c) 2008 Dave Coffin, dcoffin a cybercom o net Devoc is free software, released under the GNU General Public License version 2.0. $Revision: 1.4 $ $Date: 2008/12/13 08:33:00 $ */ #include #include #include #include #define SQR(x) ((long long) (x)*(x)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define LIM(x,min,max) MAX(min,MIN(x,max)) #define SWAP(a,b) { a ^= b; a ^= (b ^= a); } #define SHL(i,j) ((j) > 0 ? (i) << (j) : (i) >> -(j)) FILE *ifp, *ofp; char *ifname, *ofname; int out_mode=3; union { char c[2]; short s; } bo_test; int read_cs (unsigned char *in, int len) { int zero=0, zbeg, off, i; while (1) { if (fread (in, 1, len, ifp) != len) return 0; for (zbeg=len; !in[zbeg-1] && --zbeg; ); if (zero) { if (!zbeg) return 0; for (zero=off=0, i=4; i--; ) off = off << 8 | in[i]; if (off >= 0) fseek (ifp, off-len, SEEK_CUR); } else if ((len-zbeg)/20 == 1) fseek(ifp, -20, SEEK_CUR); else if (!zbeg) zero = 1; else return 1; } } int sp_decode() { static const short tab7[128][10] = { { 1486, 2168, 3751, 9074,12134,13944,17983,19173,21190,21820 }, { 1730, 2640, 3450, 4870, 6126, 7876,15644,17817,20294,21902 }, { 1568, 2256, 3088, 4874,11063,13393,18307,19293,21109,21741 }, { 1733, 2512, 3357, 4708, 6977,10296,17024,17956,19145,20350 }, { 1744, 2436, 3308, 8731,10432,12007,15614,16639,21359,21913 }, { 1786, 2369, 3372, 4521, 6795,12963,17674,18988,20855,21640 }, { 1631, 2433, 3361, 6328,10709,12013,13277,13904,19441,21088 }, { 1489, 2364, 3291, 6250, 9227,10403,13843,15278,17721,21451 }, { 1869, 2533, 3475, 4365, 9152,14513,15908,17022,20611,21411 }, { 2070, 3025, 4333, 5854, 7805, 9231,10597,16047,20109,21834 }, { 1910, 2673, 3419, 4261,11168,15111,16577,17591,19310,20265 }, { 1141, 1815, 2624, 4623, 6495, 9588,13968,16428,19351,21286 }, { 2192, 3171, 4707, 5808,10904,12500,14162,15664,21124,21789 }, { 1286, 1907, 2548, 3453, 9574,11964,15978,17344,19691,22495 }, { 1921, 2720, 4604, 6684,11503,12992,14350,15262,16997,20791 }, { 2052, 2759, 3897, 5246, 6638,10267,15834,16814,18149,21675 }, { 1798, 2497, 5617,11449,13189,14711,17050,18195,20307,21182 }, { 1009, 1647, 2889, 5709, 9541,12354,15231,18494,20966,22033 }, { 3016, 3794, 5406, 7469,12488,13984,15328,16334,19952,20791 }, { 2203, 3040, 3796, 5442,11987,13512,14931,16370,17856,18803 }, { 2912, 4292, 7988, 9572,11562,13244,14556,16529,20004,21073 }, { 2861, 3607, 5923, 7034, 9234,12054,13729,18056,20262,20974 }, { 3069, 4311, 5967, 7367,11482,12699,14309,16233,18333,19172 }, { 2434, 3661, 4866, 5798,10383,11722,13049,15668,18862,19831 }, { 2020, 2605, 3860, 9241,13275,14644,16010,17099,19268,20251 }, { 1877, 2809, 3590, 4707,11056,12441,15622,17168,18761,19907 }, { 2107, 2873, 3673, 5799,13579,14687,15938,17077,18890,19831 }, { 1612, 2284, 2944, 3572, 8219,13959,15924,17239,18592,20117 }, { 2420, 3156, 6542,10215,12061,13534,15305,16452,18717,19880 }, { 1667, 2612, 3534, 5237,10513,11696,12940,16798,18058,19378 }, { 2388, 3017, 4839, 9333,11413,12730,15024,16248,17449,18677 }, { 1875, 2786, 4231, 6320, 8694,10149,11785,17013,18608,19960 }, { 679, 1411, 4654, 8006,11446,13249,15763,18127,20361,21567 }, { 1838, 2596, 3578, 4608, 5650,11274,14355,15886,20579,21754 }, { 1303, 1955, 2395, 3322,12023,13764,15883,18077,20180,21232 }, { 1438, 2102, 2663, 3462, 8328,10362,13763,17248,19732,22344 }, { 860, 1904, 6098, 7775, 9815,12007,14821,16709,19787,21132 }, { 1673, 2723, 3704, 6125, 7668, 9447,13683,14443,20538,21731 }, { 1246, 1849, 2902, 4508, 7221,12710,14835,16314,19335,22720 }, { 1525, 2260, 3862, 5659, 7342,11748,13370,14442,18044,21334 }, { 1196, 1846, 3104, 7063,10972,12905,14814,17037,19922,22636 }, { 2147, 3106, 4475, 6511, 8227, 9765,10984,12161,18971,21300 }, { 1585, 2405, 2994, 4036,11481,13177,14519,15431,19967,21275 }, { 1778, 2688, 3614, 4680, 9465,11064,12473,16320,19742,20800 }, { 1862, 2586, 3492, 6719,11708,13012,14364,16128,19610,20425 }, { 1395, 2156, 2669, 3386,10607,12125,13614,16705,18976,21367 }, { 1444, 2117, 3286, 6233, 9423,12981,14998,15853,17188,21857 }, { 2004, 2895, 3783, 4897, 6168, 7297,12609,16445,19297,21465 }, { 1495, 2863, 6360, 8100,11399,14271,15902,17711,20479,22061 }, { 2484, 3114, 5718, 7097, 8400,12616,14073,14847,20535,21396 }, { 2424, 3277, 5296, 6284,11290,12903,16022,17508,19333,20283 }, { 2565, 3778, 5360, 6989, 8782,10428,14390,15742,17770,21734 }, { 2727, 3384, 6613, 9254,10542,12236,14651,15687,20074,21102 }, { 1916, 2953, 6274, 8088, 9710,10925,12392,16434,20010,21183 }, { 3384, 4366, 5349, 7667,11180,12605,13921,15324,19901,20754 }, { 3075, 4283, 5951, 7619, 9604,11010,12384,14006,20658,21497 }, { 1751, 2455, 5147, 9966,11621,13176,14739,16470,20788,21756 }, { 1442, 2188, 3330, 6813, 8929,12135,14476,15306,19635,20544 }, { 2294, 2895, 4070, 8035,12233,13416,14762,17367,18952,19688 }, { 1937, 2659, 4602, 6697, 9071,12863,14197,15230,16047,18877 }, { 2071, 2663, 4216, 9445,10887,12292,13949,14909,19236,20341 }, { 1740, 2491, 3488, 8138, 9656,11153,13206,14688,20896,21907 }, { 2199, 2881, 4675, 8527,10051,11408,14435,15463,17190,20597 }, { 1943, 2988, 4177, 6039, 7478, 8536,14181,15551,17622,21579 }, { 1825, 3175, 7062, 9818,12824,15450,18330,19856,21830,22412 }, { 2464, 3046, 4822, 5977, 7696,15398,16730,17646,20588,21320 }, { 2550, 3393, 5305, 6920,10235,14083,18143,19195,20681,21336 }, { 3003, 3799, 5321, 6437, 7919,11643,15810,16846,18119,18980 }, { 3455, 4157, 6838, 8199, 9877,12314,15905,16826,19949,20892 }, { 3052, 3769, 4891, 5810, 6977,10126,14788,15990,19773,20904 }, { 3671, 4356, 5827, 6997, 8460,12084,14154,14939,19247,20423 }, { 2716, 3684, 5246, 6686, 8463,10001,12394,14131,16150,19776 }, { 1945, 2638, 4130, 7995,14338,15576,17057,18206,20225,20997 }, { 2304, 2928, 4122, 4824, 5640,13139,15825,16938,20108,21054 }, { 1800, 2516, 3350, 5219,13406,15948,17618,18540,20531,21252 }, { 1436, 2224, 2753, 4546, 9657,11245,15177,16317,17489,19135 }, { 2319, 2899, 4980, 6936, 8404,13489,15554,16281,20270,20911 }, { 2187, 2919, 4610, 5875, 7390,12556,14033,16794,20998,21769 }, { 2235, 2923, 5121, 6259, 8099,13589,15340,16340,17927,20159 }, { 1765, 2638, 3751, 5730, 7883,10108,13633,15419,16808,18574 }, { 3460, 5741, 9596,11742,14413,16080,18173,19090,20845,21601 }, { 3735, 4426, 6199, 7363, 9250,14489,16035,17026,19873,20876 }, { 3521, 4778, 6887, 8680,12717,14322,15950,18050,20166,21145 }, { 2141, 2968, 6865, 8051,10010,13159,14813,15861,17528,18655 }, { 4148, 6128, 9028,10871,12686,14005,15976,17208,19587,20595 }, { 4403, 5367, 6634, 8371,10163,11599,14963,16331,17982,18768 }, { 4091, 5386, 6852, 8770,11563,13290,15728,16930,19056,20102 }, { 2746, 3625, 5299, 7504,10262,11432,13172,15490,16875,17514 }, { 2248, 3556, 8539,10590,12665,14696,16515,17824,20268,21247 }, { 1279, 1960, 3920, 7793,10153,14753,16646,18139,20679,21466 }, { 2440, 3475, 6737, 8654,12190,14588,17119,17925,19110,19979 }, { 1879, 2514, 4497, 7572,10017,14948,16141,16897,18397,19376 }, { 2804, 3688, 7490,10086,11218,12711,16307,17470,20077,21126 }, { 2023, 2682, 3873, 8268,10255,11645,15187,17102,18965,19788 }, { 2823, 3605, 5815, 8595,10085,11469,16568,17462,18754,19876 }, { 2851, 3681, 5280, 7648, 9173,10338,14961,16148,17559,18474 }, { 1348, 2645, 5826, 8785,10620,12831,16255,18319,21133,22586 }, { 2141, 3036, 4293, 6082, 7593,10629,17158,18033,21466,22084 }, { 1608, 2375, 3384, 6878, 9970,11227,16928,17650,20185,21120 }, { 2774, 3616, 5014, 6557, 7788, 8959,17068,18302,19537,20542 }, { 1934, 4813, 6204, 7212, 8979,11665,15989,17811,20426,21703 }, { 2288, 3507, 5037, 6841, 8278, 9638,15066,16481,21653,22214 }, { 2951, 3771, 4878, 7578, 9016,10298,14490,15242,20223,20990 }, { 3256, 4791, 6601, 7521, 8644, 9707,13398,16078,19102,20249 }, { 1827, 2614, 3486, 6039,12149,13823,16191,17282,21423,22041 }, { 1000, 1704, 3002, 6335, 8471,10500,14878,16979,20026,22427 }, { 1646, 2286, 3109, 7245,11493,12791,16824,17667,18981,20222 }, { 1708, 2501, 3315, 6737, 8729, 9924,16089,17097,18374,19917 }, { 2623, 3510, 4478, 5645, 9862,11115,15219,18067,19583,20382 }, { 2518, 3434, 4728, 6388, 8082, 9285,13162,18383,19819,20552 }, { 1726, 2383, 4090, 6303, 7805,12845,14612,17608,19269,20181 }, { 2860, 3735, 4838, 6044, 7254, 8402,14031,16381,18037,19410 }, { 4247, 5993, 7952, 9792,12342,14653,17527,18774,20831,21699 }, { 3502, 4051, 5680, 6805, 8146,11945,16649,17444,20390,21564 }, { 3151, 4893, 5899, 7198,11418,13073,15124,17673,20520,21861 }, { 3960, 4848, 5926, 7259, 8811,10529,15661,16560,18196,20183 }, { 4499, 6604, 8036, 9251,10804,12627,15880,17512,20020,21046 }, { 4251, 5541, 6654, 8318, 9900,11686,15100,17093,20572,21687 }, { 3769, 5327, 7865, 9360,10684,11818,13660,15366,18733,19882 }, { 3083, 3969, 6248, 8121, 9798,10994,12393,13686,17888,19105 }, { 2731, 4670, 7063, 9201,11346,13735,16875,18797,20787,22360 }, { 1187, 2227, 4737, 7214, 9622,12633,15404,17968,20262,23533 }, { 1911, 2477, 3915,10098,11616,12955,16223,17138,19270,20729 }, { 1764, 2519, 3887, 6944, 9150,12590,16258,16984,17924,18435 }, { 1400, 3674, 7131, 8718,10688,12508,15708,17711,19720,21068 }, { 2322, 3073, 4287, 8108, 9407,10628,15862,16693,19714,21474 }, { 2630, 3339, 4758, 8360,10274,11333,12880,17374,19221,19936 }, { 1721, 2577, 5553, 7195, 8651,10686,15069,16953,18703,19929 } }; static const short tab5[32][10] = { { -435, -815, -742, 1033, -518, 582,-1201, 829, 86, 385 }, { -833, -891, 463, -8,-1251, 1450, 72, -231, 864, 661 }, { -1021, 231, -306, 321, -220, -163, -526, -754,-1633, 267 }, { 57, -198, -339, -33,-1468, 573, 796, -169, -631, 816 }, { 171, -350, 294, 1660, 453, 519, 291, 159, -640,-1296 }, { -701, -842, -58, 950, 892, 1549, 715, 527, -714, -193 }, { 584, 31, -289, 356, -333, -457, 612, -283,-1381, -741 }, { -109, -808, 231, 77, -87, -344, 1341, 1087, -654, -569 }, { -859, 1236, 550, 854, 714, -543,-1752, -195, -98, -276 }, { -877, -954,-1248, -299, 212, -235, -728, 949, 1517, 895 }, { -77, 344, -620, 763, 413, 502, -362, -960, -483, 1386 }, { -314, -307, -256,-1260, -429, 450, -466, -108, 1010, 2223 }, { 711, 693, 521, 650, 1305, -28, -378, 744,-1005, 240 }, { -112, -271, -500, 946, 1733, 271, -15, 909, -259, 1688 }, { 575, -10, -468, -199, 1101,-1011, 581, -53, -747, 878 }, { 145, -285,-1280, -398, 36, -498,-1377, 18, -444, 1483 }, { -1133, -835, 1350, 1284, -95, 1015, -222, 443, 372, -354 }, { -1459,-1237, 416, -213, 466, 669, 659, 1640, 932, 534 }, { -15, 66, 468, 1019, -748, 1385, -182, -907, -721, -262 }, { -338, 148, 1445, 75, -760, 569, 1247, 337, 416, -121 }, { 389, 239, 1568, 981, 113, 369,-1003, -507, -587, -904 }, { -312, -98, 949, 31, 1104, 72, -141, 1465, 63, -785 }, { 1127, 584, 835, 277,-1159, 208, 301, -882, 117, -404 }, { 539, -114, 856, -493, 223, -912, 623, -76, 276, -440 }, { 2197, 2337, 1268, 670, 304, -267, -525, 140, 882, -139 }, { -1596, 550, 801, -456, -56, -697, 865, 1060, 413, 446 }, { 1154, 593, -77, 1237, -31, 581,-1037, -895, 669, 297 }, { 397, 558, 203, -797, -919, 3, 692, -292, 1050, 782 }, { 334, 1475, 632, -80, 48,-1061, -484, 362, -597, -852 }, { -545, -330, -429, -680, 1133,-1182, -744, 1340, 262, 63 }, { 1320, 827, -398, -576, 341, -774, -483,-1247, -70, 98 }, { -163, 674, -11, -886, 531,-1125, -265, -242, 724, 934 } }; static const short tab3[2][4][10] = { { { 8421,9109,9175,8965,9034,9057,8765,8775,9106,8673 }, { 7018,7189,7638,7307,7444,7379,7038,6956,6930,6868 }, { 5472,4990,5134,5177,5246,5141,5206,5095,4830,5147 }, { 4056,3031,2614,3024,2916,2713,3309,3237,2857,3473 } }, { { 7733,7880,8188,8175,8247,8490,8637,8601,8359,7569 }, { 4210,3031,2552,3473,3876,3853,4184,4154,3909,3968 }, { 3214,1930,1313,2143,2493,2385,2755,2706,2542,2919 }, { 3024,1592, 940,1631,1723,1579,2034,2084,1913,2601 } } }; static const short tab1[2][10] = { { 7798, 8447, 8205, 8293, 8126, 8477, 8447, 8703, 9043, 8604 }, { 14585,18333,19772,17344,16426,16459,15155,15220,16043,15708 } }; static const short tab0[10] = { 2339, 4679, 7018, 9358,11698,14037,16377,18717,21056,23396 }; static const short stab[64] = { 32767, 32729, 32610, 32413, 32138, 31786, 31357, 30853, 30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279, 23170, 22006, 20788, 19520, 18205, 16846, 15447, 14010, 12540, 11039, 9512, 7962, 6393, 4808, 3212, 1608, 0, -1608, -3212, -4808, -6393, -7962, -9512,-11039, -12540,-14010,-15447,-16846,-18205,-19520,-20788,-22006, -23170,-24279,-25330,-26320,-27246,-28106,-28899,-29622, -30274,-30853,-31357,-31786,-32138,-32413,-32610,-32729 }; static const short mtab[64] = { -632, -1893, -3150, -4399, -5638, -6863, -8072, -9261, -10428,-11570,-12684,-13767,-14817,-15832,-16808,-17744, -18637,-19486,-20287,-21039,-21741,-22390,-22986,-23526, -24009,-24435,-24801,-25108,-25354,-25540,-25664,-25726, -25726,-25664,-25540,-25354,-25108,-24801,-24435,-24009, -23526,-22986,-22390,-21741,-21039,-20287,-19486,-18637, -17744,-16808,-15832,-14817,-13767,-12684,-11570,-10428, -9261, -8072, -6863, -5638, -4399, -3150, -1893, -632 }; static const short pulse[61] = { 0,70,91,34,-79,-165,-120,78,296,308,0,-451,-634,-245,550,1099,756,-464, -1666,-1652,0,2259,3130,1211,-2783,-5850,-4402,3143,14701,25207,29443, 25207,14701,3143,-4402,-5850,-2783,1211,3130,2259,0,-1652,-1666,-464, 756,1099,550,-245,-634,-451,0,308,296,78,-120,-165,-79,34,91,70,0 }; static const short pulse2[7][16] = { { -40,72,-156,315,-579,1023,-1874,4439,31915,-3390,1595,-887,501,-266,130,-59 }, { -77,147,-317,631,-1150,2030,-3773,9639,29436,-5579,2727,-1527,859,-453,218,-101 }, { -106,212,-455,892,-1614,2850,-5392,15206,25569,-6549,3303,-1860,1041,-543,258,-122 }, { -123,253,-538,1044,-1876,3319,-6414,20676,20676,-6414,3319,-1876,1044,-538,253,-123 }, { -122,258,-543,1041,-1860,3303,-6549,25569,15206,-5392,2850,-1614,892,-455,212,-106 }, { -101,218,-453,859,-1527,2727,-5579,29436,9639,-3773,2030,-1150,631,-317,147,-77 }, { -59,130,-266,501,-887,1595,-3390,31915,4439,-1874,1023,-579,315,-156,72,-40 } }; static const short xtab[12] = { 7699,-15398,7699,8192,15836,-7667,1899,-3798,1899,4096,7807,-3733 }; static const short ttab[40] = { 1,3,6,8,11,13,16,18,21,23,26,28,31,33,36,38, 0,2,4,5,7,9,10,12,14,15,17,19,20,22,24,25,27,29,30,32,34,35,37,39 }; static const short dtab[] = { 30000,26000,21000,15000,8000,0,-8000,-15000,-21000,-26000 }; static const short etab[2][33] = { { 0, 1455, 2866, 4236, 5568, 6863, 8124, 9352,10549,11716,12855, 13967,15054,16117,17156,18172,19167,20142,21097,22033,22951,23852, 24735,25603,26455,27291,28113,28922,29716,30497,31266,32023,32767 }, { 16384,16743,17109,17484,17867,18258,18658,19066,19484,19911,20347, 20792,21247,21713,22188,22674,23170,23678,24196,24726,25268,25821, 26386,26964,27554,28158,28774,29405,30048,30706,31379,32066,32767 } }; static const short ktab[4][8] = { { 5849,2929,9425,6068,3617,3171,3915,4987 }, { 0,3988,4478,7876,10291,10828,11956,16423 }, { 0,1078,2731,6093, 6747, 9280,12872,22294 }, { 4175,0,7324,7821,11385,27602,10735,15724 } }; static const short ltab[3][40] = { { 14690,11518,1268,-2762,-5672,7514,-36,-2808,-3041,4823,2952,-8425,3785, 1455,2179,-8638,8051,-2104,-1455,777,1108,-2386,2254,-364,-675,-2104,6046, -5682,1072,3123,-5059,5312,-2330,-3729,6924,-3890,675,-1776,29,10145 }, { 30274,3831,-4037,2972,-1049,-1003,2477,-3044,2815,-2232,1753,-1612,1714, -1776,1543,-1009,429,-170,472,-1265,2176,-2707,2523,-1622,344,826,-1530, 1724,-1658,1701,-2064,2644,-3061,2897,-1979,557,780,-1370,842,655 }, { 32767,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }; static const short ptab[7][4] = { { -188,2873,31650,-1597 }, { -484,7041,28469,-2147 }, { -933,12266,23705,-1992 }, { -1492,18050,18050,-1492 }, { -1992,23705,12266,-933 }, { -2147,28469,7041,-484 }, { -1597,31650,2873,-188 } }; static const short ntab[2] = { 22938, 18022 }; static const short itab[4] = { 5571,4751,2785,1556 }; static const char chlen[10] = { 8,10,8,6,2,5,4,6,2,5 }; unsigned char in[8]; int vtab[4][10], alpha[10], beta[10], gamma[10], delta[3][10]; int iota[4] = { -3670016,-3670016,-3670016,-3670016 }; int ccdh[6] = { 0,0,0,0,0,0 }, ccd=0, dold=0, dcnt=0, eold=0; int bach[] = { 30,30 }, psig[] = { 0,0,0 }, carry=0x400000; long long epsilon[2][6], rsum[7][2], sum, psum, pmax, rmax, smax; long long rssh, osum, prod1, prod2, pssm[] = { 0,0 }; int zeta[2][11], look[240], xi[200], pi[200], phi[20]; int theta[40], kappa[120], lambda[40], mu[40], tau[80], sigma[80]; int diff, back=0, fback, a, b, c, d, e, f, i, j, k, m; int mant, hi, lo, kasum, nu[2][11], rho[7][41], *chi; int emax, expo, expo1, expo2, expo3; short out[80]; memset (look, 0, sizeof look); memset (kappa, 0, sizeof kappa); memset (xi, 0, sizeof xi); memset (tau, 0, sizeof tau); for (i=0; i < 10; i++) delta[0][i] = dtab[i] << 8; for (j=0; j < 4; j++) for (i=0; i < 10; i++) vtab[j][i] = tab0[i] << 8; while (read_cs (in, 7)) { for (b=i=0; i < 10; i++) for (alpha[i]=j=0; j < chlen[i]; j++, b++) alpha[i] |= (in[b >> 3] >> (~b & 7) & 1) << j; for (i=0; i <= 4; i+=4) { alpha[3+i] = ((alpha[3+i] >> 3) * 24 | (alpha[3+i] & 7)) << 1 | 1; alpha[5+i] <<= 1; } for (i=0; i < 10; i++) beta[i] = (tab7[alpha[0] & 127][i] + tab5[alpha[1] >> (5-i/5*5) & 31][i]) << 8; for (j=2; j > 0; j--) for (i=0; i < 9; i++) if ((diff = (beta[i]-beta[i+1] + j*1280) >> 1) > 0) { beta[i] -= diff; beta[i+1] += diff; } for (i=0; i < 10; i++) { sum = (long long) tab1[alpha[0] >> 7][i] * beta[i]; for (j=0; j < 4; j++) sum += (long long) tab3[alpha[0] >> 7][j][i] * vtab[j][i]; gamma[i] = sum >> 15; } memmove (vtab+1, vtab, 3 * sizeof *vtab); memcpy (vtab, beta, sizeof beta); for (i=0; i < 9; i++) if (gamma[i] > gamma[i+1]) SWAP(gamma[i],gamma[i+1]); if (gamma[0] < 10240) gamma[0] = 10240; for (i=0; i < 9; i++) if (gamma[i+1] < gamma[i]+82176) gamma[i+1] = gamma[i]+82176; if (gamma[9] > 6574336) gamma[9] = 6574336; for (i=0; i < 10; i++) { j = (long long) gamma[i] * 20861 >> 23; k = MIN (j >> 8, 63); delta[2][i] = (stab[k] << 8) + (mtab[k] * (j & 255) >> 4); delta[1][i] = (delta[0][i] >> 1) + (delta[2][i] >> 1); } for (a=0; a < 2; a++) { for (b=0; b < 2; b++) { epsilon[b][0] = 0x10000000000LL; epsilon[b][1] = -0x40000LL * delta[a+1][b]; for (i=1; i < 5; i++) { epsilon[b][i+1] = epsilon[b][i-1]; for (j=1; j <= i; j++) { sum = ((epsilon[b][i-j+1] >> 32) * delta[a+1][b+i*2] << 9) + ((0x7fffff & epsilon[b][i-j+1] >> 9) * delta[a+1][b+i*2] >> 14); epsilon[b][i-j+2] += epsilon[b][i-j] - (sum << 1); } epsilon[b][1] -= 0x40000LL * delta[a+1][b+i*2]; } } for (i=6; --i; ) { epsilon[0][i] += epsilon[0][i-1]; epsilon[1][i] -= epsilon[1][i-1]; } zeta[a][0] = 0x100000; for (i=1; i < 6; i++) { zeta[a][i] = (epsilon[0][i] + epsilon[1][i]) >> 21; zeta[a][11-i] = (epsilon[0][i] - epsilon[1][i]) >> 21; } } memcpy (delta[0], delta[2], sizeof delta[0]); for (a=0; a < 8; a+=4) { if (a == (fback = 0)) { if (alpha[2] < 197) { back = (alpha[2] + 59) / 3; fback = alpha[2] + 58 - 3*back; } else back = alpha[2] - 112; } else { back = LIM (back, 25, 139) - 5; if (alpha[6] < 4) back += alpha[6]; else if (alpha[6] > 11) back += alpha[6] - 6; else { back += (alpha[6] + 7) / 3; fback = (alpha[6] + 1) % 3 - 1; } } bach[a >> 2] = back; fback = (fback + 2) % 3 + 1; for (i=0; i < 40; i++) { for (sum=0, j=-10; j < 10; j++) sum += (long long) pulse[30+fback+j*3] * look[160+(fback > 1)+a*10-back+i+j]; look[160+a*10+i] = sum >> 15; } ccd = LIM (ccd, 3277, 13017); memset (theta, 0, sizeof theta); theta[ttab[ alpha[3+a] & 15 ]] = alpha[4+a] & 1 ? 0x1fff00:-0x200000; theta[ttab[(alpha[3+a]>>4)+16]] = alpha[4+a] & 2 ? 0x1fff00:-0x200000; for (i=back; i < 40; i++) theta[i] += (long long) theta[i-back] * ccd >> 14; for (sum=i=0; i < 40; i++) sum += (long long) theta[i]*theta[i]; for (expo=0; sum >> expo > 0; expo++); i = sum >> (expo-6) & 31; mant = (((long long) etab[0][i] << 23) + (SHL(sum,29-expo) & 0x7fffff) * (etab[0][i+1]-etab[0][i])) >> 23; sum = ((8147LL << 20) - 6165LL * (((expo-16) << 15) + mant)) << 5; for (i=0; i < 4; i++) sum += (long long) iota[i] * itab[i]; k = (sum >> 15) * 5439 >> 16; i = 31 & (k >> 10); j = 14 - (k >> 15); k = (etab[1][i] << 8) + ((k & 0x3ff) * (etab[1][i+1]-etab[1][i]) >> 2); hi = alpha[5+a] >> 3; lo = alpha[5+a] & 7; ccd = ktab[0][hi] + ktab[1][lo]; c = ktab[2][hi] + ktab[3][lo]; d = (long long) c * k >> (13+j); for (i=4; --i; ) iota[i] = iota[i-1]; for (expo=0; c >> expo > 0; expo++); i = SHL(c,6-expo) & 31; mant = (((long long) etab[0][i] << 23) + (long long) (SHL(c,29-expo) & 0x7fffff) * (etab[0][i+1]-etab[0][i])) >> 23; iota[0] = (((expo-15) << 15) + mant) * 6165 >> 7; for (i=0; i < 40; i++) look[160+a*10+i] = (((long long) look[160+a*10+i] * ccd << 8) + ((long long) theta[i] * d)) >> 22; for (i=6; --i; ) ccdh[i] = ccdh[i-1]; ccdh[0] = ccd; if (d >> 1 > dold) dcnt = 2; else if (dcnt) dcnt--; dold = d; e = ccd > 14744 ? 2 : ccd > 9830; for (f=i=0; i < 6; i++) if (ccdh[i] < 9830) f++; if (f > 2 && !dcnt) e = 0; if (e > eold + 1) e--; if (dcnt && e < 2) e++; eold = e; memset (mu, 0, sizeof mu); for (i=0; i < 40; i++) if (theta[i]) for (j=0; j < 40; j++) mu[j] += (long long) theta[i] * ltab[e][(j-i+40)%40] >> 15; for (i=0; i < 40; i++) lambda[i] = look[160+a*10+i] - ((long long) theta[i] * d >> 22) + ((long long) mu[i] * d >> 22); memmove (kappa, kappa+40, 80*sizeof *kappa); for (kasum=i=0; i < 40; i++) { kappa[80+i] = -lambda[i]; for (sum=j=0; j < 11; j++) sum += (long long) zeta[a>>2][j] * kappa[80+i-j]; kasum += abs(kappa[80+i] = -sum >> 20); } } for (sum=i=0; i < 80; i++) sum += (long long) look[160+i]*look[160+i]; for (expo=0; sum >> expo > 0; expo++); i = SHL(sum,6-expo) & 31; mant = (((long long) etab[0][i] << 23) + (SHL(sum,29-expo) & 0x7fffff) * (etab[0][i+1]-etab[0][i])) >> 23; memmove (look, look+80, 160*sizeof *look); for (a=0; a < 2; a++) { for (b=0; b < 2; b++) for (c = 1 << 23, i=0; i < 11; i++) { nu[b][i] = (long long) zeta[a][i] * c >> 23; c = (long long) c * ntab[b] >> 15; } for (i=0; i < 40; i++) { for (sum=j=0; j < 11; j++) sum += (long long) nu[1][j] * kappa[(a+1)*40+i-j]; tau[40+i] = xi[160+i] = sum >> 20; } for (c=0,i=8; i < 200; i++) c |= abs(xi[i]); for (expo1=0; c >> expo1 > 0; expo1++); for (i=0; i < 200; i++) pi[i] = SHL(xi[i],20-expo1); for (psum=i=0; i < 40; i++) psum += SQR(pi[160+i]); if (!psum) goto skip; for (expo=0; psum >> expo > 0; expo++); psum = SHL(psum,23-expo); for (smax=-1, j=bach[0]-1; j < bach[0]+2; j++) { for (sum=i=0; i < 40; i++) sum += (long long) pi[160+i] * pi[160+i-j]; if (sum < 0) sum = 0; if (smax < sum) { smax = sum; back = j; } } if (!smax) goto skip; for (pmax=i=0; i < 40; i++) pmax += SQR(pi[160-back+i]); for (rmax=i=0; i < 7; i++) { for (j=0; j < 41; j++) { for (sum=k=0; k < 4; k++) sum += (long long) pi[161-back+j-k] * ptab[i][k]; rho[i][j] = sum >> 15; } for (sum=0, j=1; j < 40; j++) sum += SQR(rho[i][j]); rsum[i][0] = sum + SQR(rho[i][ 0]); rsum[i][1] = sum + SQR(rho[i][40]); m = rsum[i][0] < rsum[i][1]; if (rmax < rsum[i][m]) rmax = rsum[i][m]; } if (!rmax) goto skip; for (emax=0; rmax >> emax > 0; emax++); if (emax < expo) emax = expo; pmax = SHL(pmax,23-emax); rmax = SHL(rmax,23-emax); smax = SHL(smax,23-emax); for (m=-1,i=0; i < 7; i++) for (j=0; j < 2; j++) { for (sum=k=0; k < 40; k++) sum += (long long) pi[160+k] * rho[i][j+k]; sum = MAX (0, SHL(sum,23-emax)); osum = ((sum*sum*2 >> 32) * pmax << 9) + ((sum*sum*2 >> 9 & 0x7fffff) * pmax >> 14); rssh = SHL(rsum[i][j],23-emax); if (osum > ((smax*smax*2 >> 32) * rssh << 9) + ((smax*smax*2 >> 9 & 0x7fffff) * rssh >> 14)) { smax = sum; pmax = rssh; m = i*2 + j; } } if (rmax > 1 && smax && smax*smax >> 7 << 8 >= SHL(psum*pmax,expo-emax)) { chi = xi+160-back; if (m < 0) goto mlt0; chi = mu; back += ~m & 1; for (i=0; i < 40; i++) { for (sum=j=0; j < 16; j++) sum += (long long) pi[168-back+i-j] * pulse2[m/2][j]; chi[i] = sum >> 15; } for (osum=i=0; i < 40; i++) osum += (long long) pi[160+i] * chi[i]; if (osum < 0) osum = 0; for (expo2=0; osum >> expo2 > 0; expo2++); if (expo2 < 30) expo2 = 30; osum >>= expo2-23; for (psum=i=0; i < 40; i++) psum += SQR(chi[i]); for (expo3=0; psum >> expo3 > 0; expo3++); if (expo3 < 30) expo3 = 30; psum >>= expo3-23; prod1 = ((smax*smax*2 >> 32) * psum << 9) + ((smax*smax*2 >> 9 & 0x7fffff) * psum >> 14); prod2 = ((osum*osum*2 >> 32) * pmax << 9) + ((osum*osum*2 >> 9 & 0x7fffff) * pmax >> 14); i = (emax*2 + expo3) - (expo2*2 + emax); if (i < 0) prod1 >>= -i; else prod2 >>= i; if (prod1 > prod2) chi = rho[m >> 1] + (m & 1); for (i=0; i < 40; i++) chi[i] = SHL(chi[i],expo1-20); if (prod1 > prod2) { mlt0: osum = smax; psum = pmax; expo2 = expo3 = emax; } osum = SHL(osum,expo2-expo3); j = (psum > osum) ? (psum << 15)/(psum + osum/2) : 0x5555; for (i=0; i < 40; i++) tau[40+i] = ((long long) j * tau[40+i] + (long long) (0x8000 - j) * chi[i]) >> 15; } skip: for (kasum=i=0; i < 20; i++) { phi[i] = i < 11 ? -nu[1][i] : 0; for (sum=j=0; j < 11; j++) if (i >= j) sum += (long long) nu[0][j] * phi[i-j]; kasum += abs (phi[i] = -sum >> 20); } for (psum=i=0; i < 20; i++) psum += SQR(phi[i]); for (osum=i=0; i < 19; i++) osum += (long long) phi[i] * phi[i+1]; for (expo=0; psum >> expo > 0; expo++); psum = SHL(psum,23-expo); osum = SHL(osum,23-expo); b = psum < abs(osum) ? 0 : (osum << 15) / -psum; if ((kasum >>= 2) > 0x40000) { c = (1LL << 33) / kasum; for (i=40; i < 80; i++) tau[i] = (long long) tau[i] * c >> 15; } for (i=40; i < 80; i++) { tau[i] = -tau[i]; for (sum=j=0; j < 11; j++) sum += (long long) nu[0][j] * tau[i-j]; tau[i] = -sum >> 20; } c = (b > 0 ? 6554:29491) * b >> 7; b = (b > 0) * 3; d = (1LL << (34+b)) / (0x800000 - abs(c)); c >>= 1; for (i=0; i < 40; i++) sigma[a*40+i] = ((((long long) tau[39+i] * c >> 22) + tau[40+i] + 128) * d >> (11+b)) + 128; for (sum=i=0; i < 40; i++) sum += abs (kappa[(a+1)*40+i]); for (expo=0; sum >> expo > 0; expo++); sum = sum << 15 >> expo; for (osum=i=0; i < 40; i++) osum += abs (sigma[a*40+i]); for (emax=0; osum >> emax > 0; emax++); if ((osum = osum << 15 >> emax)) { e = ((sum << 15) / osum << (7+expo-emax)) * 205 >> 14; for (i=0; i < 40; i++) { carry = (16179LL * carry >> 14) + e; sigma[a*40+i] = (long long) sigma[a*40+i] * carry >> 22; } } else carry = 0; memmove (xi, xi+40, 160*sizeof *xi); memcpy (tau, tau+40, 40*sizeof *tau); } for (i=0; i < 80; i++) { for (j=3; --j; ) psig[j] = psig[j-1]; psig[0] = sigma[i]; for (sum=j=0; j < 2; j++) sum += ((pssm[j] >> 32) * xtab[4+j] << 19) + ((pssm[j] >> 9 & 0x7fffff) * xtab[4+j] >> 4); for (j=0; j < 3; j++) sum += (long long) psig[j] * xtab[j] << 9; sigma[i] = sum >> 21; pssm[1] = pssm[0]; pssm[0] = sum; } for (i=0; i < 80; i++) out[i] = LIM (sigma[i] >> 8, -32768, 32767); if (bo_test.c[1] && out_mode == 3) swab (out, out, sizeof out); fwrite (out, 2, 80, ofp); } return 0; } int hq_decode() { static const short tab[2][16] = { { -2048,4,135,213,273,323,373,425,425,373,323,273,213,135,4,-2048 }, { -12,18,41,64,112,198,355,1122,1122,355,198,112,64,41,18,-12 } }; int pred[24], nib, map, diff, s, i; unsigned char in[40]; short out[80]; memset (pred, 0, sizeof pred); pred[1] = 544; while (read_cs (in, 40)) { for (s=0; s < 80; s++) { nib = in[s >> 1] >> ((s & 1) << 2) & 15; if (nib == 15) diff = 0; else { map = MAX ((pred[1] >> 2) + tab[0][nib], 0); diff = ((map & 127) + 128) << ((map >> 7 & 15) + 1); if (nib & 8) diff = -diff; } out[s] = LIM ((pred[0] << 2) + (diff >> 6), -32768, 32767); pred[1] += tab[1][nib] + (-pred[1] >> 5); pred[1] = LIM (pred[1], 544, 5120); for (i=24; --i > 12; ) pred[i] = pred[i-1]; pred[17] = diff; pred[15] = LIM (diff + (pred[2] << 8), -8388608, 8388607); pred[12] = LIM (diff + (pred[3] << 8), -8388608, 8388607); pred[5] = ((pred[5] * 32512 - LIM (pred[4] << 10, -8388608, 8388607) * ((pred[12] ^ pred[13]) >> 31 | 1)) >> 15) + (((pred[12] ^ pred[14]) >> 31 | 1) << 7); pred[5] = LIM (pred[5], -12288, 12288); pred[4] = (pred[4] * 255 >> 8) + 192 * ((pred[12] ^ pred[13]) >> 31 | 1); pred[4] = LIM (pred[4], -(15360-pred[5]), 15360-pred[5]); for (i=6; i < 12; i++) { pred[i] = pred[i] * 255 >> 8; if (diff) pred[i] += ((diff ^ pred[i+12]) >> 31 | 1) << 7; pred[i] = LIM (pred[i], -32768, 32767); } for (pred[2]=pred[3]=i=0; i < 8; i++) pred[2 + (i > 1)] += (long long) pred[4+i] * pred[15+i] >> 23 << 1; pred[0] = pred[2] += pred[3]; } if (bo_test.c[1] && out_mode == 3) swab (out, out, sizeof out); fwrite (out, 2, 80, ofp); } return 0; } int main (int argc, char **argv) { int arg=1, status, size, i; unsigned char b[32]; char *cp, riff[44]= "RIFF WAVEfmt \20\0\0\0\1\0\1\0@\37\0\0\200>\0\0\2\0\20\0data"; bo_test.s = 1; ofp = ifp = 0; ofname = 0; ifname = "stdin"; if (argc == 1) { fprintf (stderr, "Usage: %s [OPTION] file1.voc file2.voc ...\n\n" "-i Identify RCA VOC files without decoding\n" "-c Write 16-bit raw audio to standard output\n" "-p Play sound (SoX must be installed)\n" "-w Convert each RCA VOC file to WAV\n", argv[0]); return 1; } for (arg=1; arg < argc && argv[arg][0]=='-'; arg++) switch (argv[arg][1]) { case 'i': out_mode = 0; break; case 'c': out_mode = 1; break; case 'p': out_mode = 2; break; case 'w': out_mode = 3; break; } if (out_mode == 1 && (ofp = stdout) && isatty(1)) { fprintf (stderr, "Will not write sound to the terminal!\n"); return 1; } if (out_mode == 2 && !(ofp = popen ("play -t raw -s -2 -r 8000 -","w"))) { perror ("play"); return 1; } do { status = 1; if (arg < argc) { if (ifp) fclose(ifp); if (!(ifp = fopen (ifname = argv[arg],"rb"))) { perror (ifname); continue; } } else ifp = stdin; fread (b, 1, 31, ifp); if (memcmp (b+6, "_VOC_File", 9)) { fprintf (stderr, "%s is not an RCA VOC file.\n",ifname); continue; } if (out_mode == 0) { fprintf (stderr, "%s: model %.6s start %d/%02d/%02d %02d:%02d:%02d", ifname, b, 2000+b[16], b[17], b[18], b[19], b[20], b[21]); fprintf (stderr, " duration %02d:%02d:%02d.%02d quality %s\n", b[22], b[23], b[24], b[25], b[26] ? "HQ":"SP"); status = 0; continue; } if (out_mode == 3) { if (ofname) free(ofname); if (!(ofname = malloc (strlen(ifname) + 5))) return 1; strcpy (ofname, ifname); if ((cp = strrchr (ofname, '.'))) *cp = 0; strcat (ofname, ".wav"); if (ofp) fclose(ofp); if (!(ofp = fopen (ofname,"wb"))) perror (ofname); if (!ofp) continue; fwrite (riff, 1, 44, ofp); } i = b[15] == 12 ? 30 : 254; while (i--) fread (b, 1, 16, ifp); switch (b[26]) { case 0: status = sp_decode(); break; case 3: status = hq_decode(); break; default: fprintf (stderr, "%s: Unsupported compression\n", ifname); if (ofname) remove (ofname); continue; } if (out_mode == 3) { size = ftell(ofp); for (i=0; i < 4; i++) { riff[i+4 ] = (size - 8) >> i*8; riff[i+40] = (size - 44) >> i*8; } fseek (ofp, 0, SEEK_SET); fwrite (riff, 1, 44, ofp); } } while (++arg < argc); if (ifp) fclose(ifp); if (ofp) fclose(ofp); if (ofname) free(ofname); return status; }