| 1 | /* |
| 2 | * some code for sample mixing |
| 3 | * (C) notaz, 2006,2007 |
| 4 | * (C) irixxxx, 2019,2020 added filtering |
| 5 | * |
| 6 | * This work is licensed under the terms of MAME license. |
| 7 | * See COPYING file in the top-level directory. |
| 8 | */ |
| 9 | |
| 10 | #include <string.h> |
| 11 | #include "../pico_int.h" |
| 12 | |
| 13 | #define MAXOUT (+32767) |
| 14 | #define MINOUT (-32768) |
| 15 | |
| 16 | /* limitter */ |
| 17 | #define Limit16(val) \ |
| 18 | val -= val >> 3; /* reduce level to avoid clipping */ \ |
| 19 | if ((s16)val != val) val = (val < 0 ? MINOUT : MAXOUT) |
| 20 | |
| 21 | int mix_32_to_16_level; |
| 22 | |
| 23 | static struct iir { |
| 24 | int alpha; // alpha for EMA low pass |
| 25 | int y[2]; // filter intermediates |
| 26 | } lfi2, rfi2; |
| 27 | |
| 28 | // NB ">>" rounds to -infinity, "/" to 0. To compensate the effect possibly use |
| 29 | // "-(-y>>n)" (round to +infinity) instead of "y>>n" in places. |
| 30 | |
| 31 | // NB uses fixpoint; samples mustn't have more than (32-QB) bits. Adding the |
| 32 | // outputs of the sound sources together yields a max. of 18 bits, restricting |
| 33 | // QB to a maximum of 14. |
| 34 | #define QB 12 |
| 35 | // NB alpha for DC filtering shouldn't be smaller than 1/(1<<QB) to avoid loss. |
| 36 | |
| 37 | |
| 38 | // exponential moving average combined DC filter and lowpass filter |
| 39 | // y0[n] = (x[n]-y0[n-1])*alpha+y0[n-1], y1[n] = (y0[n] - y1[n-1])*(1-1/8192) |
| 40 | static inline int filter_band(struct iir *fi2, int x) |
| 41 | { |
| 42 | // low pass. alpha is Q8 to avoid loss by 32 bit overflow. |
| 43 | // fi2->y[0] += ((x<<(QB-8)) - (fi2->y[0]>>8)) * fi2->alpha; |
| 44 | fi2->y[0] += (x - (fi2->y[0]>>QB)) * fi2->alpha; |
| 45 | // DC filter. for alpha=1-1/8192 cutoff ~1HZ, for 1-1/1024 ~7Hz |
| 46 | fi2->y[1] += (fi2->y[0] - fi2->y[1]) >> QB; |
| 47 | return (fi2->y[0] - fi2->y[1]) >> QB; |
| 48 | } |
| 49 | |
| 50 | // exponential moving average filter for DC filtering |
| 51 | // y[n] = (x[n]-y[n-1])*(1-1/8192) (corner approx. 1Hz, gain 1) |
| 52 | static inline int filter_exp(struct iir *fi2, int x) |
| 53 | { |
| 54 | fi2->y[1] += ((x << QB) - fi2->y[1]) >> QB; |
| 55 | return x - (fi2->y[1] >> QB); |
| 56 | } |
| 57 | |
| 58 | // unfiltered (for testing) |
| 59 | static inline int filter_null(struct iir *fi2, int x) |
| 60 | { |
| 61 | return x; |
| 62 | } |
| 63 | |
| 64 | #define filter filter_band |
| 65 | |
| 66 | #define mix_32_to_16_stereo_core(dest, src, count, lv, fl) { \ |
| 67 | int l, r; \ |
| 68 | struct iir lf = lfi2, rf = rfi2; \ |
| 69 | \ |
| 70 | for (; count > 0; count--) \ |
| 71 | { \ |
| 72 | l = *dest; \ |
| 73 | l += *src++ >> lv; \ |
| 74 | l = fl(&lf, l); \ |
| 75 | Limit16(l); \ |
| 76 | *dest++ = l; \ |
| 77 | r = *dest; \ |
| 78 | r += *src++ >> lv; \ |
| 79 | r = fl(&rf, r); \ |
| 80 | Limit16(r); \ |
| 81 | *dest++ = r; \ |
| 82 | } \ |
| 83 | lfi2 = lf, rfi2 = rf; \ |
| 84 | } |
| 85 | |
| 86 | void mix_32_to_16_stereo_lvl(s16 *dest, s32 *src, int count) |
| 87 | { |
| 88 | mix_32_to_16_stereo_core(dest, src, count, mix_32_to_16_level, filter); |
| 89 | } |
| 90 | |
| 91 | void mix_32_to_16_stereo(s16 *dest, s32 *src, int count) |
| 92 | { |
| 93 | mix_32_to_16_stereo_core(dest, src, count, 0, filter); |
| 94 | } |
| 95 | |
| 96 | void mix_32_to_16_mono(s16 *dest, s32 *src, int count) |
| 97 | { |
| 98 | int l; |
| 99 | struct iir lf = lfi2; |
| 100 | |
| 101 | for (; count > 0; count--) |
| 102 | { |
| 103 | l = *dest; |
| 104 | l += *src++; |
| 105 | l = filter(&lf, l); |
| 106 | Limit16(l); |
| 107 | *dest++ = l; |
| 108 | } |
| 109 | lfi2 = lf; |
| 110 | } |
| 111 | |
| 112 | |
| 113 | void mix_16h_to_32(s32 *dest_buf, s16 *mp3_buf, int count) |
| 114 | { |
| 115 | while (count--) |
| 116 | { |
| 117 | *dest_buf++ += (*mp3_buf++ * 5) >> 3; |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | void mix_16h_to_32_s1(s32 *dest_buf, s16 *mp3_buf, int count) |
| 122 | { |
| 123 | count >>= 1; |
| 124 | while (count--) |
| 125 | { |
| 126 | *dest_buf++ += (*mp3_buf++ * 5) >> 3; |
| 127 | *dest_buf++ += (*mp3_buf++ * 5) >> 3; |
| 128 | mp3_buf += 1*2; |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | void mix_16h_to_32_s2(s32 *dest_buf, s16 *mp3_buf, int count) |
| 133 | { |
| 134 | count >>= 1; |
| 135 | while (count--) |
| 136 | { |
| 137 | *dest_buf++ += (*mp3_buf++ * 5) >> 3; |
| 138 | *dest_buf++ += (*mp3_buf++ * 5) >> 3; |
| 139 | mp3_buf += 3*2; |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | // mixes cdda audio @44.1 KHz into dest_buf, resampling with nearest neighbour |
| 144 | void mix_16h_to_32_resample_stereo(s32 *dest_buf, s16 *cdda_buf, int count, int fac16) |
| 145 | { |
| 146 | int pos16 = 0; |
| 147 | while (count--) { |
| 148 | int pos = 2 * (pos16>>16); |
| 149 | *dest_buf++ += (cdda_buf[pos ] * 5) >> 3; |
| 150 | *dest_buf++ += (cdda_buf[pos+1] * 5) >> 3; |
| 151 | pos16 += fac16; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | // mixes cdda audio @44.1 KHz into dest_buf, resampling with nearest neighbour |
| 156 | void mix_16h_to_32_resample_mono(s32 *dest_buf, s16 *cdda_buf, int count, int fac16) |
| 157 | { |
| 158 | int pos16 = 0; |
| 159 | while (count--) { |
| 160 | int pos = 2 * (pos16>>16); |
| 161 | *dest_buf += (cdda_buf[pos ] * 5) >> 4; |
| 162 | *dest_buf++ += (cdda_buf[pos+1] * 5) >> 4; |
| 163 | pos16 += fac16; |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | void mix_reset(int alpha_q16) |
| 168 | { |
| 169 | memset(&lfi2, 0, sizeof(lfi2)); |
| 170 | memset(&rfi2, 0, sizeof(rfi2)); |
| 171 | lfi2.alpha = rfi2.alpha = (0x10000-alpha_q16) >> 4; // filter alpha, Q12 |
| 172 | } |