From 6f7c8b35c5392cd518857ddbd8ec955e8dc73c4a Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 17 Apr 2020 22:33:13 -0400 Subject: [PATCH] Applies an ahead-of-time transformation to the `exp` table, and wraps it in a helper function. --- Components/OPL2/Implementation/Tables.h | 105 +++++++++++++++--------- 1 file changed, 68 insertions(+), 37 deletions(-) diff --git a/Components/OPL2/Implementation/Tables.h b/Components/OPL2/Implementation/Tables.h index 5d4845e10..2e03d0e3f 100644 --- a/Components/OPL2/Implementation/Tables.h +++ b/Components/OPL2/Implementation/Tables.h @@ -21,8 +21,17 @@ namespace OPL { */ -/// Defines the first quadrant of a sine curve, as calculated by round(-log(sin((x+0.5)*pi/256/2))/log(2)*256). -constexpr int log_sin[] = { +/// Defines the first quadrant of 1024-unit negative log to the base two of sine (that conveniently misses sin(0)). +/// +/// Expected branchless usage for a full 1024 unit output: +/// +/// constexpr int multiplier[] = { 1, -1 }; +/// constexpr int mask[] = { 0, 255 }; +/// +/// value = exp( log_sin[angle & 255] ^ mask[(angle >> 8) & 1]) * multitplier[(angle >> 9) & 1] +/// +/// ... where exp(x) = 2 ^ -x / 256 +constexpr int16_t log_sin[] = { 2137, 1731, 1543, 1419, 1326, 1252, 1190, 1137, 1091, 1050, 1013, 979, 949, 920, 894, 869, 846, 825, 804, 785, 767, 749, 732, 717, @@ -57,41 +66,63 @@ constexpr int log_sin[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -/// Defines exponentiation; to get exponential of x is (exp[x&255] + 1024) << (x >> 8) -constexpr int exp[] = { - 0, 3, 6, 8, 11, 14, 17, 20, - 22, 25, 28, 31, 34, 37, 40, 42, - 45, 48, 51, 54, 57, 60, 63, 66, - 69, 72, 75, 78, 81, 84, 87, 90, - 93, 96, 99, 102, 105, 108, 111, 114, - 117, 120, 123, 126, 130, 133, 136, 139, - 142, 145, 148, 152, 155, 158, 161, 164, - 168, 171, 174, 177, 181, 184, 187, 190, - 194, 197, 200, 204, 207, 210, 214, 217, - 220, 224, 227, 231, 234, 237, 241, 244, - 248, 251, 255, 258, 262, 265, 268, 272, - 276, 279, 283, 286, 290, 293, 297, 300, - 304, 308, 311, 315, 318, 322, 326, 329, - 333, 337, 340, 344, 348, 352, 355, 359, - 363, 367, 370, 374, 378, 382, 385, 389, - 393, 397, 401, 405, 409, 412, 416, 420, - 424, 428, 432, 436, 440, 444, 448, 452, - 456, 460, 464, 468, 472, 476, 480, 484, - 488, 492, 496, 501, 505, 509, 513, 517, - 521, 526, 530, 534, 538, 542, 547, 551, - 555, 560, 564, 568, 572, 577, 581, 585, - 590, 594, 599, 603, 607, 612, 616, 621, - 625, 630, 634, 639, 643, 648, 652, 657, - 661, 666, 670, 675, 680, 684, 689, 693, - 698, 703, 708, 712, 717, 722, 726, 731, - 736, 741, 745, 750, 755, 760, 765, 770, - 774, 779, 784, 789, 794, 799, 804, 809, - 814, 819, 824, 829, 834, 839, 844, 849, - 854, 859, 864, 869, 874, 880, 885, 890, - 895, 900, 906, 911, 916, 921, 927, 932, - 937, 942, 948, 953, 959, 964, 969, 975, - 980, 986, 991, 996, 1002, 1007, 1013, 1018 -}; +/*! + @returns 2 ^ -x/256 in 0.10 fixed-point form. +*/ +constexpr int exp(int x) { + /// A derivative of the exponent table in a real OPL2; mapped_exp[x] = (source[c ^ 0xff] << 1) | 0x800. + /// + /// The ahead-of-time transformation represents fixed work the OPL2 does when reading its table + /// independent on the input. + /// + /// The original table is a 0.10 fixed-point representation of 2^x - 1 with bit 10 implicitly set, where x is + /// in 0.8 fixed point. + /// + /// Since the log_sin table represents sine in a negative base-2 logarithm, values from it would need + /// to be negatived before being put into the original table. That's haned with the ^ 0xff. The | 0x800 is to + /// set the implicit bit 10 (subject to the shift). + /// + /// The shift by 1 is to allow the chip's exploitation of the recursive symmetry of the exponential table to + /// be achieved more easily. Specifically, to convert a logarithmic attenuation to a linear one, just perform: + /// + /// result = mapped_exp[x & 0xff] >> (x >> 8) + constexpr int mapped_exp[] = { + 4084, 4074, 4062, 4052, 4040, 4030, 4020, 4008, + 3998, 3986, 3976, 3966, 3954, 3944, 3932, 3922, + 3912, 3902, 3890, 3880, 3870, 3860, 3848, 3838, + 3828, 3818, 3808, 3796, 3786, 3776, 3766, 3756, + 3746, 3736, 3726, 3716, 3706, 3696, 3686, 3676, + 3666, 3656, 3646, 3636, 3626, 3616, 3606, 3596, + 3588, 3578, 3568, 3558, 3548, 3538, 3530, 3520, + 3510, 3500, 3492, 3482, 3472, 3464, 3454, 3444, + 3434, 3426, 3416, 3408, 3398, 3388, 3380, 3370, + 3362, 3352, 3344, 3334, 3326, 3316, 3308, 3298, + 3290, 3280, 3272, 3262, 3254, 3246, 3236, 3228, + 3218, 3210, 3202, 3192, 3184, 3176, 3168, 3158, + 3150, 3142, 3132, 3124, 3116, 3108, 3100, 3090, + 3082, 3074, 3066, 3058, 3050, 3040, 3032, 3024, + 3016, 3008, 3000, 2992, 2984, 2976, 2968, 2960, + 2952, 2944, 2936, 2928, 2920, 2912, 2904, 2896, + 2888, 2880, 2872, 2866, 2858, 2850, 2842, 2834, + 2826, 2818, 2812, 2804, 2796, 2788, 2782, 2774, + 2766, 2758, 2752, 2744, 2736, 2728, 2722, 2714, + 2706, 2700, 2692, 2684, 2678, 2670, 2664, 2656, + 2648, 2642, 2634, 2628, 2620, 2614, 2606, 2600, + 2592, 2584, 2578, 2572, 2564, 2558, 2550, 2544, + 2536, 2530, 2522, 2516, 2510, 2502, 2496, 2488, + 2482, 2476, 2468, 2462, 2456, 2448, 2442, 2436, + 2428, 2422, 2416, 2410, 2402, 2396, 2390, 2384, + 2376, 2370, 2364, 2358, 2352, 2344, 2338, 2332, + 2326, 2320, 2314, 2308, 2300, 2294, 2288, 2282, + 2276, 2270, 2264, 2258, 2252, 2246, 2240, 2234, + 2228, 2222, 2216, 2210, 2204, 2198, 2192, 2186, + 2180, 2174, 2168, 2162, 2156, 2150, 2144, 2138, + 2132, 2128, 2122, 2116, 2110, 2104, 2098, 2092, + 2088, 2082, 2076, 2070, 2064, 2060, 2054, 2048, + }; + + return mapped_exp[x & 0xff] >> (x >> 8); +} /*