xref: /openbmc/qemu/audio/mixeng.c (revision a28853871d6ef5ec4afe810a43fdde859dfdaa7e)
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  */
2587ecb68bSpbrook #include "qemu-common.h"
2687ecb68bSpbrook #include "audio.h"
2785571bc7Sbellard 
281d14ffa9Sbellard #define AUDIO_CAP "mixeng"
291d14ffa9Sbellard #include "audio_int.h"
301d14ffa9Sbellard 
311d14ffa9Sbellard /* 8 bit */
321d14ffa9Sbellard #define ENDIAN_CONVERSION natural
331d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
341d14ffa9Sbellard 
351d14ffa9Sbellard /* Signed 8 bit */
36*a2885387SRoger Pau Monne #define BSIZE 8
37*a2885387SRoger Pau Monne #define ITYPE int
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
46*a2885387SRoger Pau Monne #undef BSIZE
47*a2885387SRoger Pau Monne #undef ITYPE
481d14ffa9Sbellard #undef SHIFT
4985571bc7Sbellard 
501d14ffa9Sbellard /* Unsigned 8 bit */
51*a2885387SRoger Pau Monne #define BSIZE 8
52*a2885387SRoger Pau Monne #define ITYPE uint
5385571bc7Sbellard #define IN_MIN 0
5485571bc7Sbellard #define IN_MAX UCHAR_MAX
551d14ffa9Sbellard #define SHIFT 8
5685571bc7Sbellard #include "mixeng_template.h"
5785571bc7Sbellard #undef IN_MAX
5885571bc7Sbellard #undef IN_MIN
59*a2885387SRoger Pau Monne #undef BSIZE
60*a2885387SRoger Pau Monne #undef ITYPE
611d14ffa9Sbellard #undef SHIFT
6285571bc7Sbellard 
631d14ffa9Sbellard #undef ENDIAN_CONVERT
641d14ffa9Sbellard #undef ENDIAN_CONVERSION
651d14ffa9Sbellard 
661d14ffa9Sbellard /* Signed 16 bit */
67*a2885387SRoger Pau Monne #define BSIZE 16
68*a2885387SRoger Pau Monne #define ITYPE int
6985571bc7Sbellard #define IN_MIN SHRT_MIN
7085571bc7Sbellard #define IN_MAX SHRT_MAX
7185571bc7Sbellard #define SIGNED
721d14ffa9Sbellard #define SHIFT 16
731d14ffa9Sbellard #define ENDIAN_CONVERSION natural
741d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
7585571bc7Sbellard #include "mixeng_template.h"
761d14ffa9Sbellard #undef ENDIAN_CONVERT
771d14ffa9Sbellard #undef ENDIAN_CONVERSION
781d14ffa9Sbellard #define ENDIAN_CONVERSION swap
791d14ffa9Sbellard #define ENDIAN_CONVERT(v) bswap16 (v)
801d14ffa9Sbellard #include "mixeng_template.h"
811d14ffa9Sbellard #undef ENDIAN_CONVERT
821d14ffa9Sbellard #undef ENDIAN_CONVERSION
8385571bc7Sbellard #undef SIGNED
8485571bc7Sbellard #undef IN_MAX
8585571bc7Sbellard #undef IN_MIN
86*a2885387SRoger Pau Monne #undef BSIZE
87*a2885387SRoger Pau Monne #undef ITYPE
881d14ffa9Sbellard #undef SHIFT
8985571bc7Sbellard 
90f941aa25Sths /* Unsigned 16 bit */
91*a2885387SRoger Pau Monne #define BSIZE 16
92*a2885387SRoger Pau Monne #define ITYPE uint
9385571bc7Sbellard #define IN_MIN 0
9485571bc7Sbellard #define IN_MAX USHRT_MAX
951d14ffa9Sbellard #define SHIFT 16
961d14ffa9Sbellard #define ENDIAN_CONVERSION natural
971d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
9885571bc7Sbellard #include "mixeng_template.h"
991d14ffa9Sbellard #undef ENDIAN_CONVERT
1001d14ffa9Sbellard #undef ENDIAN_CONVERSION
1011d14ffa9Sbellard #define ENDIAN_CONVERSION swap
1021d14ffa9Sbellard #define ENDIAN_CONVERT(v) bswap16 (v)
1031d14ffa9Sbellard #include "mixeng_template.h"
1041d14ffa9Sbellard #undef ENDIAN_CONVERT
1051d14ffa9Sbellard #undef ENDIAN_CONVERSION
10685571bc7Sbellard #undef IN_MAX
10785571bc7Sbellard #undef IN_MIN
108*a2885387SRoger Pau Monne #undef BSIZE
109*a2885387SRoger Pau Monne #undef ITYPE
1101d14ffa9Sbellard #undef SHIFT
11185571bc7Sbellard 
112f941aa25Sths /* Signed 32 bit */
113*a2885387SRoger Pau Monne #define BSIZE 32
114*a2885387SRoger Pau Monne #define ITYPE int
115f941aa25Sths #define IN_MIN INT32_MIN
116f941aa25Sths #define IN_MAX INT32_MAX
117f941aa25Sths #define SIGNED
118f941aa25Sths #define SHIFT 32
119f941aa25Sths #define ENDIAN_CONVERSION natural
120f941aa25Sths #define ENDIAN_CONVERT(v) (v)
121f941aa25Sths #include "mixeng_template.h"
122f941aa25Sths #undef ENDIAN_CONVERT
123f941aa25Sths #undef ENDIAN_CONVERSION
124f941aa25Sths #define ENDIAN_CONVERSION swap
125f941aa25Sths #define ENDIAN_CONVERT(v) bswap32 (v)
126f941aa25Sths #include "mixeng_template.h"
127f941aa25Sths #undef ENDIAN_CONVERT
128f941aa25Sths #undef ENDIAN_CONVERSION
129f941aa25Sths #undef SIGNED
130f941aa25Sths #undef IN_MAX
131f941aa25Sths #undef IN_MIN
132*a2885387SRoger Pau Monne #undef BSIZE
133*a2885387SRoger Pau Monne #undef ITYPE
134f941aa25Sths #undef SHIFT
135f941aa25Sths 
136ad483a51Smalc /* Unsigned 32 bit */
137*a2885387SRoger Pau Monne #define BSIZE 32
138*a2885387SRoger Pau Monne #define ITYPE uint
139f941aa25Sths #define IN_MIN 0
140f941aa25Sths #define IN_MAX UINT32_MAX
141f941aa25Sths #define SHIFT 32
142f941aa25Sths #define ENDIAN_CONVERSION natural
143f941aa25Sths #define ENDIAN_CONVERT(v) (v)
144f941aa25Sths #include "mixeng_template.h"
145f941aa25Sths #undef ENDIAN_CONVERT
146f941aa25Sths #undef ENDIAN_CONVERSION
147f941aa25Sths #define ENDIAN_CONVERSION swap
148f941aa25Sths #define ENDIAN_CONVERT(v) bswap32 (v)
149f941aa25Sths #include "mixeng_template.h"
150f941aa25Sths #undef ENDIAN_CONVERT
151f941aa25Sths #undef ENDIAN_CONVERSION
152f941aa25Sths #undef IN_MAX
153f941aa25Sths #undef IN_MIN
154*a2885387SRoger Pau Monne #undef BSIZE
155*a2885387SRoger Pau Monne #undef ITYPE
156f941aa25Sths #undef SHIFT
157f941aa25Sths 
158f941aa25Sths t_sample *mixeng_conv[2][2][2][3] = {
15985571bc7Sbellard     {
16085571bc7Sbellard         {
1611d14ffa9Sbellard             {
1621d14ffa9Sbellard                 conv_natural_uint8_t_to_mono,
163f941aa25Sths                 conv_natural_uint16_t_to_mono,
164f941aa25Sths                 conv_natural_uint32_t_to_mono
16585571bc7Sbellard             },
16685571bc7Sbellard             {
1671d14ffa9Sbellard                 conv_natural_uint8_t_to_mono,
168f941aa25Sths                 conv_swap_uint16_t_to_mono,
169f941aa25Sths                 conv_swap_uint32_t_to_mono,
17085571bc7Sbellard             }
17185571bc7Sbellard         },
17285571bc7Sbellard         {
17385571bc7Sbellard             {
1741d14ffa9Sbellard                 conv_natural_int8_t_to_mono,
175f941aa25Sths                 conv_natural_int16_t_to_mono,
176f941aa25Sths                 conv_natural_int32_t_to_mono
17785571bc7Sbellard             },
17885571bc7Sbellard             {
1791d14ffa9Sbellard                 conv_natural_int8_t_to_mono,
180f941aa25Sths                 conv_swap_int16_t_to_mono,
181f941aa25Sths                 conv_swap_int32_t_to_mono
1821d14ffa9Sbellard             }
1831d14ffa9Sbellard         }
1841d14ffa9Sbellard     },
1851d14ffa9Sbellard     {
1861d14ffa9Sbellard         {
1871d14ffa9Sbellard             {
1881d14ffa9Sbellard                 conv_natural_uint8_t_to_stereo,
189f941aa25Sths                 conv_natural_uint16_t_to_stereo,
190f941aa25Sths                 conv_natural_uint32_t_to_stereo
1911d14ffa9Sbellard             },
1921d14ffa9Sbellard             {
1931d14ffa9Sbellard                 conv_natural_uint8_t_to_stereo,
194f941aa25Sths                 conv_swap_uint16_t_to_stereo,
195f941aa25Sths                 conv_swap_uint32_t_to_stereo
1961d14ffa9Sbellard             }
1971d14ffa9Sbellard         },
1981d14ffa9Sbellard         {
1991d14ffa9Sbellard             {
2001d14ffa9Sbellard                 conv_natural_int8_t_to_stereo,
201f941aa25Sths                 conv_natural_int16_t_to_stereo,
202f941aa25Sths                 conv_natural_int32_t_to_stereo
2031d14ffa9Sbellard             },
2041d14ffa9Sbellard             {
2051d14ffa9Sbellard                 conv_natural_int8_t_to_stereo,
206f941aa25Sths                 conv_swap_int16_t_to_stereo,
207f941aa25Sths                 conv_swap_int32_t_to_stereo,
2081d14ffa9Sbellard             }
20985571bc7Sbellard         }
21085571bc7Sbellard     }
21185571bc7Sbellard };
21285571bc7Sbellard 
213f941aa25Sths f_sample *mixeng_clip[2][2][2][3] = {
21485571bc7Sbellard     {
21585571bc7Sbellard         {
2161d14ffa9Sbellard             {
2171d14ffa9Sbellard                 clip_natural_uint8_t_from_mono,
218f941aa25Sths                 clip_natural_uint16_t_from_mono,
219f941aa25Sths                 clip_natural_uint32_t_from_mono
22085571bc7Sbellard             },
22185571bc7Sbellard             {
2221d14ffa9Sbellard                 clip_natural_uint8_t_from_mono,
223f941aa25Sths                 clip_swap_uint16_t_from_mono,
224f941aa25Sths                 clip_swap_uint32_t_from_mono
22585571bc7Sbellard             }
22685571bc7Sbellard         },
22785571bc7Sbellard         {
22885571bc7Sbellard             {
2291d14ffa9Sbellard                 clip_natural_int8_t_from_mono,
230f941aa25Sths                 clip_natural_int16_t_from_mono,
231f941aa25Sths                 clip_natural_int32_t_from_mono
23285571bc7Sbellard             },
23385571bc7Sbellard             {
2341d14ffa9Sbellard                 clip_natural_int8_t_from_mono,
235f941aa25Sths                 clip_swap_int16_t_from_mono,
236f941aa25Sths                 clip_swap_int32_t_from_mono
2371d14ffa9Sbellard             }
2381d14ffa9Sbellard         }
2391d14ffa9Sbellard     },
2401d14ffa9Sbellard     {
2411d14ffa9Sbellard         {
2421d14ffa9Sbellard             {
2431d14ffa9Sbellard                 clip_natural_uint8_t_from_stereo,
244f941aa25Sths                 clip_natural_uint16_t_from_stereo,
245f941aa25Sths                 clip_natural_uint32_t_from_stereo
2461d14ffa9Sbellard             },
2471d14ffa9Sbellard             {
2481d14ffa9Sbellard                 clip_natural_uint8_t_from_stereo,
249f941aa25Sths                 clip_swap_uint16_t_from_stereo,
250f941aa25Sths                 clip_swap_uint32_t_from_stereo
2511d14ffa9Sbellard             }
2521d14ffa9Sbellard         },
2531d14ffa9Sbellard         {
2541d14ffa9Sbellard             {
2551d14ffa9Sbellard                 clip_natural_int8_t_from_stereo,
256f941aa25Sths                 clip_natural_int16_t_from_stereo,
257f941aa25Sths                 clip_natural_int32_t_from_stereo
2581d14ffa9Sbellard             },
2591d14ffa9Sbellard             {
2601d14ffa9Sbellard                 clip_natural_int8_t_from_stereo,
261f941aa25Sths                 clip_swap_int16_t_from_stereo,
262f941aa25Sths                 clip_swap_int32_t_from_stereo
2631d14ffa9Sbellard             }
26485571bc7Sbellard         }
26585571bc7Sbellard     }
26685571bc7Sbellard };
26785571bc7Sbellard 
26885571bc7Sbellard /*
26985571bc7Sbellard  * August 21, 1998
27085571bc7Sbellard  * Copyright 1998 Fabrice Bellard.
27185571bc7Sbellard  *
27285571bc7Sbellard  * [Rewrote completly the code of Lance Norskog And Sundry
27385571bc7Sbellard  * Contributors with a more efficient algorithm.]
27485571bc7Sbellard  *
27585571bc7Sbellard  * This source code is freely redistributable and may be used for
27685571bc7Sbellard  * any purpose.  This copyright notice must be maintained.
27785571bc7Sbellard  * Lance Norskog And Sundry Contributors are not responsible for
27885571bc7Sbellard  * the consequences of using this software.
27985571bc7Sbellard  */
28085571bc7Sbellard 
28185571bc7Sbellard /*
28285571bc7Sbellard  * Sound Tools rate change effect file.
28385571bc7Sbellard  */
28485571bc7Sbellard /*
28585571bc7Sbellard  * Linear Interpolation.
28685571bc7Sbellard  *
28785571bc7Sbellard  * The use of fractional increment allows us to use no buffer. It
28885571bc7Sbellard  * avoid the problems at the end of the buffer we had with the old
28985571bc7Sbellard  * method which stored a possibly big buffer of size
29085571bc7Sbellard  * lcm(in_rate,out_rate).
29185571bc7Sbellard  *
29285571bc7Sbellard  * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
29385571bc7Sbellard  * the input & output frequencies are equal, a delay of one sample is
29485571bc7Sbellard  * introduced.  Limited to processing 32-bit count worth of samples.
29585571bc7Sbellard  *
29685571bc7Sbellard  * 1 << FRAC_BITS evaluating to zero in several places.  Changed with
29785571bc7Sbellard  * an (unsigned long) cast to make it safe.  MarkMLl 2/1/99
29885571bc7Sbellard  */
29985571bc7Sbellard 
30085571bc7Sbellard /* Private data */
301c0fe3827Sbellard struct rate {
30285571bc7Sbellard     uint64_t opos;
30385571bc7Sbellard     uint64_t opos_inc;
30485571bc7Sbellard     uint32_t ipos;              /* position in the input stream (integer) */
3051ea879e5Smalc     struct st_sample ilast;          /* last sample in the input stream */
306c0fe3827Sbellard };
30785571bc7Sbellard 
30885571bc7Sbellard /*
30985571bc7Sbellard  * Prepare processing.
31085571bc7Sbellard  */
31185571bc7Sbellard void *st_rate_start (int inrate, int outrate)
31285571bc7Sbellard {
313c0fe3827Sbellard     struct rate *rate = audio_calloc (AUDIO_FUNC, 1, sizeof (*rate));
31485571bc7Sbellard 
31585571bc7Sbellard     if (!rate) {
316e7cad338Sbellard         dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate));
3171d14ffa9Sbellard         return NULL;
31885571bc7Sbellard     }
31985571bc7Sbellard 
32085571bc7Sbellard     rate->opos = 0;
32185571bc7Sbellard 
32285571bc7Sbellard     /* increment */
3231d14ffa9Sbellard     rate->opos_inc = ((uint64_t) inrate << 32) / outrate;
32485571bc7Sbellard 
32585571bc7Sbellard     rate->ipos = 0;
32685571bc7Sbellard     rate->ilast.l = 0;
32785571bc7Sbellard     rate->ilast.r = 0;
32885571bc7Sbellard     return rate;
32985571bc7Sbellard }
33085571bc7Sbellard 
3311d14ffa9Sbellard #define NAME st_rate_flow_mix
3321d14ffa9Sbellard #define OP(a, b) a += b
3331d14ffa9Sbellard #include "rate_template.h"
33485571bc7Sbellard 
3351d14ffa9Sbellard #define NAME st_rate_flow
3361d14ffa9Sbellard #define OP(a, b) a = b
3371d14ffa9Sbellard #include "rate_template.h"
33885571bc7Sbellard 
33985571bc7Sbellard void st_rate_stop (void *opaque)
34085571bc7Sbellard {
3417267c094SAnthony Liguori     g_free (opaque);
34285571bc7Sbellard }
3431d14ffa9Sbellard 
3441ea879e5Smalc void mixeng_clear (struct st_sample *buf, int len)
3451d14ffa9Sbellard {
3461ea879e5Smalc     memset (buf, 0, len * sizeof (struct st_sample));
3471d14ffa9Sbellard }
34800e07679SMichael Walle 
34900e07679SMichael Walle void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol)
35000e07679SMichael Walle {
35100e07679SMichael Walle #ifdef CONFIG_MIXEMU
35200e07679SMichael Walle     if (vol->mute) {
35300e07679SMichael Walle         mixeng_clear (buf, len);
35400e07679SMichael Walle         return;
35500e07679SMichael Walle     }
35600e07679SMichael Walle 
35700e07679SMichael Walle     while (len--) {
35800e07679SMichael Walle #ifdef FLOAT_MIXENG
35900e07679SMichael Walle         buf->l = buf->l * vol->l;
36000e07679SMichael Walle         buf->r = buf->r * vol->r;
36100e07679SMichael Walle #else
36200e07679SMichael Walle         buf->l = (buf->l * vol->l) >> 32;
36300e07679SMichael Walle         buf->r = (buf->r * vol->r) >> 32;
36400e07679SMichael Walle #endif
36500e07679SMichael Walle         buf += 1;
36600e07679SMichael Walle     }
36700e07679SMichael Walle #else
36800e07679SMichael Walle     (void) buf;
36900e07679SMichael Walle     (void) len;
37000e07679SMichael Walle     (void) vol;
37100e07679SMichael Walle #endif
37200e07679SMichael Walle }
373