1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-29 12:50:28 +00:00

Applies an ahead-of-time transformation to the exp table, and wraps it in a helper function.

This commit is contained in:
Thomas Harte 2020-04-17 22:33:13 -04:00
parent e58ba27c00
commit 6f7c8b35c5

View File

@ -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,42 +66,64 @@ 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);
}
/*
Credit for the fixed register lists goes to Nuke.YKT; I found them at: