xref: /openbmc/qemu/audio/mixeng.c (revision f941aa256f2254c3f35f00fcf5d7f20dba55a5b7)
185571bc7Sbellard /*
285571bc7Sbellard  * QEMU Mixing engine
385571bc7Sbellard  *
41d14ffa9Sbellard  * Copyright (c) 2004-2005 Vassili Karpov (malc)
585571bc7Sbellard  * Copyright (c) 1998 Fabrice Bellard
685571bc7Sbellard  *
785571bc7Sbellard  * Permission is hereby granted, free of charge, to any person obtaining a copy
885571bc7Sbellard  * of this software and associated documentation files (the "Software"), to deal
985571bc7Sbellard  * in the Software without restriction, including without limitation the rights
1085571bc7Sbellard  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1185571bc7Sbellard  * copies of the Software, and to permit persons to whom the Software is
1285571bc7Sbellard  * furnished to do so, subject to the following conditions:
1385571bc7Sbellard  *
1485571bc7Sbellard  * The above copyright notice and this permission notice shall be included in
1585571bc7Sbellard  * all copies or substantial portions of the Software.
1685571bc7Sbellard  *
1785571bc7Sbellard  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1885571bc7Sbellard  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1985571bc7Sbellard  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2085571bc7Sbellard  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2185571bc7Sbellard  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2285571bc7Sbellard  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2385571bc7Sbellard  * THE SOFTWARE.
2485571bc7Sbellard  */
2585571bc7Sbellard #include "vl.h"
2685571bc7Sbellard 
271d14ffa9Sbellard #define AUDIO_CAP "mixeng"
281d14ffa9Sbellard #include "audio_int.h"
291d14ffa9Sbellard 
301d14ffa9Sbellard #define NOVOL
311d14ffa9Sbellard 
321d14ffa9Sbellard /* 8 bit */
331d14ffa9Sbellard #define ENDIAN_CONVERSION natural
341d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
351d14ffa9Sbellard 
361d14ffa9Sbellard /* Signed 8 bit */
3785571bc7Sbellard #define IN_T int8_t
381d14ffa9Sbellard #define IN_MIN SCHAR_MIN
391d14ffa9Sbellard #define IN_MAX SCHAR_MAX
4085571bc7Sbellard #define SIGNED
411d14ffa9Sbellard #define SHIFT 8
4285571bc7Sbellard #include "mixeng_template.h"
4385571bc7Sbellard #undef SIGNED
4485571bc7Sbellard #undef IN_MAX
4585571bc7Sbellard #undef IN_MIN
4685571bc7Sbellard #undef IN_T
471d14ffa9Sbellard #undef SHIFT
4885571bc7Sbellard 
491d14ffa9Sbellard /* Unsigned 8 bit */
5085571bc7Sbellard #define IN_T uint8_t
5185571bc7Sbellard #define IN_MIN 0
5285571bc7Sbellard #define IN_MAX UCHAR_MAX
531d14ffa9Sbellard #define SHIFT 8
5485571bc7Sbellard #include "mixeng_template.h"
5585571bc7Sbellard #undef IN_MAX
5685571bc7Sbellard #undef IN_MIN
5785571bc7Sbellard #undef IN_T
581d14ffa9Sbellard #undef SHIFT
5985571bc7Sbellard 
601d14ffa9Sbellard #undef ENDIAN_CONVERT
611d14ffa9Sbellard #undef ENDIAN_CONVERSION
621d14ffa9Sbellard 
631d14ffa9Sbellard /* Signed 16 bit */
6485571bc7Sbellard #define IN_T int16_t
6585571bc7Sbellard #define IN_MIN SHRT_MIN
6685571bc7Sbellard #define IN_MAX SHRT_MAX
6785571bc7Sbellard #define SIGNED
681d14ffa9Sbellard #define SHIFT 16
691d14ffa9Sbellard #define ENDIAN_CONVERSION natural
701d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
7185571bc7Sbellard #include "mixeng_template.h"
721d14ffa9Sbellard #undef ENDIAN_CONVERT
731d14ffa9Sbellard #undef ENDIAN_CONVERSION
741d14ffa9Sbellard #define ENDIAN_CONVERSION swap
751d14ffa9Sbellard #define ENDIAN_CONVERT(v) bswap16 (v)
761d14ffa9Sbellard #include "mixeng_template.h"
771d14ffa9Sbellard #undef ENDIAN_CONVERT
781d14ffa9Sbellard #undef ENDIAN_CONVERSION
7985571bc7Sbellard #undef SIGNED
8085571bc7Sbellard #undef IN_MAX
8185571bc7Sbellard #undef IN_MIN
8285571bc7Sbellard #undef IN_T
831d14ffa9Sbellard #undef SHIFT
8485571bc7Sbellard 
85*f941aa25Sths /* Unsigned 16 bit */
8685571bc7Sbellard #define IN_T uint16_t
8785571bc7Sbellard #define IN_MIN 0
8885571bc7Sbellard #define IN_MAX USHRT_MAX
891d14ffa9Sbellard #define SHIFT 16
901d14ffa9Sbellard #define ENDIAN_CONVERSION natural
911d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
9285571bc7Sbellard #include "mixeng_template.h"
931d14ffa9Sbellard #undef ENDIAN_CONVERT
941d14ffa9Sbellard #undef ENDIAN_CONVERSION
951d14ffa9Sbellard #define ENDIAN_CONVERSION swap
961d14ffa9Sbellard #define ENDIAN_CONVERT(v) bswap16 (v)
971d14ffa9Sbellard #include "mixeng_template.h"
981d14ffa9Sbellard #undef ENDIAN_CONVERT
991d14ffa9Sbellard #undef ENDIAN_CONVERSION
10085571bc7Sbellard #undef IN_MAX
10185571bc7Sbellard #undef IN_MIN
10285571bc7Sbellard #undef IN_T
1031d14ffa9Sbellard #undef SHIFT
10485571bc7Sbellard 
105*f941aa25Sths /* Signed 32 bit */
106*f941aa25Sths #define IN_T int32_t
107*f941aa25Sths #define IN_MIN INT32_MIN
108*f941aa25Sths #define IN_MAX INT32_MAX
109*f941aa25Sths #define SIGNED
110*f941aa25Sths #define SHIFT 32
111*f941aa25Sths #define ENDIAN_CONVERSION natural
112*f941aa25Sths #define ENDIAN_CONVERT(v) (v)
113*f941aa25Sths #include "mixeng_template.h"
114*f941aa25Sths #undef ENDIAN_CONVERT
115*f941aa25Sths #undef ENDIAN_CONVERSION
116*f941aa25Sths #define ENDIAN_CONVERSION swap
117*f941aa25Sths #define ENDIAN_CONVERT(v) bswap32 (v)
118*f941aa25Sths #include "mixeng_template.h"
119*f941aa25Sths #undef ENDIAN_CONVERT
120*f941aa25Sths #undef ENDIAN_CONVERSION
121*f941aa25Sths #undef SIGNED
122*f941aa25Sths #undef IN_MAX
123*f941aa25Sths #undef IN_MIN
124*f941aa25Sths #undef IN_T
125*f941aa25Sths #undef SHIFT
126*f941aa25Sths 
127*f941aa25Sths /* Unsigned 16 bit */
128*f941aa25Sths #define IN_T uint32_t
129*f941aa25Sths #define IN_MIN 0
130*f941aa25Sths #define IN_MAX UINT32_MAX
131*f941aa25Sths #define SHIFT 32
132*f941aa25Sths #define ENDIAN_CONVERSION natural
133*f941aa25Sths #define ENDIAN_CONVERT(v) (v)
134*f941aa25Sths #include "mixeng_template.h"
135*f941aa25Sths #undef ENDIAN_CONVERT
136*f941aa25Sths #undef ENDIAN_CONVERSION
137*f941aa25Sths #define ENDIAN_CONVERSION swap
138*f941aa25Sths #define ENDIAN_CONVERT(v) bswap32 (v)
139*f941aa25Sths #include "mixeng_template.h"
140*f941aa25Sths #undef ENDIAN_CONVERT
141*f941aa25Sths #undef ENDIAN_CONVERSION
142*f941aa25Sths #undef IN_MAX
143*f941aa25Sths #undef IN_MIN
144*f941aa25Sths #undef IN_T
145*f941aa25Sths #undef SHIFT
146*f941aa25Sths 
147*f941aa25Sths t_sample *mixeng_conv[2][2][2][3] = {
14885571bc7Sbellard     {
14985571bc7Sbellard         {
1501d14ffa9Sbellard             {
1511d14ffa9Sbellard                 conv_natural_uint8_t_to_mono,
152*f941aa25Sths                 conv_natural_uint16_t_to_mono,
153*f941aa25Sths                 conv_natural_uint32_t_to_mono
15485571bc7Sbellard             },
15585571bc7Sbellard             {
1561d14ffa9Sbellard                 conv_natural_uint8_t_to_mono,
157*f941aa25Sths                 conv_swap_uint16_t_to_mono,
158*f941aa25Sths                 conv_swap_uint32_t_to_mono,
15985571bc7Sbellard             }
16085571bc7Sbellard         },
16185571bc7Sbellard         {
16285571bc7Sbellard             {
1631d14ffa9Sbellard                 conv_natural_int8_t_to_mono,
164*f941aa25Sths                 conv_natural_int16_t_to_mono,
165*f941aa25Sths                 conv_natural_int32_t_to_mono
16685571bc7Sbellard             },
16785571bc7Sbellard             {
1681d14ffa9Sbellard                 conv_natural_int8_t_to_mono,
169*f941aa25Sths                 conv_swap_int16_t_to_mono,
170*f941aa25Sths                 conv_swap_int32_t_to_mono
1711d14ffa9Sbellard             }
1721d14ffa9Sbellard         }
1731d14ffa9Sbellard     },
1741d14ffa9Sbellard     {
1751d14ffa9Sbellard         {
1761d14ffa9Sbellard             {
1771d14ffa9Sbellard                 conv_natural_uint8_t_to_stereo,
178*f941aa25Sths                 conv_natural_uint16_t_to_stereo,
179*f941aa25Sths                 conv_natural_uint32_t_to_stereo
1801d14ffa9Sbellard             },
1811d14ffa9Sbellard             {
1821d14ffa9Sbellard                 conv_natural_uint8_t_to_stereo,
183*f941aa25Sths                 conv_swap_uint16_t_to_stereo,
184*f941aa25Sths                 conv_swap_uint32_t_to_stereo
1851d14ffa9Sbellard             }
1861d14ffa9Sbellard         },
1871d14ffa9Sbellard         {
1881d14ffa9Sbellard             {
1891d14ffa9Sbellard                 conv_natural_int8_t_to_stereo,
190*f941aa25Sths                 conv_natural_int16_t_to_stereo,
191*f941aa25Sths                 conv_natural_int32_t_to_stereo
1921d14ffa9Sbellard             },
1931d14ffa9Sbellard             {
1941d14ffa9Sbellard                 conv_natural_int8_t_to_stereo,
195*f941aa25Sths                 conv_swap_int16_t_to_stereo,
196*f941aa25Sths                 conv_swap_int32_t_to_stereo,
1971d14ffa9Sbellard             }
19885571bc7Sbellard         }
19985571bc7Sbellard     }
20085571bc7Sbellard };
20185571bc7Sbellard 
202*f941aa25Sths f_sample *mixeng_clip[2][2][2][3] = {
20385571bc7Sbellard     {
20485571bc7Sbellard         {
2051d14ffa9Sbellard             {
2061d14ffa9Sbellard                 clip_natural_uint8_t_from_mono,
207*f941aa25Sths                 clip_natural_uint16_t_from_mono,
208*f941aa25Sths                 clip_natural_uint32_t_from_mono
20985571bc7Sbellard             },
21085571bc7Sbellard             {
2111d14ffa9Sbellard                 clip_natural_uint8_t_from_mono,
212*f941aa25Sths                 clip_swap_uint16_t_from_mono,
213*f941aa25Sths                 clip_swap_uint32_t_from_mono
21485571bc7Sbellard             }
21585571bc7Sbellard         },
21685571bc7Sbellard         {
21785571bc7Sbellard             {
2181d14ffa9Sbellard                 clip_natural_int8_t_from_mono,
219*f941aa25Sths                 clip_natural_int16_t_from_mono,
220*f941aa25Sths                 clip_natural_int32_t_from_mono
22185571bc7Sbellard             },
22285571bc7Sbellard             {
2231d14ffa9Sbellard                 clip_natural_int8_t_from_mono,
224*f941aa25Sths                 clip_swap_int16_t_from_mono,
225*f941aa25Sths                 clip_swap_int32_t_from_mono
2261d14ffa9Sbellard             }
2271d14ffa9Sbellard         }
2281d14ffa9Sbellard     },
2291d14ffa9Sbellard     {
2301d14ffa9Sbellard         {
2311d14ffa9Sbellard             {
2321d14ffa9Sbellard                 clip_natural_uint8_t_from_stereo,
233*f941aa25Sths                 clip_natural_uint16_t_from_stereo,
234*f941aa25Sths                 clip_natural_uint32_t_from_stereo
2351d14ffa9Sbellard             },
2361d14ffa9Sbellard             {
2371d14ffa9Sbellard                 clip_natural_uint8_t_from_stereo,
238*f941aa25Sths                 clip_swap_uint16_t_from_stereo,
239*f941aa25Sths                 clip_swap_uint32_t_from_stereo
2401d14ffa9Sbellard             }
2411d14ffa9Sbellard         },
2421d14ffa9Sbellard         {
2431d14ffa9Sbellard             {
2441d14ffa9Sbellard                 clip_natural_int8_t_from_stereo,
245*f941aa25Sths                 clip_natural_int16_t_from_stereo,
246*f941aa25Sths                 clip_natural_int32_t_from_stereo
2471d14ffa9Sbellard             },
2481d14ffa9Sbellard             {
2491d14ffa9Sbellard                 clip_natural_int8_t_from_stereo,
250*f941aa25Sths                 clip_swap_int16_t_from_stereo,
251*f941aa25Sths                 clip_swap_int32_t_from_stereo
2521d14ffa9Sbellard             }
25385571bc7Sbellard         }
25485571bc7Sbellard     }
25585571bc7Sbellard };
25685571bc7Sbellard 
25785571bc7Sbellard /*
25885571bc7Sbellard  * August 21, 1998
25985571bc7Sbellard  * Copyright 1998 Fabrice Bellard.
26085571bc7Sbellard  *
26185571bc7Sbellard  * [Rewrote completly the code of Lance Norskog And Sundry
26285571bc7Sbellard  * Contributors with a more efficient algorithm.]
26385571bc7Sbellard  *
26485571bc7Sbellard  * This source code is freely redistributable and may be used for
26585571bc7Sbellard  * any purpose.  This copyright notice must be maintained.
26685571bc7Sbellard  * Lance Norskog And Sundry Contributors are not responsible for
26785571bc7Sbellard  * the consequences of using this software.
26885571bc7Sbellard  */
26985571bc7Sbellard 
27085571bc7Sbellard /*
27185571bc7Sbellard  * Sound Tools rate change effect file.
27285571bc7Sbellard  */
27385571bc7Sbellard /*
27485571bc7Sbellard  * Linear Interpolation.
27585571bc7Sbellard  *
27685571bc7Sbellard  * The use of fractional increment allows us to use no buffer. It
27785571bc7Sbellard  * avoid the problems at the end of the buffer we had with the old
27885571bc7Sbellard  * method which stored a possibly big buffer of size
27985571bc7Sbellard  * lcm(in_rate,out_rate).
28085571bc7Sbellard  *
28185571bc7Sbellard  * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
28285571bc7Sbellard  * the input & output frequencies are equal, a delay of one sample is
28385571bc7Sbellard  * introduced.  Limited to processing 32-bit count worth of samples.
28485571bc7Sbellard  *
28585571bc7Sbellard  * 1 << FRAC_BITS evaluating to zero in several places.  Changed with
28685571bc7Sbellard  * an (unsigned long) cast to make it safe.  MarkMLl 2/1/99
28785571bc7Sbellard  */
28885571bc7Sbellard 
28985571bc7Sbellard /* Private data */
290c0fe3827Sbellard struct rate {
29185571bc7Sbellard     uint64_t opos;
29285571bc7Sbellard     uint64_t opos_inc;
29385571bc7Sbellard     uint32_t ipos;              /* position in the input stream (integer) */
29485571bc7Sbellard     st_sample_t ilast;          /* last sample in the input stream */
295c0fe3827Sbellard };
29685571bc7Sbellard 
29785571bc7Sbellard /*
29885571bc7Sbellard  * Prepare processing.
29985571bc7Sbellard  */
30085571bc7Sbellard void *st_rate_start (int inrate, int outrate)
30185571bc7Sbellard {
302c0fe3827Sbellard     struct rate *rate = audio_calloc (AUDIO_FUNC, 1, sizeof (*rate));
30385571bc7Sbellard 
30485571bc7Sbellard     if (!rate) {
305e7cad338Sbellard         dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate));
3061d14ffa9Sbellard         return NULL;
30785571bc7Sbellard     }
30885571bc7Sbellard 
30985571bc7Sbellard     rate->opos = 0;
31085571bc7Sbellard 
31185571bc7Sbellard     /* increment */
3121d14ffa9Sbellard     rate->opos_inc = ((uint64_t) inrate << 32) / outrate;
31385571bc7Sbellard 
31485571bc7Sbellard     rate->ipos = 0;
31585571bc7Sbellard     rate->ilast.l = 0;
31685571bc7Sbellard     rate->ilast.r = 0;
31785571bc7Sbellard     return rate;
31885571bc7Sbellard }
31985571bc7Sbellard 
3201d14ffa9Sbellard #define NAME st_rate_flow_mix
3211d14ffa9Sbellard #define OP(a, b) a += b
3221d14ffa9Sbellard #include "rate_template.h"
32385571bc7Sbellard 
3241d14ffa9Sbellard #define NAME st_rate_flow
3251d14ffa9Sbellard #define OP(a, b) a = b
3261d14ffa9Sbellard #include "rate_template.h"
32785571bc7Sbellard 
32885571bc7Sbellard void st_rate_stop (void *opaque)
32985571bc7Sbellard {
33085571bc7Sbellard     qemu_free (opaque);
33185571bc7Sbellard }
3321d14ffa9Sbellard 
3331d14ffa9Sbellard void mixeng_clear (st_sample_t *buf, int len)
3341d14ffa9Sbellard {
3351d14ffa9Sbellard     memset (buf, 0, len * sizeof (st_sample_t));
3361d14ffa9Sbellard }
337