1a4785d13b96ef0977f10699b754f1e13a0da274
[picodrive.git] / pico / sound / mix.c
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 }