aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakamichi Horikawa <takamichiho@gmail.com>2017-08-23 21:13:48 +0900
committerTakamichi Horikawa <takamichiho@gmail.com>2017-08-23 21:13:48 +0900
commitdfb3f4f10cc66a72027ae5869318cc10baf30a2e (patch)
tree596dfb3e1177478accaf89e9f94e0be3c10e3c5a
parentf8a9839f5c133adbba53e5a3415f3b932bb81067 (diff)
PPZ8: add sinc interpolation
-rw-r--r--fmdriver/ppz8-sinctable.inc264
-rw-r--r--fmdriver/ppz8.c175
-rw-r--r--fmdriver/ppz8.h13
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);