diff options
Diffstat (limited to 'fmdriver')
| -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); | 
