Revision 1d14ffa9 audio/mixeng.c
b/audio/mixeng.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* QEMU Mixing engine |
3 | 3 |
* |
4 |
* Copyright (c) 2004 Vassili Karpov (malc) |
|
4 |
* Copyright (c) 2004-2005 Vassili Karpov (malc)
|
|
5 | 5 |
* Copyright (c) 1998 Fabrice Bellard |
6 | 6 |
* |
7 | 7 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
... | ... | |
23 | 23 |
* THE SOFTWARE. |
24 | 24 |
*/ |
25 | 25 |
#include "vl.h" |
26 |
//#define DEBUG_FP |
|
27 |
#include "audio/mixeng.h" |
|
28 | 26 |
|
27 |
#define AUDIO_CAP "mixeng" |
|
28 |
#include "audio_int.h" |
|
29 |
|
|
30 |
#define NOVOL |
|
31 |
|
|
32 |
/* 8 bit */ |
|
33 |
#define ENDIAN_CONVERSION natural |
|
34 |
#define ENDIAN_CONVERT(v) (v) |
|
35 |
|
|
36 |
/* Signed 8 bit */ |
|
29 | 37 |
#define IN_T int8_t |
30 |
#define IN_MIN CHAR_MIN |
|
31 |
#define IN_MAX CHAR_MAX |
|
38 |
#define IN_MIN SCHAR_MIN
|
|
39 |
#define IN_MAX SCHAR_MAX
|
|
32 | 40 |
#define SIGNED |
41 |
#define SHIFT 8 |
|
33 | 42 |
#include "mixeng_template.h" |
34 | 43 |
#undef SIGNED |
35 | 44 |
#undef IN_MAX |
36 | 45 |
#undef IN_MIN |
37 | 46 |
#undef IN_T |
47 |
#undef SHIFT |
|
38 | 48 |
|
49 |
/* Unsigned 8 bit */ |
|
39 | 50 |
#define IN_T uint8_t |
40 | 51 |
#define IN_MIN 0 |
41 | 52 |
#define IN_MAX UCHAR_MAX |
53 |
#define SHIFT 8 |
|
42 | 54 |
#include "mixeng_template.h" |
43 | 55 |
#undef IN_MAX |
44 | 56 |
#undef IN_MIN |
45 | 57 |
#undef IN_T |
58 |
#undef SHIFT |
|
59 |
|
|
60 |
#undef ENDIAN_CONVERT |
|
61 |
#undef ENDIAN_CONVERSION |
|
46 | 62 |
|
63 |
/* Signed 16 bit */ |
|
47 | 64 |
#define IN_T int16_t |
48 | 65 |
#define IN_MIN SHRT_MIN |
49 | 66 |
#define IN_MAX SHRT_MAX |
50 | 67 |
#define SIGNED |
68 |
#define SHIFT 16 |
|
69 |
#define ENDIAN_CONVERSION natural |
|
70 |
#define ENDIAN_CONVERT(v) (v) |
|
51 | 71 |
#include "mixeng_template.h" |
72 |
#undef ENDIAN_CONVERT |
|
73 |
#undef ENDIAN_CONVERSION |
|
74 |
#define ENDIAN_CONVERSION swap |
|
75 |
#define ENDIAN_CONVERT(v) bswap16 (v) |
|
76 |
#include "mixeng_template.h" |
|
77 |
#undef ENDIAN_CONVERT |
|
78 |
#undef ENDIAN_CONVERSION |
|
52 | 79 |
#undef SIGNED |
53 | 80 |
#undef IN_MAX |
54 | 81 |
#undef IN_MIN |
55 | 82 |
#undef IN_T |
83 |
#undef SHIFT |
|
56 | 84 |
|
57 | 85 |
#define IN_T uint16_t |
58 | 86 |
#define IN_MIN 0 |
59 | 87 |
#define IN_MAX USHRT_MAX |
88 |
#define SHIFT 16 |
|
89 |
#define ENDIAN_CONVERSION natural |
|
90 |
#define ENDIAN_CONVERT(v) (v) |
|
91 |
#include "mixeng_template.h" |
|
92 |
#undef ENDIAN_CONVERT |
|
93 |
#undef ENDIAN_CONVERSION |
|
94 |
#define ENDIAN_CONVERSION swap |
|
95 |
#define ENDIAN_CONVERT(v) bswap16 (v) |
|
60 | 96 |
#include "mixeng_template.h" |
97 |
#undef ENDIAN_CONVERT |
|
98 |
#undef ENDIAN_CONVERSION |
|
61 | 99 |
#undef IN_MAX |
62 | 100 |
#undef IN_MIN |
63 | 101 |
#undef IN_T |
102 |
#undef SHIFT |
|
64 | 103 |
|
65 |
t_sample *mixeng_conv[2][2][2] = { |
|
104 |
t_sample *mixeng_conv[2][2][2][2] = {
|
|
66 | 105 |
{ |
67 | 106 |
{ |
68 |
conv_uint8_t_to_mono, |
|
69 |
conv_uint16_t_to_mono |
|
107 |
{ |
|
108 |
conv_natural_uint8_t_to_mono, |
|
109 |
conv_natural_uint16_t_to_mono |
|
110 |
}, |
|
111 |
{ |
|
112 |
conv_natural_uint8_t_to_mono, |
|
113 |
conv_swap_uint16_t_to_mono |
|
114 |
} |
|
70 | 115 |
}, |
71 | 116 |
{ |
72 |
conv_int8_t_to_mono, |
|
73 |
conv_int16_t_to_mono |
|
117 |
{ |
|
118 |
conv_natural_int8_t_to_mono, |
|
119 |
conv_natural_int16_t_to_mono |
|
120 |
}, |
|
121 |
{ |
|
122 |
conv_natural_int8_t_to_mono, |
|
123 |
conv_swap_int16_t_to_mono |
|
124 |
} |
|
74 | 125 |
} |
75 | 126 |
}, |
76 | 127 |
{ |
77 | 128 |
{ |
78 |
conv_uint8_t_to_stereo, |
|
79 |
conv_uint16_t_to_stereo |
|
129 |
{ |
|
130 |
conv_natural_uint8_t_to_stereo, |
|
131 |
conv_natural_uint16_t_to_stereo |
|
132 |
}, |
|
133 |
{ |
|
134 |
conv_natural_uint8_t_to_stereo, |
|
135 |
conv_swap_uint16_t_to_stereo |
|
136 |
} |
|
80 | 137 |
}, |
81 | 138 |
{ |
82 |
conv_int8_t_to_stereo, |
|
83 |
conv_int16_t_to_stereo |
|
139 |
{ |
|
140 |
conv_natural_int8_t_to_stereo, |
|
141 |
conv_natural_int16_t_to_stereo |
|
142 |
}, |
|
143 |
{ |
|
144 |
conv_natural_int8_t_to_stereo, |
|
145 |
conv_swap_int16_t_to_stereo |
|
146 |
} |
|
84 | 147 |
} |
85 | 148 |
} |
86 | 149 |
}; |
87 | 150 |
|
88 |
f_sample *mixeng_clip[2][2][2] = { |
|
151 |
f_sample *mixeng_clip[2][2][2][2] = {
|
|
89 | 152 |
{ |
90 | 153 |
{ |
91 |
clip_uint8_t_from_mono, |
|
92 |
clip_uint16_t_from_mono |
|
154 |
{ |
|
155 |
clip_natural_uint8_t_from_mono, |
|
156 |
clip_natural_uint16_t_from_mono |
|
157 |
}, |
|
158 |
{ |
|
159 |
clip_natural_uint8_t_from_mono, |
|
160 |
clip_swap_uint16_t_from_mono |
|
161 |
} |
|
93 | 162 |
}, |
94 | 163 |
{ |
95 |
clip_int8_t_from_mono, |
|
96 |
clip_int16_t_from_mono |
|
164 |
{ |
|
165 |
clip_natural_int8_t_from_mono, |
|
166 |
clip_natural_int16_t_from_mono |
|
167 |
}, |
|
168 |
{ |
|
169 |
clip_natural_int8_t_from_mono, |
|
170 |
clip_swap_int16_t_from_mono |
|
171 |
} |
|
97 | 172 |
} |
98 | 173 |
}, |
99 | 174 |
{ |
100 | 175 |
{ |
101 |
clip_uint8_t_from_stereo, |
|
102 |
clip_uint16_t_from_stereo |
|
176 |
{ |
|
177 |
clip_natural_uint8_t_from_stereo, |
|
178 |
clip_natural_uint16_t_from_stereo |
|
179 |
}, |
|
180 |
{ |
|
181 |
clip_natural_uint8_t_from_stereo, |
|
182 |
clip_swap_uint16_t_from_stereo |
|
183 |
} |
|
103 | 184 |
}, |
104 | 185 |
{ |
105 |
clip_int8_t_from_stereo, |
|
106 |
clip_int16_t_from_stereo |
|
186 |
{ |
|
187 |
clip_natural_int8_t_from_stereo, |
|
188 |
clip_natural_int16_t_from_stereo |
|
189 |
}, |
|
190 |
{ |
|
191 |
clip_natural_int8_t_from_stereo, |
|
192 |
clip_swap_int16_t_from_stereo |
|
193 |
} |
|
107 | 194 |
} |
108 | 195 |
} |
109 | 196 |
}; |
... | ... | |
116 | 203 |
* Contributors with a more efficient algorithm.] |
117 | 204 |
* |
118 | 205 |
* This source code is freely redistributable and may be used for |
119 |
* any purpose. This copyright notice must be maintained.
|
|
120 |
* Lance Norskog And Sundry Contributors are not responsible for
|
|
121 |
* the consequences of using this software.
|
|
206 |
* any purpose. This copyright notice must be maintained. |
|
207 |
* Lance Norskog And Sundry Contributors are not responsible for |
|
208 |
* the consequences of using this software. |
|
122 | 209 |
*/ |
123 | 210 |
|
124 | 211 |
/* |
... | ... | |
156 | 243 |
rate_t rate = (rate_t) qemu_mallocz (sizeof (struct ratestuff)); |
157 | 244 |
|
158 | 245 |
if (!rate) { |
159 |
exit (EXIT_FAILURE); |
|
160 |
} |
|
161 |
|
|
162 |
if (inrate == outrate) { |
|
163 |
// exit (EXIT_FAILURE); |
|
164 |
} |
|
165 |
|
|
166 |
if (inrate >= 65535 || outrate >= 65535) { |
|
167 |
// exit (EXIT_FAILURE); |
|
246 |
return NULL; |
|
168 | 247 |
} |
169 | 248 |
|
170 | 249 |
rate->opos = 0; |
171 | 250 |
|
172 | 251 |
/* increment */ |
173 |
rate->opos_inc = (inrate * ((int64_t) UINT_MAX)) / outrate;
|
|
252 |
rate->opos_inc = ((uint64_t) inrate << 32) / outrate;
|
|
174 | 253 |
|
175 | 254 |
rate->ipos = 0; |
176 | 255 |
rate->ilast.l = 0; |
... | ... | |
178 | 257 |
return rate; |
179 | 258 |
} |
180 | 259 |
|
181 |
/* |
|
182 |
* Processed signed long samples from ibuf to obuf. |
|
183 |
* Return number of samples processed. |
|
184 |
*/ |
|
185 |
void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf, |
|
186 |
int *isamp, int *osamp) |
|
187 |
{ |
|
188 |
rate_t rate = (rate_t) opaque; |
|
189 |
st_sample_t *istart, *iend; |
|
190 |
st_sample_t *ostart, *oend; |
|
191 |
st_sample_t ilast, icur, out; |
|
192 |
int64_t t; |
|
193 |
|
|
194 |
ilast = rate->ilast; |
|
195 |
|
|
196 |
istart = ibuf; |
|
197 |
iend = ibuf + *isamp; |
|
260 |
#define NAME st_rate_flow_mix |
|
261 |
#define OP(a, b) a += b |
|
262 |
#include "rate_template.h" |
|
198 | 263 |
|
199 |
ostart = obuf; |
|
200 |
oend = obuf + *osamp; |
|
201 |
|
|
202 |
if (rate->opos_inc == 1ULL << 32) { |
|
203 |
int i, n = *isamp > *osamp ? *osamp : *isamp; |
|
204 |
for (i = 0; i < n; i++) { |
|
205 |
obuf[i].l += ibuf[i].r; |
|
206 |
obuf[i].r += ibuf[i].r; |
|
207 |
} |
|
208 |
*isamp = n; |
|
209 |
*osamp = n; |
|
210 |
return; |
|
211 |
} |
|
212 |
|
|
213 |
while (obuf < oend) { |
|
214 |
|
|
215 |
/* Safety catch to make sure we have input samples. */ |
|
216 |
if (ibuf >= iend) |
|
217 |
break; |
|
218 |
|
|
219 |
/* read as many input samples so that ipos > opos */ |
|
220 |
|
|
221 |
while (rate->ipos <= (rate->opos >> 32)) { |
|
222 |
ilast = *ibuf++; |
|
223 |
rate->ipos++; |
|
224 |
/* See if we finished the input buffer yet */ |
|
225 |
if (ibuf >= iend) goto the_end; |
|
226 |
} |
|
227 |
|
|
228 |
icur = *ibuf; |
|
229 |
|
|
230 |
/* interpolate */ |
|
231 |
t = rate->opos & 0xffffffff; |
|
232 |
out.l = (ilast.l * (INT_MAX - t) + icur.l * t) / INT_MAX; |
|
233 |
out.r = (ilast.r * (INT_MAX - t) + icur.r * t) / INT_MAX; |
|
234 |
|
|
235 |
/* output sample & increment position */ |
|
236 |
#if 0 |
|
237 |
*obuf++ = out; |
|
238 |
#else |
|
239 |
obuf->l += out.l; |
|
240 |
obuf->r += out.r; |
|
241 |
obuf += 1; |
|
242 |
#endif |
|
243 |
rate->opos += rate->opos_inc; |
|
244 |
} |
|
245 |
|
|
246 |
the_end: |
|
247 |
*isamp = ibuf - istart; |
|
248 |
*osamp = obuf - ostart; |
|
249 |
rate->ilast = ilast; |
|
250 |
} |
|
264 |
#define NAME st_rate_flow |
|
265 |
#define OP(a, b) a = b |
|
266 |
#include "rate_template.h" |
|
251 | 267 |
|
252 | 268 |
void st_rate_stop (void *opaque) |
253 | 269 |
{ |
254 | 270 |
qemu_free (opaque); |
255 | 271 |
} |
272 |
|
|
273 |
void mixeng_clear (st_sample_t *buf, int len) |
|
274 |
{ |
|
275 |
memset (buf, 0, len * sizeof (st_sample_t)); |
|
276 |
} |
Also available in: Unified diff