platform ps2, handle audio similar to psp
[picodrive.git] / pico / sound / mix.c
... / ...
CommitLineData
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
21int mix_32_to_16_level;
22
23static 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)
40static 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)
52static 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)
59static 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
86void 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
91void 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
96void 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
113void 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
121void 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
132void 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
144void 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
156void 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
167void 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}