xref: /openbmc/qemu/audio/mixeng.c (revision 11938d78)
1 /*
2  * QEMU Mixing engine
3  *
4  * Copyright (c) 2004-2005 Vassili Karpov (malc)
5  * Copyright (c) 1998 Fabrice Bellard
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 #include "qemu-common.h"
26 #include "audio.h"
27 
28 #define AUDIO_CAP "mixeng"
29 #include "audio_int.h"
30 
31 /* 8 bit */
32 #define ENDIAN_CONVERSION natural
33 #define ENDIAN_CONVERT(v) (v)
34 
35 /* Signed 8 bit */
36 #define BSIZE 8
37 #define ITYPE int
38 #define IN_MIN SCHAR_MIN
39 #define IN_MAX SCHAR_MAX
40 #define SIGNED
41 #define SHIFT 8
42 #include "mixeng_template.h"
43 #undef SIGNED
44 #undef IN_MAX
45 #undef IN_MIN
46 #undef BSIZE
47 #undef ITYPE
48 #undef SHIFT
49 
50 /* Unsigned 8 bit */
51 #define BSIZE 8
52 #define ITYPE uint
53 #define IN_MIN 0
54 #define IN_MAX UCHAR_MAX
55 #define SHIFT 8
56 #include "mixeng_template.h"
57 #undef IN_MAX
58 #undef IN_MIN
59 #undef BSIZE
60 #undef ITYPE
61 #undef SHIFT
62 
63 #undef ENDIAN_CONVERT
64 #undef ENDIAN_CONVERSION
65 
66 /* Signed 16 bit */
67 #define BSIZE 16
68 #define ITYPE int
69 #define IN_MIN SHRT_MIN
70 #define IN_MAX SHRT_MAX
71 #define SIGNED
72 #define SHIFT 16
73 #define ENDIAN_CONVERSION natural
74 #define ENDIAN_CONVERT(v) (v)
75 #include "mixeng_template.h"
76 #undef ENDIAN_CONVERT
77 #undef ENDIAN_CONVERSION
78 #define ENDIAN_CONVERSION swap
79 #define ENDIAN_CONVERT(v) bswap16 (v)
80 #include "mixeng_template.h"
81 #undef ENDIAN_CONVERT
82 #undef ENDIAN_CONVERSION
83 #undef SIGNED
84 #undef IN_MAX
85 #undef IN_MIN
86 #undef BSIZE
87 #undef ITYPE
88 #undef SHIFT
89 
90 /* Unsigned 16 bit */
91 #define BSIZE 16
92 #define ITYPE uint
93 #define IN_MIN 0
94 #define IN_MAX USHRT_MAX
95 #define SHIFT 16
96 #define ENDIAN_CONVERSION natural
97 #define ENDIAN_CONVERT(v) (v)
98 #include "mixeng_template.h"
99 #undef ENDIAN_CONVERT
100 #undef ENDIAN_CONVERSION
101 #define ENDIAN_CONVERSION swap
102 #define ENDIAN_CONVERT(v) bswap16 (v)
103 #include "mixeng_template.h"
104 #undef ENDIAN_CONVERT
105 #undef ENDIAN_CONVERSION
106 #undef IN_MAX
107 #undef IN_MIN
108 #undef BSIZE
109 #undef ITYPE
110 #undef SHIFT
111 
112 /* Signed 32 bit */
113 #define BSIZE 32
114 #define ITYPE int
115 #define IN_MIN INT32_MIN
116 #define IN_MAX INT32_MAX
117 #define SIGNED
118 #define SHIFT 32
119 #define ENDIAN_CONVERSION natural
120 #define ENDIAN_CONVERT(v) (v)
121 #include "mixeng_template.h"
122 #undef ENDIAN_CONVERT
123 #undef ENDIAN_CONVERSION
124 #define ENDIAN_CONVERSION swap
125 #define ENDIAN_CONVERT(v) bswap32 (v)
126 #include "mixeng_template.h"
127 #undef ENDIAN_CONVERT
128 #undef ENDIAN_CONVERSION
129 #undef SIGNED
130 #undef IN_MAX
131 #undef IN_MIN
132 #undef BSIZE
133 #undef ITYPE
134 #undef SHIFT
135 
136 /* Unsigned 32 bit */
137 #define BSIZE 32
138 #define ITYPE uint
139 #define IN_MIN 0
140 #define IN_MAX UINT32_MAX
141 #define SHIFT 32
142 #define ENDIAN_CONVERSION natural
143 #define ENDIAN_CONVERT(v) (v)
144 #include "mixeng_template.h"
145 #undef ENDIAN_CONVERT
146 #undef ENDIAN_CONVERSION
147 #define ENDIAN_CONVERSION swap
148 #define ENDIAN_CONVERT(v) bswap32 (v)
149 #include "mixeng_template.h"
150 #undef ENDIAN_CONVERT
151 #undef ENDIAN_CONVERSION
152 #undef IN_MAX
153 #undef IN_MIN
154 #undef BSIZE
155 #undef ITYPE
156 #undef SHIFT
157 
158 t_sample *mixeng_conv[2][2][2][3] = {
159     {
160         {
161             {
162                 conv_natural_uint8_t_to_mono,
163                 conv_natural_uint16_t_to_mono,
164                 conv_natural_uint32_t_to_mono
165             },
166             {
167                 conv_natural_uint8_t_to_mono,
168                 conv_swap_uint16_t_to_mono,
169                 conv_swap_uint32_t_to_mono,
170             }
171         },
172         {
173             {
174                 conv_natural_int8_t_to_mono,
175                 conv_natural_int16_t_to_mono,
176                 conv_natural_int32_t_to_mono
177             },
178             {
179                 conv_natural_int8_t_to_mono,
180                 conv_swap_int16_t_to_mono,
181                 conv_swap_int32_t_to_mono
182             }
183         }
184     },
185     {
186         {
187             {
188                 conv_natural_uint8_t_to_stereo,
189                 conv_natural_uint16_t_to_stereo,
190                 conv_natural_uint32_t_to_stereo
191             },
192             {
193                 conv_natural_uint8_t_to_stereo,
194                 conv_swap_uint16_t_to_stereo,
195                 conv_swap_uint32_t_to_stereo
196             }
197         },
198         {
199             {
200                 conv_natural_int8_t_to_stereo,
201                 conv_natural_int16_t_to_stereo,
202                 conv_natural_int32_t_to_stereo
203             },
204             {
205                 conv_natural_int8_t_to_stereo,
206                 conv_swap_int16_t_to_stereo,
207                 conv_swap_int32_t_to_stereo,
208             }
209         }
210     }
211 };
212 
213 f_sample *mixeng_clip[2][2][2][3] = {
214     {
215         {
216             {
217                 clip_natural_uint8_t_from_mono,
218                 clip_natural_uint16_t_from_mono,
219                 clip_natural_uint32_t_from_mono
220             },
221             {
222                 clip_natural_uint8_t_from_mono,
223                 clip_swap_uint16_t_from_mono,
224                 clip_swap_uint32_t_from_mono
225             }
226         },
227         {
228             {
229                 clip_natural_int8_t_from_mono,
230                 clip_natural_int16_t_from_mono,
231                 clip_natural_int32_t_from_mono
232             },
233             {
234                 clip_natural_int8_t_from_mono,
235                 clip_swap_int16_t_from_mono,
236                 clip_swap_int32_t_from_mono
237             }
238         }
239     },
240     {
241         {
242             {
243                 clip_natural_uint8_t_from_stereo,
244                 clip_natural_uint16_t_from_stereo,
245                 clip_natural_uint32_t_from_stereo
246             },
247             {
248                 clip_natural_uint8_t_from_stereo,
249                 clip_swap_uint16_t_from_stereo,
250                 clip_swap_uint32_t_from_stereo
251             }
252         },
253         {
254             {
255                 clip_natural_int8_t_from_stereo,
256                 clip_natural_int16_t_from_stereo,
257                 clip_natural_int32_t_from_stereo
258             },
259             {
260                 clip_natural_int8_t_from_stereo,
261                 clip_swap_int16_t_from_stereo,
262                 clip_swap_int32_t_from_stereo
263             }
264         }
265     }
266 };
267 
268 /*
269  * August 21, 1998
270  * Copyright 1998 Fabrice Bellard.
271  *
272  * [Rewrote completly the code of Lance Norskog And Sundry
273  * Contributors with a more efficient algorithm.]
274  *
275  * This source code is freely redistributable and may be used for
276  * any purpose.  This copyright notice must be maintained.
277  * Lance Norskog And Sundry Contributors are not responsible for
278  * the consequences of using this software.
279  */
280 
281 /*
282  * Sound Tools rate change effect file.
283  */
284 /*
285  * Linear Interpolation.
286  *
287  * The use of fractional increment allows us to use no buffer. It
288  * avoid the problems at the end of the buffer we had with the old
289  * method which stored a possibly big buffer of size
290  * lcm(in_rate,out_rate).
291  *
292  * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
293  * the input & output frequencies are equal, a delay of one sample is
294  * introduced.  Limited to processing 32-bit count worth of samples.
295  *
296  * 1 << FRAC_BITS evaluating to zero in several places.  Changed with
297  * an (unsigned long) cast to make it safe.  MarkMLl 2/1/99
298  */
299 
300 /* Private data */
301 struct rate {
302     uint64_t opos;
303     uint64_t opos_inc;
304     uint32_t ipos;              /* position in the input stream (integer) */
305     struct st_sample ilast;          /* last sample in the input stream */
306 };
307 
308 /*
309  * Prepare processing.
310  */
311 void *st_rate_start (int inrate, int outrate)
312 {
313     struct rate *rate = audio_calloc (AUDIO_FUNC, 1, sizeof (*rate));
314 
315     if (!rate) {
316         dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate));
317         return NULL;
318     }
319 
320     rate->opos = 0;
321 
322     /* increment */
323     rate->opos_inc = ((uint64_t) inrate << 32) / outrate;
324 
325     rate->ipos = 0;
326     rate->ilast.l = 0;
327     rate->ilast.r = 0;
328     return rate;
329 }
330 
331 #define NAME st_rate_flow_mix
332 #define OP(a, b) a += b
333 #include "rate_template.h"
334 
335 #define NAME st_rate_flow
336 #define OP(a, b) a = b
337 #include "rate_template.h"
338 
339 void st_rate_stop (void *opaque)
340 {
341     g_free (opaque);
342 }
343 
344 void mixeng_clear (struct st_sample *buf, int len)
345 {
346     memset (buf, 0, len * sizeof (struct st_sample));
347 }
348 
349 void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol)
350 {
351     if (vol->mute) {
352         mixeng_clear (buf, len);
353         return;
354     }
355 
356     while (len--) {
357 #ifdef FLOAT_MIXENG
358         buf->l = buf->l * vol->l;
359         buf->r = buf->r * vol->r;
360 #else
361         buf->l = (buf->l * vol->l) >> 32;
362         buf->r = (buf->r * vol->r) >> 32;
363 #endif
364         buf += 1;
365     }
366 }
367