diff options
author | Takamichi Horikawa <takamichiho@gmail.com> | 2017-08-23 21:13:48 +0900 |
---|---|---|
committer | Takamichi Horikawa <takamichiho@gmail.com> | 2017-08-23 21:13:48 +0900 |
commit | dfb3f4f10cc66a72027ae5869318cc10baf30a2e (patch) | |
tree | 596dfb3e1177478accaf89e9f94e0be3c10e3c5a | |
parent | f8a9839f5c133adbba53e5a3415f3b932bb81067 (diff) |
PPZ8: add sinc interpolation
-rw-r--r-- | fmdriver/ppz8-sinctable.inc | 264 | ||||
-rw-r--r-- | fmdriver/ppz8.c | 175 | ||||
-rw-r--r-- | fmdriver/ppz8.h | 13 |
3 files changed, 387 insertions, 65 deletions
diff --git a/fmdriver/ppz8-sinctable.inc b/fmdriver/ppz8-sinctable.inc new file mode 100644 index 0000000..9a6cf4f --- /dev/null +++ b/fmdriver/ppz8-sinctable.inc @@ -0,0 +1,264 @@ +// reference: fluidsynth src/rvoice/fluid_rvoice_dsp.c +// i_shifted = j - 3.5 + (255-i)/256; +// v = sinc(PI*i_shifted); +// v *= 0.5*(1.0 + cos(2PI * i_shifted / 7)); +// ppz8_sinctable[i][j] = round(sinc * ((1<<15)-1)); + +static const int16_t ppz8_sinctable[256][7] = { + { 778, -4227, 19656, 19998, -4273, 792, 0, }, + { 771, -4203, 19485, 20168, -4295, 799, 0, }, + { 764, -4179, 19313, 20337, -4317, 806, 0, }, + { 757, -4154, 19141, 20507, -4338, 813, 0, }, + { 750, -4129, 18968, 20675, -4358, 819, 0, }, + { 742, -4103, 18795, 20843, -4378, 826, 0, }, + { 735, -4077, 18622, 21011, -4397, 832, 0, }, + { 728, -4051, 18449, 21178, -4416, 838, -1, }, + { 720, -4023, 18275, 21344, -4434, 844, -1, }, + { 712, -3996, 18101, 21510, -4452, 850, -1, }, + { 705, -3968, 17926, 21676, -4469, 856, -1, }, + { 697, -3940, 17752, 21840, -4485, 862, -1, }, + { 689, -3911, 17577, 22004, -4500, 868, -2, }, + { 682, -3881, 17402, 22168, -4515, 873, -2, }, + { 674, -3852, 17227, 22330, -4530, 879, -2, }, + { 666, -3822, 17051, 22492, -4543, 884, -2, }, + { 658, -3791, 16876, 22653, -4556, 889, -3, }, + { 650, -3761, 16700, 22814, -4568, 894, -3, }, + { 642, -3730, 16524, 22974, -4580, 899, -3, }, + { 634, -3698, 16349, 23133, -4591, 904, -4, }, + { 626, -3666, 16173, 23291, -4601, 909, -4, }, + { 618, -3634, 15997, 23448, -4610, 913, -4, }, + { 610, -3602, 15820, 23605, -4619, 918, -5, }, + { 602, -3569, 15644, 23761, -4626, 922, -5, }, + { 594, -3536, 15468, 23916, -4634, 926, -6, }, + { 586, -3503, 15292, 24070, -4640, 930, -6, }, + { 578, -3469, 15116, 24223, -4645, 933, -7, }, + { 570, -3435, 14940, 24375, -4650, 937, -7, }, + { 562, -3401, 14764, 24527, -4654, 940, -7, }, + { 554, -3366, 14588, 24677, -4657, 943, -8, }, + { 546, -3332, 14412, 24827, -4660, 946, -8, }, + { 538, -3297, 14236, 24975, -4661, 949, -9, }, + { 530, -3262, 14061, 25123, -4662, 952, -10, }, + { 521, -3226, 13885, 25270, -4662, 954, -10, }, + { 513, -3191, 13710, 25415, -4661, 957, -11, }, + { 505, -3155, 13534, 25560, -4659, 959, -11, }, + { 497, -3119, 13359, 25703, -4657, 961, -12, }, + { 489, -3083, 13185, 25846, -4653, 963, -12, }, + { 481, -3047, 13010, 25987, -4649, 964, -13, }, + { 473, -3010, 12836, 26127, -4643, 965, -14, }, + { 465, -2974, 12662, 26267, -4637, 966, -14, }, + { 457, -2937, 12488, 26405, -4630, 967, -15, }, + { 449, -2900, 12314, 26542, -4622, 968, -15, }, + { 442, -2863, 12141, 26677, -4613, 968, -16, }, + { 434, -2826, 11968, 26812, -4603, 969, -17, }, + { 426, -2789, 11795, 26946, -4592, 969, -17, }, + { 418, -2751, 11623, 27078, -4581, 969, -18, }, + { 410, -2714, 11451, 27209, -4568, 968, -18, }, + { 403, -2676, 11279, 27339, -4554, 967, -19, }, + { 395, -2638, 11108, 27467, -4540, 967, -20, }, + { 387, -2601, 10937, 27595, -4524, 965, -20, }, + { 380, -2563, 10767, 27721, -4508, 964, -21, }, + { 372, -2525, 10597, 27846, -4490, 962, -22, }, + { 365, -2487, 10428, 27969, -4472, 961, -22, }, + { 357, -2449, 10259, 28092, -4452, 958, -23, }, + { 350, -2411, 10090, 28213, -4431, 956, -24, }, + { 343, -2373, 9922, 28332, -4410, 953, -24, }, + { 335, -2335, 9755, 28450, -4387, 951, -25, }, + { 328, -2297, 9588, 28567, -4364, 947, -25, }, + { 321, -2259, 9421, 28683, -4339, 944, -26, }, + { 314, -2221, 9255, 28797, -4313, 940, -27, }, + { 307, -2183, 9090, 28910, -4287, 936, -27, }, + { 300, -2145, 8925, 29021, -4259, 932, -28, }, + { 293, -2107, 8761, 29131, -4230, 928, -28, }, + { 286, -2069, 8597, 29239, -4200, 923, -29, }, + { 279, -2031, 8434, 29346, -4169, 918, -30, }, + { 272, -1994, 8272, 29452, -4137, 913, -30, }, + { 265, -1956, 8110, 29556, -4104, 907, -31, }, + { 259, -1918, 7949, 29659, -4070, 901, -31, }, + { 252, -1880, 7789, 29760, -4034, 895, -32, }, + { 246, -1843, 7629, 29859, -3998, 889, -32, }, + { 239, -1805, 7470, 29957, -3961, 882, -33, }, + { 233, -1768, 7312, 30054, -3922, 875, -33, }, + { 226, -1731, 7154, 30149, -3882, 868, -33, }, + { 220, -1693, 6998, 30243, -3841, 860, -34, }, + { 214, -1656, 6841, 30334, -3799, 852, -34, }, + { 208, -1619, 6686, 30425, -3756, 844, -35, }, + { 202, -1582, 6532, 30514, -3712, 836, -35, }, + { 196, -1546, 6378, 30601, -3667, 827, -35, }, + { 190, -1509, 6225, 30686, -3620, 818, -36, }, + { 184, -1472, 6073, 30770, -3572, 808, -36, }, + { 178, -1436, 5921, 30853, -3524, 798, -36, }, + { 173, -1400, 5771, 30933, -3474, 788, -36, }, + { 167, -1364, 5621, 31013, -3422, 778, -36, }, + { 162, -1328, 5472, 31090, -3370, 767, -37, }, + { 156, -1292, 5324, 31166, -3317, 756, -37, }, + { 151, -1257, 5177, 31240, -3262, 745, -37, }, + { 146, -1221, 5031, 31312, -3206, 734, -37, }, + { 141, -1186, 4885, 31383, -3149, 722, -37, }, + { 135, -1151, 4741, 31452, -3091, 709, -37, }, + { 130, -1116, 4597, 31520, -3032, 697, -37, }, + { 125, -1082, 4455, 31585, -2972, 684, -37, }, + { 121, -1047, 4313, 31649, -2910, 671, -36, }, + { 116, -1013, 4172, 31712, -2847, 657, -36, }, + { 111, -979, 4032, 31772, -2783, 643, -36, }, + { 106, -945, 3894, 31831, -2718, 629, -36, }, + { 102, -912, 3756, 31888, -2651, 614, -36, }, + { 97, -878, 3619, 31943, -2584, 600, -35, }, + { 93, -845, 3483, 31997, -2515, 584, -35, }, + { 89, -812, 3348, 32049, -2445, 569, -34, }, + { 84, -780, 3214, 32099, -2374, 553, -34, }, + { 80, -747, 3081, 32147, -2301, 537, -33, }, + { 76, -715, 2949, 32193, -2228, 520, -33, }, + { 72, -683, 2818, 32238, -2153, 503, -32, }, + { 68, -651, 2688, 32281, -2077, 486, -31, }, + { 65, -620, 2559, 32322, -2000, 469, -31, }, + { 61, -589, 2431, 32362, -1922, 451, -30, }, + { 57, -558, 2305, 32399, -1842, 433, -29, }, + { 54, -527, 2179, 32435, -1761, 414, -28, }, + { 50, -497, 2054, 32469, -1679, 395, -27, }, + { 47, -467, 1931, 32501, -1596, 376, -26, }, + { 43, -437, 1808, 32531, -1512, 357, -25, }, + { 40, -408, 1687, 32560, -1426, 337, -24, }, + { 37, -378, 1567, 32586, -1339, 317, -23, }, + { 34, -349, 1447, 32611, -1251, 296, -22, }, + { 31, -321, 1329, 32634, -1162, 275, -20, }, + { 28, -292, 1212, 32655, -1072, 254, -19, }, + { 25, -264, 1096, 32675, -980, 233, -18, }, + { 22, -236, 982, 32692, -888, 211, -16, }, + { 19, -209, 868, 32708, -794, 189, -15, }, + { 17, -182, 756, 32722, -699, 166, -13, }, + { 14, -155, 644, 32734, -602, 144, -11, }, + { 11, -128, 534, 32744, -505, 120, -10, }, + { 9, -102, 425, 32752, -406, 97, -8, }, + { 7, -76, 317, 32759, -306, 73, -6, }, + { 4, -50, 210, 32763, -205, 49, -4, }, + { 2, -25, 104, 32766, -103, 25, -2, }, + { 0, 0, 0, 32767, 0, 0, 0, }, + { -2, 25, -103, 32766, 104, -25, 2, }, + { -4, 49, -205, 32763, 210, -50, 4, }, + { -6, 73, -306, 32759, 317, -76, 7, }, + { -8, 97, -406, 32752, 425, -102, 9, }, + { -10, 120, -505, 32744, 534, -128, 11, }, + { -11, 144, -602, 32734, 644, -155, 14, }, + { -13, 166, -699, 32722, 756, -182, 17, }, + { -15, 189, -794, 32708, 868, -209, 19, }, + { -16, 211, -888, 32692, 982, -236, 22, }, + { -18, 233, -980, 32675, 1096, -264, 25, }, + { -19, 254, -1072, 32655, 1212, -292, 28, }, + { -20, 275, -1162, 32634, 1329, -321, 31, }, + { -22, 296, -1251, 32611, 1447, -349, 34, }, + { -23, 317, -1339, 32586, 1567, -378, 37, }, + { -24, 337, -1426, 32560, 1687, -408, 40, }, + { -25, 357, -1512, 32531, 1808, -437, 43, }, + { -26, 376, -1596, 32501, 1931, -467, 47, }, + { -27, 395, -1679, 32469, 2054, -497, 50, }, + { -28, 414, -1761, 32435, 2179, -527, 54, }, + { -29, 433, -1842, 32399, 2305, -558, 57, }, + { -30, 451, -1922, 32362, 2431, -589, 61, }, + { -31, 469, -2000, 32322, 2559, -620, 65, }, + { -31, 486, -2077, 32281, 2688, -651, 68, }, + { -32, 503, -2153, 32238, 2818, -683, 72, }, + { -33, 520, -2228, 32193, 2949, -715, 76, }, + { -33, 537, -2301, 32147, 3081, -747, 80, }, + { -34, 553, -2374, 32099, 3214, -780, 84, }, + { -34, 569, -2445, 32049, 3348, -812, 89, }, + { -35, 584, -2515, 31997, 3483, -845, 93, }, + { -35, 600, -2584, 31943, 3619, -878, 97, }, + { -36, 614, -2651, 31888, 3756, -912, 102, }, + { -36, 629, -2718, 31831, 3894, -945, 106, }, + { -36, 643, -2783, 31772, 4032, -979, 111, }, + { -36, 657, -2847, 31712, 4172, -1013, 116, }, + { -36, 671, -2910, 31649, 4313, -1047, 121, }, + { -37, 684, -2972, 31585, 4455, -1082, 125, }, + { -37, 697, -3032, 31520, 4597, -1116, 130, }, + { -37, 709, -3091, 31452, 4741, -1151, 135, }, + { -37, 722, -3149, 31383, 4885, -1186, 141, }, + { -37, 734, -3206, 31312, 5031, -1221, 146, }, + { -37, 745, -3262, 31240, 5177, -1257, 151, }, + { -37, 756, -3317, 31166, 5324, -1292, 156, }, + { -37, 767, -3370, 31090, 5472, -1328, 162, }, + { -36, 778, -3422, 31013, 5621, -1364, 167, }, + { -36, 788, -3474, 30933, 5771, -1400, 173, }, + { -36, 798, -3524, 30853, 5921, -1436, 178, }, + { -36, 808, -3572, 30770, 6073, -1472, 184, }, + { -36, 818, -3620, 30686, 6225, -1509, 190, }, + { -35, 827, -3667, 30601, 6378, -1546, 196, }, + { -35, 836, -3712, 30514, 6532, -1582, 202, }, + { -35, 844, -3756, 30425, 6686, -1619, 208, }, + { -34, 852, -3799, 30334, 6841, -1656, 214, }, + { -34, 860, -3841, 30243, 6998, -1693, 220, }, + { -33, 868, -3882, 30149, 7154, -1731, 226, }, + { -33, 875, -3922, 30054, 7312, -1768, 233, }, + { -33, 882, -3961, 29957, 7470, -1805, 239, }, + { -32, 889, -3998, 29859, 7629, -1843, 246, }, + { -32, 895, -4034, 29760, 7789, -1880, 252, }, + { -31, 901, -4070, 29659, 7949, -1918, 259, }, + { -31, 907, -4104, 29556, 8110, -1956, 265, }, + { -30, 913, -4137, 29452, 8272, -1994, 272, }, + { -30, 918, -4169, 29346, 8434, -2031, 279, }, + { -29, 923, -4200, 29239, 8597, -2069, 286, }, + { -28, 928, -4230, 29131, 8761, -2107, 293, }, + { -28, 932, -4259, 29021, 8925, -2145, 300, }, + { -27, 936, -4287, 28910, 9090, -2183, 307, }, + { -27, 940, -4313, 28797, 9255, -2221, 314, }, + { -26, 944, -4339, 28683, 9421, -2259, 321, }, + { -25, 947, -4364, 28567, 9588, -2297, 328, }, + { -25, 951, -4387, 28450, 9755, -2335, 335, }, + { -24, 953, -4410, 28332, 9922, -2373, 343, }, + { -24, 956, -4431, 28213, 10090, -2411, 350, }, + { -23, 958, -4452, 28092, 10259, -2449, 357, }, + { -22, 961, -4472, 27969, 10428, -2487, 365, }, + { -22, 962, -4490, 27846, 10597, -2525, 372, }, + { -21, 964, -4508, 27721, 10767, -2563, 380, }, + { -20, 965, -4524, 27595, 10937, -2601, 387, }, + { -20, 967, -4540, 27467, 11108, -2638, 395, }, + { -19, 967, -4554, 27339, 11279, -2676, 403, }, + { -18, 968, -4568, 27209, 11451, -2714, 410, }, + { -18, 969, -4581, 27078, 11623, -2751, 418, }, + { -17, 969, -4592, 26946, 11795, -2789, 426, }, + { -17, 969, -4603, 26812, 11968, -2826, 434, }, + { -16, 968, -4613, 26677, 12141, -2863, 442, }, + { -15, 968, -4622, 26542, 12314, -2900, 449, }, + { -15, 967, -4630, 26405, 12488, -2937, 457, }, + { -14, 966, -4637, 26267, 12662, -2974, 465, }, + { -14, 965, -4643, 26127, 12836, -3010, 473, }, + { -13, 964, -4649, 25987, 13010, -3047, 481, }, + { -12, 963, -4653, 25846, 13185, -3083, 489, }, + { -12, 961, -4657, 25703, 13359, -3119, 497, }, + { -11, 959, -4659, 25560, 13534, -3155, 505, }, + { -11, 957, -4661, 25415, 13710, -3191, 513, }, + { -10, 954, -4662, 25270, 13885, -3226, 521, }, + { -10, 952, -4662, 25123, 14061, -3262, 530, }, + { -9, 949, -4661, 24975, 14236, -3297, 538, }, + { -8, 946, -4660, 24827, 14412, -3332, 546, }, + { -8, 943, -4657, 24677, 14588, -3366, 554, }, + { -7, 940, -4654, 24527, 14764, -3401, 562, }, + { -7, 937, -4650, 24375, 14940, -3435, 570, }, + { -7, 933, -4645, 24223, 15116, -3469, 578, }, + { -6, 930, -4640, 24070, 15292, -3503, 586, }, + { -6, 926, -4634, 23916, 15468, -3536, 594, }, + { -5, 922, -4626, 23761, 15644, -3569, 602, }, + { -5, 918, -4619, 23605, 15820, -3602, 610, }, + { -4, 913, -4610, 23448, 15997, -3634, 618, }, + { -4, 909, -4601, 23291, 16173, -3666, 626, }, + { -4, 904, -4591, 23133, 16349, -3698, 634, }, + { -3, 899, -4580, 22974, 16524, -3730, 642, }, + { -3, 894, -4568, 22814, 16700, -3761, 650, }, + { -3, 889, -4556, 22653, 16876, -3791, 658, }, + { -2, 884, -4543, 22492, 17051, -3822, 666, }, + { -2, 879, -4530, 22330, 17227, -3852, 674, }, + { -2, 873, -4515, 22168, 17402, -3881, 682, }, + { -2, 868, -4500, 22004, 17577, -3911, 689, }, + { -1, 862, -4485, 21840, 17752, -3940, 697, }, + { -1, 856, -4469, 21676, 17926, -3968, 705, }, + { -1, 850, -4452, 21510, 18101, -3996, 712, }, + { -1, 844, -4434, 21344, 18275, -4023, 720, }, + { -1, 838, -4416, 21178, 18449, -4051, 728, }, + { 0, 832, -4397, 21011, 18622, -4077, 735, }, + { 0, 826, -4378, 20843, 18795, -4103, 742, }, + { 0, 819, -4358, 20675, 18968, -4129, 750, }, + { 0, 813, -4338, 20507, 19141, -4154, 757, }, + { 0, 806, -4317, 20337, 19313, -4179, 764, }, + { 0, 799, -4295, 20168, 19485, -4203, 771, }, + { 0, 792, -4273, 19998, 19656, -4227, 778, }, + { 0, 785, -4250, 19827, 19827, -4250, 785, }, +}; diff --git a/fmdriver/ppz8.c b/fmdriver/ppz8.c index d1afd72..1d06780 100644 --- a/fmdriver/ppz8.c +++ b/fmdriver/ppz8.c @@ -1,6 +1,7 @@ #include "ppz8.h" #include "fmdriver_common.h" #include <string.h> +#include "ppz8-sinctable.inc" unsigned ppz8_get_mask(const struct ppz8 *ppz8) { return ppz8->mask; @@ -32,51 +33,137 @@ void ppz8_init(struct ppz8 *ppz8, uint16_t srate, uint16_t mix_volume) { channel->freq = 0; channel->loopstartoff = -1; channel->loopendoff = -1; - channel->prevout[0] = 0; - channel->prevout[1] = 0; channel->vol = 8; channel->pan = 5; channel->voice = 0; + channel->looped = false; leveldata_init(&channel->leveldata); } ppz8->srate = srate; ppz8->totalvol = 12; ppz8->mix_volume = mix_volume; + ppz8->interp = PPZ8_INTERP_SINC; } static uint64_t ppz8_loop(const struct ppz8_channel *channel, uint64_t ptr) { if (channel->loopstartptr != (uint64_t)-1) { - if (channel->loopendptr != (uint64_t)-1) { - if (ptr >= channel->loopendptr) { - if (channel->loopendptr == channel->loopstartptr) return (uint64_t)-1; - uint32_t offset = (ptr - channel->loopendptr) >> 16; - offset %= (uint32_t)((channel->loopendptr - channel->loopstartptr) >> 16); - offset += (uint32_t)(channel->loopstartptr >> 16); - return (ptr & ((1<<16)-1)) | (((uint64_t)offset) << 16); - } - } else if (ptr >= channel->endptr) { - if (channel->endptr == channel->loopstartptr) return (uint64_t)-1; - uint32_t offset = (ptr - channel->endptr) >> 16; - offset %= (uint32_t)((channel->endptr - channel->loopstartptr) >> 16); + uint64_t loopendptr = (channel->loopendptr == (uint64_t)-1) ? + channel->endptr : channel->loopendptr; + if (ptr >= loopendptr) { + if (loopendptr == channel->loopstartptr) return (uint64_t)-1; + uint32_t offset = (ptr - loopendptr) >> 16; + offset %= (uint32_t)((loopendptr - channel->loopstartptr) >> 16); offset += (uint32_t)(channel->loopstartptr >> 16); return (ptr & ((1<<16)-1)) | (((uint64_t)offset) << 16); } } - if (ptr >= channel->endptr) { + uint64_t limit = channel->endptr; + if ((channel->loopstartptr != (uint64_t)-1) && + (channel->loopendptr != (uint64_t)-1) && + (channel->loopendptr > channel->endptr)) { + limit = channel->loopendptr; + } + if (ptr >= limit) { return (uint64_t)-1; } return ptr; } +static void ppz8_channel_get_centered_samples( + struct ppz8 *ppz8, + struct ppz8_channel *channel, + int16_t *obuf, int samples) { + struct ppz8_pcmbuf *buf = &ppz8->buf[channel->voice>>7]; + uint32_t currind = channel->ptr >> 16; + for (int i = 0; i < samples; i++) { + int indoff = i - (samples - 1)/2; + uint32_t ind = currind + indoff; + if (indoff < 0) { + if ((channel->loopstartptr != (uint64_t)-1) && channel->looped) { + uint32_t loopendind = ((channel->loopendptr == (uint64_t)-1) ? + channel->endptr : channel->loopendptr) >> 16; + uint32_t loopperiod = loopendind - (channel->loopstartptr >> 16); + if (!loopperiod) { + ind = -1; + } else { + uint32_t loopoffset = -(ind - ((uint32_t)(channel->loopstartptr >> 16)) - loopperiod); + loopoffset %= loopperiod; + if (!loopoffset) loopoffset = loopperiod; + ind = (channel->loopstartptr >> 16) + loopperiod - loopoffset; + } + } else { + if (((uint32_t)-indoff) > currind) { + ind = -1; + } + } + } else { + uint32_t loopendind = (channel->loopendptr == (uint64_t)-1) ? + channel->endptr : channel->loopendptr; + if ((channel->loopstartptr != (uint64_t)-1) && (ind >= loopendind)) { + uint32_t loopperiod = loopendind - (channel->loopstartptr >> 16); + if (!loopperiod) { + ind = -1; + } else { + uint32_t loopoffset = ind - (channel->loopstartptr >> 16); + loopoffset %= loopperiod; + ind = (channel->loopstartptr >> 16) + loopoffset; + } + } + } + if ((ind >= (channel->endptr >> 16)) || (ind >= buf->buflen) || !buf->data) { + obuf[i] = 0; + } else { + obuf[i] = buf->data[ind]; + } + } +} + +static int32_t ppz8_channel_calc_nearest_neighbor(struct ppz8 *ppz8, struct ppz8_channel *channel) { + int16_t sample; + ppz8_channel_get_centered_samples(ppz8, channel, &sample, 1); + return sample; +} + +static int32_t ppz8_channel_calc_linear(struct ppz8 *ppz8, struct ppz8_channel *channel) { + int32_t out = 0; + int16_t samples[2]; + ppz8_channel_get_centered_samples(ppz8, channel, samples, 2); + uint16_t coeff = channel->ptr & 0xffffu; + out += (int32_t)samples[0] * (0x10000u - coeff); + out += (int32_t)samples[1] * coeff; + out >>= 16; + return out; +} + +static int32_t ppz8_channel_calc_sinc(struct ppz8 *ppz8, struct ppz8_channel *channel) { + int16_t samples[7]; + uint8_t frac = channel->ptr >> 8; + ppz8_channel_get_centered_samples(ppz8, channel, samples, 7); + const int16_t *sinctable = ppz8_sinctable[frac]; + int32_t out = 0; + for (int i = 0; i < 7; i++) { + out += samples[i] * sinctable[i]; + } + out >>= 15; + return out; +} + static int32_t ppz8_channel_calc(struct ppz8 *ppz8, struct ppz8_channel *channel) { struct ppz8_pcmbuf *buf = &ppz8->buf[channel->voice>>7]; struct ppz8_pcmvoice *voice = &buf->voice[channel->voice & 0x7f]; int32_t out = 0; if (channel->vol) { - uint16_t coeff = channel->ptr & 0xffffu; - out += (int32_t)channel->prevout[0] * (0x10000u - coeff); - out += (int32_t)channel->prevout[1] * coeff; - out >>= 16; + switch (ppz8->interp) { + case PPZ8_INTERP_SINC: + out = ppz8_channel_calc_sinc(ppz8, channel); + break; + case PPZ8_INTERP_LINEAR: + out = ppz8_channel_calc_linear(ppz8, channel); + break; + default: + out = ppz8_channel_calc_nearest_neighbor(ppz8, channel); + break; + } // volume: out * 2**((volume-15)/2) out >>= (7 - ((channel->vol&0xf)>>1)); if (!(channel->vol&1)) { @@ -86,45 +173,10 @@ static int32_t ppz8_channel_calc(struct ppz8 *ppz8, struct ppz8_channel *channel } uint64_t ptrdiff = (((uint64_t)channel->freq * voice->origfreq) << 1) / ppz8->srate; - uint64_t oldptr = channel->ptr; - channel->ptr += ptrdiff; - uint32_t bufdiff = (channel->ptr>>16) - (oldptr>>16); - if (bufdiff) { - if (bufdiff == 1) { - channel->prevout[0] = channel->prevout[1]; - channel->prevout[1] = 0; - channel->ptr = ppz8_loop(channel, channel->ptr); - if (channel->ptr != (uint64_t)-1) { - uint32_t bufptr = channel->ptr >> 16; - if (buf->data && bufptr < buf->buflen) { - channel->prevout[1] = buf->data[bufptr]; - } - } else { - channel->playing = false; - } - } else { - channel->prevout[0] = 0; - channel->prevout[1] = 0; - uint64_t ptr1 = ppz8_loop(channel, channel->ptr - 0x10000); - if (ptr1 != (uint64_t)-1) { - uint32_t bufptr = ptr1 >> 16; - if (buf->data && bufptr < buf->buflen) { - channel->prevout[0] = buf->data[bufptr]; - } - channel->ptr = ppz8_loop(channel, channel->ptr); - if (channel->ptr != (uint64_t)-1) { - bufptr = channel->ptr >> 16; - if (buf->data && bufptr < buf->buflen) { - channel->prevout[1] = buf->data[bufptr]; - } - } else { - channel->playing = false; - } - } else { - channel->playing = false; - } - } - } + uint64_t newptr = channel->ptr + ptrdiff; + channel->ptr = ppz8_loop(channel, newptr); + if (newptr != channel->ptr) channel->looped = true; + if (channel->ptr == (uint64_t)-1) channel->playing = false; return out; } @@ -276,13 +328,8 @@ static void ppz8_channel_play(struct ppz8 *ppz8, uint8_t ch, uint8_t v) { : channel->ptr + (((uint64_t)(channel->loopstartoff))<<16); channel->loopendptr = (channel->loopendoff == (uint32_t)-1) ? (uint64_t)-1 : channel->ptr + (((uint64_t)(channel->loopendoff))<<16); - channel->prevout[0] = 0; - channel->prevout[1] = 0; channel->playing = true; - uint32_t bufptr = channel->ptr >> 16; - if (buf->data && bufptr < buf->buflen) { - channel->prevout[1] = buf->data[bufptr]; - } + channel->looped = false; } static void ppz8_channel_stop(struct ppz8 *ppz8, uint8_t ch) { diff --git a/fmdriver/ppz8.h b/fmdriver/ppz8.h index 35c67dc..f2134ce 100644 --- a/fmdriver/ppz8.h +++ b/fmdriver/ppz8.h @@ -10,6 +10,12 @@ extern "C" { #endif +enum ppz8_interp { + PPZ8_INTERP_NONE, + PPZ8_INTERP_LINEAR, + PPZ8_INTERP_SINC, +}; + struct ppz8_pcmvoice { uint32_t start; uint32_t len; @@ -32,11 +38,11 @@ struct ppz8_channel { uint32_t freq; uint32_t loopstartoff; uint32_t loopendoff; - int16_t prevout[2]; uint8_t vol; uint8_t pan; uint8_t voice; bool playing; + bool looped; struct leveldata leveldata; }; @@ -47,6 +53,7 @@ struct ppz8 { uint8_t totalvol; uint16_t mix_volume; unsigned mask; + enum ppz8_interp interp; }; void ppz8_init(struct ppz8 *ppz8, uint16_t srate, uint16_t mix_volume); @@ -70,6 +77,10 @@ static inline uint32_t ppz8_pzi_decodebuf_samples(uint32_t pzidatalen) { unsigned ppz8_get_mask(const struct ppz8 *ppz8); void ppz8_set_mask(struct ppz8 *ppz8, unsigned mask); +static inline void ppz8_set_interpolation(struct ppz8 *ppz8, enum ppz8_interp interp) { + ppz8->interp = interp; +} + struct ppz8_functbl { void (*channel_play)(struct ppz8 *ppz8, uint8_t channel, uint8_t voice); void (*channel_stop)(struct ppz8 *ppz8, uint8_t channel); |