cff531af |
1 | /* |
2 | * some code for sample mixing |
3 | * (C) notaz, 2006,2007 |
7bf552b5 |
4 | * (C) irixxxx, 2019,2020 added filtering |
cff531af |
5 | * |
6 | * This work is licensed under the terms of MAME license. |
7 | * See COPYING file in the top-level directory. |
8 | */ |
8b99ab90 |
9 | |
f821bb70 |
10 | #include <string.h> |
f7741cac |
11 | #include "../pico_int.h" |
2a942f0d |
12 | |
4f265db7 |
13 | #define MAXOUT (+32767) |
14 | #define MINOUT (-32768) |
15 | |
16 | /* limitter */ |
8ac9ab7f |
17 | #define Limit16(val) \ |
a5a230e0 |
18 | val -= val >> 3; /* reduce level to avoid clipping */ \ |
f7741cac |
19 | if ((s16)val != val) val = (val < 0 ? MINOUT : MAXOUT) |
4f265db7 |
20 | |
70efc52d |
21 | int mix_32_to_16_level; |
4f265db7 |
22 | |
30969671 |
23 | static struct iir { |
24 | int alpha; // alpha for EMA low pass |
2a942f0d |
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 | |
30969671 |
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. |
2a942f0d |
34 | #define QB 12 |
30969671 |
35 | // NB alpha for DC filtering shouldn't be smaller than 1/(1<<QB) to avoid loss. |
2a942f0d |
36 | |
37 | |
30969671 |
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 | |
2a942f0d |
50 | // exponential moving average filter for DC filtering |
30969671 |
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) |
4f265db7 |
53 | { |
30969671 |
54 | fi2->y[1] += ((x << QB) - fi2->y[1]) >> QB; |
55 | return x - (fi2->y[1] >> QB); |
2a942f0d |
56 | } |
4f265db7 |
57 | |
2a942f0d |
58 | // unfiltered (for testing) |
30969671 |
59 | static inline int filter_null(struct iir *fi2, int x) |
2a942f0d |
60 | { |
61 | return x; |
62 | } |
63 | |
30969671 |
64 | #define filter filter_band |
65 | |
70efc52d |
66 | #define mix_32_to_16_stereo_core(dest, src, count, lv, fl) { \ |
2a942f0d |
67 | int l, r; \ |
30969671 |
68 | struct iir lf = lfi2, rf = rfi2; \ |
2a942f0d |
69 | \ |
70 | for (; count > 0; count--) \ |
71 | { \ |
70efc52d |
72 | l = *dest; \ |
2a942f0d |
73 | l += *src++ >> lv; \ |
30969671 |
74 | l = fl(&lf, l); \ |
2a942f0d |
75 | Limit16(l); \ |
2a942f0d |
76 | *dest++ = l; \ |
70efc52d |
77 | r = *dest; \ |
78 | r += *src++ >> lv; \ |
79 | r = fl(&rf, r); \ |
80 | Limit16(r); \ |
2a942f0d |
81 | *dest++ = r; \ |
82 | } \ |
30969671 |
83 | lfi2 = lf, rfi2 = rf; \ |
4f265db7 |
84 | } |
85 | |
70efc52d |
86 | void mix_32_to_16_stereo_lvl(s16 *dest, s32 *src, int count) |
f5939109 |
87 | { |
70efc52d |
88 | mix_32_to_16_stereo_core(dest, src, count, mix_32_to_16_level, filter); |
f5939109 |
89 | } |
90 | |
70efc52d |
91 | void mix_32_to_16_stereo(s16 *dest, s32 *src, int count) |
f5939109 |
92 | { |
70efc52d |
93 | mix_32_to_16_stereo_core(dest, src, count, 0, filter); |
f5939109 |
94 | } |
4f265db7 |
95 | |
f7741cac |
96 | void mix_32_to_16_mono(s16 *dest, s32 *src, int count) |
4f265db7 |
97 | { |
98 | int l; |
30969671 |
99 | struct iir lf = lfi2; |
4f265db7 |
100 | |
101 | for (; count > 0; count--) |
102 | { |
103 | l = *dest; |
104 | l += *src++; |
30969671 |
105 | l = filter(&lf, l); |
2a942f0d |
106 | Limit16(l); |
4f265db7 |
107 | *dest++ = l; |
108 | } |
30969671 |
109 | lfi2 = lf; |
4f265db7 |
110 | } |
111 | |
112 | |
f7741cac |
113 | void mix_16h_to_32(s32 *dest_buf, s16 *mp3_buf, int count) |
cea65903 |
114 | { |
4b167c12 |
115 | while (count--) |
116 | { |
2eeee072 |
117 | *dest_buf++ += (*mp3_buf++ * 5) >> 3; |
4b167c12 |
118 | } |
cea65903 |
119 | } |
120 | |
f7741cac |
121 | void mix_16h_to_32_s1(s32 *dest_buf, s16 *mp3_buf, int count) |
cea65903 |
122 | { |
4b167c12 |
123 | count >>= 1; |
124 | while (count--) |
125 | { |
2eeee072 |
126 | *dest_buf++ += (*mp3_buf++ * 5) >> 3; |
127 | *dest_buf++ += (*mp3_buf++ * 5) >> 3; |
4b167c12 |
128 | mp3_buf += 1*2; |
129 | } |
cea65903 |
130 | } |
131 | |
f7741cac |
132 | void mix_16h_to_32_s2(s32 *dest_buf, s16 *mp3_buf, int count) |
cea65903 |
133 | { |
4b167c12 |
134 | count >>= 1; |
135 | while (count--) |
136 | { |
2eeee072 |
137 | *dest_buf++ += (*mp3_buf++ * 5) >> 3; |
138 | *dest_buf++ += (*mp3_buf++ * 5) >> 3; |
4b167c12 |
139 | mp3_buf += 3*2; |
140 | } |
cea65903 |
141 | } |
142 | |
f7741cac |
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); |
2eeee072 |
149 | *dest_buf++ += (cdda_buf[pos ] * 5) >> 3; |
150 | *dest_buf++ += (cdda_buf[pos+1] * 5) >> 3; |
f7741cac |
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); |
2eeee072 |
161 | *dest_buf += (cdda_buf[pos ] * 5) >> 4; |
162 | *dest_buf++ += (cdda_buf[pos+1] * 5) >> 4; |
f7741cac |
163 | pos16 += fac16; |
164 | } |
165 | } |
166 | |
30969671 |
167 | void mix_reset(int alpha_q16) |
2a942f0d |
168 | { |
169 | memset(&lfi2, 0, sizeof(lfi2)); |
170 | memset(&rfi2, 0, sizeof(rfi2)); |
30969671 |
171 | lfi2.alpha = rfi2.alpha = (0x10000-alpha_q16) >> 4; // filter alpha, Q12 |
2a942f0d |
172 | } |