xref: /openbmc/qemu/audio/mixeng.c (revision 1d14ffa97eacd3cb722271eaf6f093038396eac4)
185571bc7Sbellard /*
285571bc7Sbellard  * QEMU Mixing engine
385571bc7Sbellard  *
4*1d14ffa9Sbellard  * 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 
27*1d14ffa9Sbellard #define AUDIO_CAP "mixeng"
28*1d14ffa9Sbellard #include "audio_int.h"
29*1d14ffa9Sbellard 
30*1d14ffa9Sbellard #define NOVOL
31*1d14ffa9Sbellard 
32*1d14ffa9Sbellard /* 8 bit */
33*1d14ffa9Sbellard #define ENDIAN_CONVERSION natural
34*1d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
35*1d14ffa9Sbellard 
36*1d14ffa9Sbellard /* Signed 8 bit */
3785571bc7Sbellard #define IN_T int8_t
38*1d14ffa9Sbellard #define IN_MIN SCHAR_MIN
39*1d14ffa9Sbellard #define IN_MAX SCHAR_MAX
4085571bc7Sbellard #define SIGNED
41*1d14ffa9Sbellard #define SHIFT 8
4285571bc7Sbellard #include "mixeng_template.h"
4385571bc7Sbellard #undef SIGNED
4485571bc7Sbellard #undef IN_MAX
4585571bc7Sbellard #undef IN_MIN
4685571bc7Sbellard #undef IN_T
47*1d14ffa9Sbellard #undef SHIFT
4885571bc7Sbellard 
49*1d14ffa9Sbellard /* Unsigned 8 bit */
5085571bc7Sbellard #define IN_T uint8_t
5185571bc7Sbellard #define IN_MIN 0
5285571bc7Sbellard #define IN_MAX UCHAR_MAX
53*1d14ffa9Sbellard #define SHIFT 8
5485571bc7Sbellard #include "mixeng_template.h"
5585571bc7Sbellard #undef IN_MAX
5685571bc7Sbellard #undef IN_MIN
5785571bc7Sbellard #undef IN_T
58*1d14ffa9Sbellard #undef SHIFT
5985571bc7Sbellard 
60*1d14ffa9Sbellard #undef ENDIAN_CONVERT
61*1d14ffa9Sbellard #undef ENDIAN_CONVERSION
62*1d14ffa9Sbellard 
63*1d14ffa9Sbellard /* Signed 16 bit */
6485571bc7Sbellard #define IN_T int16_t
6585571bc7Sbellard #define IN_MIN SHRT_MIN
6685571bc7Sbellard #define IN_MAX SHRT_MAX
6785571bc7Sbellard #define SIGNED
68*1d14ffa9Sbellard #define SHIFT 16
69*1d14ffa9Sbellard #define ENDIAN_CONVERSION natural
70*1d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
7185571bc7Sbellard #include "mixeng_template.h"
72*1d14ffa9Sbellard #undef ENDIAN_CONVERT
73*1d14ffa9Sbellard #undef ENDIAN_CONVERSION
74*1d14ffa9Sbellard #define ENDIAN_CONVERSION swap
75*1d14ffa9Sbellard #define ENDIAN_CONVERT(v) bswap16 (v)
76*1d14ffa9Sbellard #include "mixeng_template.h"
77*1d14ffa9Sbellard #undef ENDIAN_CONVERT
78*1d14ffa9Sbellard #undef ENDIAN_CONVERSION
7985571bc7Sbellard #undef SIGNED
8085571bc7Sbellard #undef IN_MAX
8185571bc7Sbellard #undef IN_MIN
8285571bc7Sbellard #undef IN_T
83*1d14ffa9Sbellard #undef SHIFT
8485571bc7Sbellard 
8585571bc7Sbellard #define IN_T uint16_t
8685571bc7Sbellard #define IN_MIN 0
8785571bc7Sbellard #define IN_MAX USHRT_MAX
88*1d14ffa9Sbellard #define SHIFT 16
89*1d14ffa9Sbellard #define ENDIAN_CONVERSION natural
90*1d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
9185571bc7Sbellard #include "mixeng_template.h"
92*1d14ffa9Sbellard #undef ENDIAN_CONVERT
93*1d14ffa9Sbellard #undef ENDIAN_CONVERSION
94*1d14ffa9Sbellard #define ENDIAN_CONVERSION swap
95*1d14ffa9Sbellard #define ENDIAN_CONVERT(v) bswap16 (v)
96*1d14ffa9Sbellard #include "mixeng_template.h"
97*1d14ffa9Sbellard #undef ENDIAN_CONVERT
98*1d14ffa9Sbellard #undef ENDIAN_CONVERSION
9985571bc7Sbellard #undef IN_MAX
10085571bc7Sbellard #undef IN_MIN
10185571bc7Sbellard #undef IN_T
102*1d14ffa9Sbellard #undef SHIFT
10385571bc7Sbellard 
104*1d14ffa9Sbellard t_sample *mixeng_conv[2][2][2][2] = {
10585571bc7Sbellard     {
10685571bc7Sbellard         {
107*1d14ffa9Sbellard             {
108*1d14ffa9Sbellard                 conv_natural_uint8_t_to_mono,
109*1d14ffa9Sbellard                 conv_natural_uint16_t_to_mono
11085571bc7Sbellard             },
11185571bc7Sbellard             {
112*1d14ffa9Sbellard                 conv_natural_uint8_t_to_mono,
113*1d14ffa9Sbellard                 conv_swap_uint16_t_to_mono
11485571bc7Sbellard             }
11585571bc7Sbellard         },
11685571bc7Sbellard         {
11785571bc7Sbellard             {
118*1d14ffa9Sbellard                 conv_natural_int8_t_to_mono,
119*1d14ffa9Sbellard                 conv_natural_int16_t_to_mono
12085571bc7Sbellard             },
12185571bc7Sbellard             {
122*1d14ffa9Sbellard                 conv_natural_int8_t_to_mono,
123*1d14ffa9Sbellard                 conv_swap_int16_t_to_mono
124*1d14ffa9Sbellard             }
125*1d14ffa9Sbellard         }
126*1d14ffa9Sbellard     },
127*1d14ffa9Sbellard     {
128*1d14ffa9Sbellard         {
129*1d14ffa9Sbellard             {
130*1d14ffa9Sbellard                 conv_natural_uint8_t_to_stereo,
131*1d14ffa9Sbellard                 conv_natural_uint16_t_to_stereo
132*1d14ffa9Sbellard             },
133*1d14ffa9Sbellard             {
134*1d14ffa9Sbellard                 conv_natural_uint8_t_to_stereo,
135*1d14ffa9Sbellard                 conv_swap_uint16_t_to_stereo
136*1d14ffa9Sbellard             }
137*1d14ffa9Sbellard         },
138*1d14ffa9Sbellard         {
139*1d14ffa9Sbellard             {
140*1d14ffa9Sbellard                 conv_natural_int8_t_to_stereo,
141*1d14ffa9Sbellard                 conv_natural_int16_t_to_stereo
142*1d14ffa9Sbellard             },
143*1d14ffa9Sbellard             {
144*1d14ffa9Sbellard                 conv_natural_int8_t_to_stereo,
145*1d14ffa9Sbellard                 conv_swap_int16_t_to_stereo
146*1d14ffa9Sbellard             }
14785571bc7Sbellard         }
14885571bc7Sbellard     }
14985571bc7Sbellard };
15085571bc7Sbellard 
151*1d14ffa9Sbellard f_sample *mixeng_clip[2][2][2][2] = {
15285571bc7Sbellard     {
15385571bc7Sbellard         {
154*1d14ffa9Sbellard             {
155*1d14ffa9Sbellard                 clip_natural_uint8_t_from_mono,
156*1d14ffa9Sbellard                 clip_natural_uint16_t_from_mono
15785571bc7Sbellard             },
15885571bc7Sbellard             {
159*1d14ffa9Sbellard                 clip_natural_uint8_t_from_mono,
160*1d14ffa9Sbellard                 clip_swap_uint16_t_from_mono
16185571bc7Sbellard             }
16285571bc7Sbellard         },
16385571bc7Sbellard         {
16485571bc7Sbellard             {
165*1d14ffa9Sbellard                 clip_natural_int8_t_from_mono,
166*1d14ffa9Sbellard                 clip_natural_int16_t_from_mono
16785571bc7Sbellard             },
16885571bc7Sbellard             {
169*1d14ffa9Sbellard                 clip_natural_int8_t_from_mono,
170*1d14ffa9Sbellard                 clip_swap_int16_t_from_mono
171*1d14ffa9Sbellard             }
172*1d14ffa9Sbellard         }
173*1d14ffa9Sbellard     },
174*1d14ffa9Sbellard     {
175*1d14ffa9Sbellard         {
176*1d14ffa9Sbellard             {
177*1d14ffa9Sbellard                 clip_natural_uint8_t_from_stereo,
178*1d14ffa9Sbellard                 clip_natural_uint16_t_from_stereo
179*1d14ffa9Sbellard             },
180*1d14ffa9Sbellard             {
181*1d14ffa9Sbellard                 clip_natural_uint8_t_from_stereo,
182*1d14ffa9Sbellard                 clip_swap_uint16_t_from_stereo
183*1d14ffa9Sbellard             }
184*1d14ffa9Sbellard         },
185*1d14ffa9Sbellard         {
186*1d14ffa9Sbellard             {
187*1d14ffa9Sbellard                 clip_natural_int8_t_from_stereo,
188*1d14ffa9Sbellard                 clip_natural_int16_t_from_stereo
189*1d14ffa9Sbellard             },
190*1d14ffa9Sbellard             {
191*1d14ffa9Sbellard                 clip_natural_int8_t_from_stereo,
192*1d14ffa9Sbellard                 clip_swap_int16_t_from_stereo
193*1d14ffa9Sbellard             }
19485571bc7Sbellard         }
19585571bc7Sbellard     }
19685571bc7Sbellard };
19785571bc7Sbellard 
19885571bc7Sbellard /*
19985571bc7Sbellard  * August 21, 1998
20085571bc7Sbellard  * Copyright 1998 Fabrice Bellard.
20185571bc7Sbellard  *
20285571bc7Sbellard  * [Rewrote completly the code of Lance Norskog And Sundry
20385571bc7Sbellard  * Contributors with a more efficient algorithm.]
20485571bc7Sbellard  *
20585571bc7Sbellard  * This source code is freely redistributable and may be used for
20685571bc7Sbellard  * any purpose.  This copyright notice must be maintained.
20785571bc7Sbellard  * Lance Norskog And Sundry Contributors are not responsible for
20885571bc7Sbellard  * the consequences of using this software.
20985571bc7Sbellard  */
21085571bc7Sbellard 
21185571bc7Sbellard /*
21285571bc7Sbellard  * Sound Tools rate change effect file.
21385571bc7Sbellard  */
21485571bc7Sbellard /*
21585571bc7Sbellard  * Linear Interpolation.
21685571bc7Sbellard  *
21785571bc7Sbellard  * The use of fractional increment allows us to use no buffer. It
21885571bc7Sbellard  * avoid the problems at the end of the buffer we had with the old
21985571bc7Sbellard  * method which stored a possibly big buffer of size
22085571bc7Sbellard  * lcm(in_rate,out_rate).
22185571bc7Sbellard  *
22285571bc7Sbellard  * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
22385571bc7Sbellard  * the input & output frequencies are equal, a delay of one sample is
22485571bc7Sbellard  * introduced.  Limited to processing 32-bit count worth of samples.
22585571bc7Sbellard  *
22685571bc7Sbellard  * 1 << FRAC_BITS evaluating to zero in several places.  Changed with
22785571bc7Sbellard  * an (unsigned long) cast to make it safe.  MarkMLl 2/1/99
22885571bc7Sbellard  */
22985571bc7Sbellard 
23085571bc7Sbellard /* Private data */
23185571bc7Sbellard typedef struct ratestuff {
23285571bc7Sbellard     uint64_t opos;
23385571bc7Sbellard     uint64_t opos_inc;
23485571bc7Sbellard     uint32_t ipos;              /* position in the input stream (integer) */
23585571bc7Sbellard     st_sample_t ilast;          /* last sample in the input stream */
23685571bc7Sbellard } *rate_t;
23785571bc7Sbellard 
23885571bc7Sbellard /*
23985571bc7Sbellard  * Prepare processing.
24085571bc7Sbellard  */
24185571bc7Sbellard void *st_rate_start (int inrate, int outrate)
24285571bc7Sbellard {
24385571bc7Sbellard     rate_t rate = (rate_t) qemu_mallocz (sizeof (struct ratestuff));
24485571bc7Sbellard 
24585571bc7Sbellard     if (!rate) {
246*1d14ffa9Sbellard         return NULL;
24785571bc7Sbellard     }
24885571bc7Sbellard 
24985571bc7Sbellard     rate->opos = 0;
25085571bc7Sbellard 
25185571bc7Sbellard     /* increment */
252*1d14ffa9Sbellard     rate->opos_inc = ((uint64_t) inrate << 32) / outrate;
25385571bc7Sbellard 
25485571bc7Sbellard     rate->ipos = 0;
25585571bc7Sbellard     rate->ilast.l = 0;
25685571bc7Sbellard     rate->ilast.r = 0;
25785571bc7Sbellard     return rate;
25885571bc7Sbellard }
25985571bc7Sbellard 
260*1d14ffa9Sbellard #define NAME st_rate_flow_mix
261*1d14ffa9Sbellard #define OP(a, b) a += b
262*1d14ffa9Sbellard #include "rate_template.h"
26385571bc7Sbellard 
264*1d14ffa9Sbellard #define NAME st_rate_flow
265*1d14ffa9Sbellard #define OP(a, b) a = b
266*1d14ffa9Sbellard #include "rate_template.h"
26785571bc7Sbellard 
26885571bc7Sbellard void st_rate_stop (void *opaque)
26985571bc7Sbellard {
27085571bc7Sbellard     qemu_free (opaque);
27185571bc7Sbellard }
272*1d14ffa9Sbellard 
273*1d14ffa9Sbellard void mixeng_clear (st_sample_t *buf, int len)
274*1d14ffa9Sbellard {
275*1d14ffa9Sbellard     memset (buf, 0, len * sizeof (st_sample_t));
276*1d14ffa9Sbellard }
277