xref: /openbmc/qemu/audio/mixeng.c (revision 832061a2fa33b933bf3e080cbc3625ec99bacd30)
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  */
256086a565SPeter Maydell #include "qemu/osdep.h"
2658369e22SPaolo Bonzini #include "qemu/bswap.h"
273d4d16f4SPavel Dovgalyuk #include "qemu/error-report.h"
2887ecb68bSpbrook #include "audio.h"
2985571bc7Sbellard 
301d14ffa9Sbellard #define AUDIO_CAP "mixeng"
311d14ffa9Sbellard #include "audio_int.h"
321d14ffa9Sbellard 
331d14ffa9Sbellard /* 8 bit */
341d14ffa9Sbellard #define ENDIAN_CONVERSION natural
351d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
361d14ffa9Sbellard 
371d14ffa9Sbellard /* Signed 8 bit */
38a2885387SRoger Pau Monne #define BSIZE 8
39a2885387SRoger Pau Monne #define ITYPE int
401d14ffa9Sbellard #define IN_MIN SCHAR_MIN
411d14ffa9Sbellard #define IN_MAX SCHAR_MAX
4285571bc7Sbellard #define SIGNED
431d14ffa9Sbellard #define SHIFT 8
4485571bc7Sbellard #include "mixeng_template.h"
4585571bc7Sbellard #undef SIGNED
4685571bc7Sbellard #undef IN_MAX
4785571bc7Sbellard #undef IN_MIN
48a2885387SRoger Pau Monne #undef BSIZE
49a2885387SRoger Pau Monne #undef ITYPE
501d14ffa9Sbellard #undef SHIFT
5185571bc7Sbellard 
521d14ffa9Sbellard /* Unsigned 8 bit */
53a2885387SRoger Pau Monne #define BSIZE 8
54a2885387SRoger Pau Monne #define ITYPE uint
5585571bc7Sbellard #define IN_MIN 0
5685571bc7Sbellard #define IN_MAX UCHAR_MAX
571d14ffa9Sbellard #define SHIFT 8
5885571bc7Sbellard #include "mixeng_template.h"
5985571bc7Sbellard #undef IN_MAX
6085571bc7Sbellard #undef IN_MIN
61a2885387SRoger Pau Monne #undef BSIZE
62a2885387SRoger Pau Monne #undef ITYPE
631d14ffa9Sbellard #undef SHIFT
6485571bc7Sbellard 
651d14ffa9Sbellard #undef ENDIAN_CONVERT
661d14ffa9Sbellard #undef ENDIAN_CONVERSION
671d14ffa9Sbellard 
681d14ffa9Sbellard /* Signed 16 bit */
69a2885387SRoger Pau Monne #define BSIZE 16
70a2885387SRoger Pau Monne #define ITYPE int
7185571bc7Sbellard #define IN_MIN SHRT_MIN
7285571bc7Sbellard #define IN_MAX SHRT_MAX
7385571bc7Sbellard #define SIGNED
741d14ffa9Sbellard #define SHIFT 16
751d14ffa9Sbellard #define ENDIAN_CONVERSION natural
761d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
7785571bc7Sbellard #include "mixeng_template.h"
781d14ffa9Sbellard #undef ENDIAN_CONVERT
791d14ffa9Sbellard #undef ENDIAN_CONVERSION
801d14ffa9Sbellard #define ENDIAN_CONVERSION swap
811d14ffa9Sbellard #define ENDIAN_CONVERT(v) bswap16 (v)
821d14ffa9Sbellard #include "mixeng_template.h"
831d14ffa9Sbellard #undef ENDIAN_CONVERT
841d14ffa9Sbellard #undef ENDIAN_CONVERSION
8585571bc7Sbellard #undef SIGNED
8685571bc7Sbellard #undef IN_MAX
8785571bc7Sbellard #undef IN_MIN
88a2885387SRoger Pau Monne #undef BSIZE
89a2885387SRoger Pau Monne #undef ITYPE
901d14ffa9Sbellard #undef SHIFT
9185571bc7Sbellard 
92f941aa25Sths /* Unsigned 16 bit */
93a2885387SRoger Pau Monne #define BSIZE 16
94a2885387SRoger Pau Monne #define ITYPE uint
9585571bc7Sbellard #define IN_MIN 0
9685571bc7Sbellard #define IN_MAX USHRT_MAX
971d14ffa9Sbellard #define SHIFT 16
981d14ffa9Sbellard #define ENDIAN_CONVERSION natural
991d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v)
10085571bc7Sbellard #include "mixeng_template.h"
1011d14ffa9Sbellard #undef ENDIAN_CONVERT
1021d14ffa9Sbellard #undef ENDIAN_CONVERSION
1031d14ffa9Sbellard #define ENDIAN_CONVERSION swap
1041d14ffa9Sbellard #define ENDIAN_CONVERT(v) bswap16 (v)
1051d14ffa9Sbellard #include "mixeng_template.h"
1061d14ffa9Sbellard #undef ENDIAN_CONVERT
1071d14ffa9Sbellard #undef ENDIAN_CONVERSION
10885571bc7Sbellard #undef IN_MAX
10985571bc7Sbellard #undef IN_MIN
110a2885387SRoger Pau Monne #undef BSIZE
111a2885387SRoger Pau Monne #undef ITYPE
1121d14ffa9Sbellard #undef SHIFT
11385571bc7Sbellard 
114f941aa25Sths /* Signed 32 bit */
115a2885387SRoger Pau Monne #define BSIZE 32
116a2885387SRoger Pau Monne #define ITYPE int
117f941aa25Sths #define IN_MIN INT32_MIN
118f941aa25Sths #define IN_MAX INT32_MAX
119f941aa25Sths #define SIGNED
120f941aa25Sths #define SHIFT 32
121f941aa25Sths #define ENDIAN_CONVERSION natural
122f941aa25Sths #define ENDIAN_CONVERT(v) (v)
123f941aa25Sths #include "mixeng_template.h"
124f941aa25Sths #undef ENDIAN_CONVERT
125f941aa25Sths #undef ENDIAN_CONVERSION
126f941aa25Sths #define ENDIAN_CONVERSION swap
127f941aa25Sths #define ENDIAN_CONVERT(v) bswap32 (v)
128f941aa25Sths #include "mixeng_template.h"
129f941aa25Sths #undef ENDIAN_CONVERT
130f941aa25Sths #undef ENDIAN_CONVERSION
131f941aa25Sths #undef SIGNED
132f941aa25Sths #undef IN_MAX
133f941aa25Sths #undef IN_MIN
134a2885387SRoger Pau Monne #undef BSIZE
135a2885387SRoger Pau Monne #undef ITYPE
136f941aa25Sths #undef SHIFT
137f941aa25Sths 
138ad483a51Smalc /* Unsigned 32 bit */
139a2885387SRoger Pau Monne #define BSIZE 32
140a2885387SRoger Pau Monne #define ITYPE uint
141f941aa25Sths #define IN_MIN 0
142f941aa25Sths #define IN_MAX UINT32_MAX
143f941aa25Sths #define SHIFT 32
144f941aa25Sths #define ENDIAN_CONVERSION natural
145f941aa25Sths #define ENDIAN_CONVERT(v) (v)
146f941aa25Sths #include "mixeng_template.h"
147f941aa25Sths #undef ENDIAN_CONVERT
148f941aa25Sths #undef ENDIAN_CONVERSION
149f941aa25Sths #define ENDIAN_CONVERSION swap
150f941aa25Sths #define ENDIAN_CONVERT(v) bswap32 (v)
151f941aa25Sths #include "mixeng_template.h"
152f941aa25Sths #undef ENDIAN_CONVERT
153f941aa25Sths #undef ENDIAN_CONVERSION
154f941aa25Sths #undef IN_MAX
155f941aa25Sths #undef IN_MIN
156a2885387SRoger Pau Monne #undef BSIZE
157a2885387SRoger Pau Monne #undef ITYPE
158f941aa25Sths #undef SHIFT
159f941aa25Sths 
160f941aa25Sths t_sample *mixeng_conv[2][2][2][3] = {
16185571bc7Sbellard     {
16285571bc7Sbellard         {
1631d14ffa9Sbellard             {
1641d14ffa9Sbellard                 conv_natural_uint8_t_to_mono,
165f941aa25Sths                 conv_natural_uint16_t_to_mono,
166f941aa25Sths                 conv_natural_uint32_t_to_mono
16785571bc7Sbellard             },
16885571bc7Sbellard             {
1691d14ffa9Sbellard                 conv_natural_uint8_t_to_mono,
170f941aa25Sths                 conv_swap_uint16_t_to_mono,
171f941aa25Sths                 conv_swap_uint32_t_to_mono,
17285571bc7Sbellard             }
17385571bc7Sbellard         },
17485571bc7Sbellard         {
17585571bc7Sbellard             {
1761d14ffa9Sbellard                 conv_natural_int8_t_to_mono,
177f941aa25Sths                 conv_natural_int16_t_to_mono,
178f941aa25Sths                 conv_natural_int32_t_to_mono
17985571bc7Sbellard             },
18085571bc7Sbellard             {
1811d14ffa9Sbellard                 conv_natural_int8_t_to_mono,
182f941aa25Sths                 conv_swap_int16_t_to_mono,
183f941aa25Sths                 conv_swap_int32_t_to_mono
1841d14ffa9Sbellard             }
1851d14ffa9Sbellard         }
1861d14ffa9Sbellard     },
1871d14ffa9Sbellard     {
1881d14ffa9Sbellard         {
1891d14ffa9Sbellard             {
1901d14ffa9Sbellard                 conv_natural_uint8_t_to_stereo,
191f941aa25Sths                 conv_natural_uint16_t_to_stereo,
192f941aa25Sths                 conv_natural_uint32_t_to_stereo
1931d14ffa9Sbellard             },
1941d14ffa9Sbellard             {
1951d14ffa9Sbellard                 conv_natural_uint8_t_to_stereo,
196f941aa25Sths                 conv_swap_uint16_t_to_stereo,
197f941aa25Sths                 conv_swap_uint32_t_to_stereo
1981d14ffa9Sbellard             }
1991d14ffa9Sbellard         },
2001d14ffa9Sbellard         {
2011d14ffa9Sbellard             {
2021d14ffa9Sbellard                 conv_natural_int8_t_to_stereo,
203f941aa25Sths                 conv_natural_int16_t_to_stereo,
204f941aa25Sths                 conv_natural_int32_t_to_stereo
2051d14ffa9Sbellard             },
2061d14ffa9Sbellard             {
2071d14ffa9Sbellard                 conv_natural_int8_t_to_stereo,
208f941aa25Sths                 conv_swap_int16_t_to_stereo,
209f941aa25Sths                 conv_swap_int32_t_to_stereo,
2101d14ffa9Sbellard             }
21185571bc7Sbellard         }
21285571bc7Sbellard     }
21385571bc7Sbellard };
21485571bc7Sbellard 
215f941aa25Sths f_sample *mixeng_clip[2][2][2][3] = {
21685571bc7Sbellard     {
21785571bc7Sbellard         {
2181d14ffa9Sbellard             {
2191d14ffa9Sbellard                 clip_natural_uint8_t_from_mono,
220f941aa25Sths                 clip_natural_uint16_t_from_mono,
221f941aa25Sths                 clip_natural_uint32_t_from_mono
22285571bc7Sbellard             },
22385571bc7Sbellard             {
2241d14ffa9Sbellard                 clip_natural_uint8_t_from_mono,
225f941aa25Sths                 clip_swap_uint16_t_from_mono,
226f941aa25Sths                 clip_swap_uint32_t_from_mono
22785571bc7Sbellard             }
22885571bc7Sbellard         },
22985571bc7Sbellard         {
23085571bc7Sbellard             {
2311d14ffa9Sbellard                 clip_natural_int8_t_from_mono,
232f941aa25Sths                 clip_natural_int16_t_from_mono,
233f941aa25Sths                 clip_natural_int32_t_from_mono
23485571bc7Sbellard             },
23585571bc7Sbellard             {
2361d14ffa9Sbellard                 clip_natural_int8_t_from_mono,
237f941aa25Sths                 clip_swap_int16_t_from_mono,
238f941aa25Sths                 clip_swap_int32_t_from_mono
2391d14ffa9Sbellard             }
2401d14ffa9Sbellard         }
2411d14ffa9Sbellard     },
2421d14ffa9Sbellard     {
2431d14ffa9Sbellard         {
2441d14ffa9Sbellard             {
2451d14ffa9Sbellard                 clip_natural_uint8_t_from_stereo,
246f941aa25Sths                 clip_natural_uint16_t_from_stereo,
247f941aa25Sths                 clip_natural_uint32_t_from_stereo
2481d14ffa9Sbellard             },
2491d14ffa9Sbellard             {
2501d14ffa9Sbellard                 clip_natural_uint8_t_from_stereo,
251f941aa25Sths                 clip_swap_uint16_t_from_stereo,
252f941aa25Sths                 clip_swap_uint32_t_from_stereo
2531d14ffa9Sbellard             }
2541d14ffa9Sbellard         },
2551d14ffa9Sbellard         {
2561d14ffa9Sbellard             {
2571d14ffa9Sbellard                 clip_natural_int8_t_from_stereo,
258f941aa25Sths                 clip_natural_int16_t_from_stereo,
259f941aa25Sths                 clip_natural_int32_t_from_stereo
2601d14ffa9Sbellard             },
2611d14ffa9Sbellard             {
2621d14ffa9Sbellard                 clip_natural_int8_t_from_stereo,
263f941aa25Sths                 clip_swap_int16_t_from_stereo,
264f941aa25Sths                 clip_swap_int32_t_from_stereo
2651d14ffa9Sbellard             }
26685571bc7Sbellard         }
26785571bc7Sbellard     }
26885571bc7Sbellard };
26985571bc7Sbellard 
270ed2a4a79SKővágó, Zoltán #ifdef FLOAT_MIXENG
271dd381319SVolker Rümelin #define CONV_NATURAL_FLOAT(x) (x)
272dd381319SVolker Rümelin #define CLIP_NATURAL_FLOAT(x) (x)
273ed2a4a79SKővágó, Zoltán #else
2749c61fcc8SVolker Rümelin /* macros to map [-1.f, 1.f] <-> [INT32_MIN, INT32_MAX + 1] */
2759c61fcc8SVolker Rümelin static const float float_scale = (int64_t)INT32_MAX + 1;
276dd381319SVolker Rümelin #define CONV_NATURAL_FLOAT(x) ((x) * float_scale)
277ed2a4a79SKővágó, Zoltán 
278ed2a4a79SKővágó, Zoltán #ifdef RECIPROCAL
2799c61fcc8SVolker Rümelin static const float float_scale_reciprocal = 1.f / ((int64_t)INT32_MAX + 1);
280dd381319SVolker Rümelin #define CLIP_NATURAL_FLOAT(x) ((x) * float_scale_reciprocal)
281ed2a4a79SKővágó, Zoltán #else
282dd381319SVolker Rümelin #define CLIP_NATURAL_FLOAT(x) ((x) / float_scale)
283ed2a4a79SKővágó, Zoltán #endif
284ed2a4a79SKővágó, Zoltán #endif
285ed2a4a79SKővágó, Zoltán 
286ed2a4a79SKővágó, Zoltán static void conv_natural_float_to_mono(struct st_sample *dst, const void *src,
287180b044fSVolker Rümelin                                        int samples)
288180b044fSVolker Rümelin {
289180b044fSVolker Rümelin     float *in = (float *)src;
290180b044fSVolker Rümelin 
291180b044fSVolker Rümelin     while (samples--) {
292dd381319SVolker Rümelin         dst->r = dst->l = CONV_NATURAL_FLOAT(*in++);
293180b044fSVolker Rümelin         dst++;
294180b044fSVolker Rümelin     }
295180b044fSVolker Rümelin }
296180b044fSVolker Rümelin 
297ed2a4a79SKővágó, Zoltán static void conv_natural_float_to_stereo(struct st_sample *dst, const void *src,
298ed2a4a79SKővágó, Zoltán                                          int samples)
299ed2a4a79SKővágó, Zoltán {
300ed2a4a79SKővágó, Zoltán     float *in = (float *)src;
301ed2a4a79SKővágó, Zoltán 
302ed2a4a79SKővágó, Zoltán     while (samples--) {
303dd381319SVolker Rümelin         dst->l = CONV_NATURAL_FLOAT(*in++);
304dd381319SVolker Rümelin         dst->r = CONV_NATURAL_FLOAT(*in++);
305ed2a4a79SKővágó, Zoltán         dst++;
306ed2a4a79SKővágó, Zoltán     }
307ed2a4a79SKővágó, Zoltán }
308ed2a4a79SKővágó, Zoltán 
309ed2a4a79SKővágó, Zoltán t_sample *mixeng_conv_float[2] = {
310ed2a4a79SKővágó, Zoltán     conv_natural_float_to_mono,
311ed2a4a79SKővágó, Zoltán     conv_natural_float_to_stereo,
312ed2a4a79SKővágó, Zoltán };
313ed2a4a79SKővágó, Zoltán 
314ed2a4a79SKővágó, Zoltán static void clip_natural_float_from_mono(void *dst, const struct st_sample *src,
315180b044fSVolker Rümelin                                          int samples)
316180b044fSVolker Rümelin {
317180b044fSVolker Rümelin     float *out = (float *)dst;
318180b044fSVolker Rümelin 
319180b044fSVolker Rümelin     while (samples--) {
32033a93baeSVolker Rümelin         *out++ = CLIP_NATURAL_FLOAT(src->l + src->r);
321180b044fSVolker Rümelin         src++;
322180b044fSVolker Rümelin     }
323180b044fSVolker Rümelin }
3243d4d16f4SPavel Dovgalyuk 
325ed2a4a79SKővágó, Zoltán static void clip_natural_float_from_stereo(
326ed2a4a79SKővágó, Zoltán     void *dst, const struct st_sample *src, int samples)
327ed2a4a79SKővágó, Zoltán {
328ed2a4a79SKővágó, Zoltán     float *out = (float *)dst;
329ed2a4a79SKővágó, Zoltán 
330ed2a4a79SKővágó, Zoltán     while (samples--) {
331dd381319SVolker Rümelin         *out++ = CLIP_NATURAL_FLOAT(src->l);
332dd381319SVolker Rümelin         *out++ = CLIP_NATURAL_FLOAT(src->r);
333ed2a4a79SKővágó, Zoltán         src++;
334ed2a4a79SKővágó, Zoltán     }
335ed2a4a79SKővágó, Zoltán }
336ed2a4a79SKővágó, Zoltán 
337ed2a4a79SKővágó, Zoltán f_sample *mixeng_clip_float[2] = {
338ed2a4a79SKővágó, Zoltán     clip_natural_float_from_mono,
339ed2a4a79SKővágó, Zoltán     clip_natural_float_from_stereo,
340ed2a4a79SKővágó, Zoltán };
341ed2a4a79SKővágó, Zoltán 
342e709d2acSPhilippe Mathieu-Daudé void audio_sample_to_uint64(const void *samples, int pos,
3433d4d16f4SPavel Dovgalyuk                             uint64_t *left, uint64_t *right)
3443d4d16f4SPavel Dovgalyuk {
3453d4d16f4SPavel Dovgalyuk #ifdef FLOAT_MIXENG
3463d4d16f4SPavel Dovgalyuk     error_report(
3473d4d16f4SPavel Dovgalyuk         "Coreaudio and floating point samples are not supported by replay yet");
3483d4d16f4SPavel Dovgalyuk     abort();
3493d4d16f4SPavel Dovgalyuk #else
350*832061a2SAkihiko Odaki     const struct st_sample *sample = samples;
351*832061a2SAkihiko Odaki     sample += pos;
3523d4d16f4SPavel Dovgalyuk     *left = sample->l;
3533d4d16f4SPavel Dovgalyuk     *right = sample->r;
3543d4d16f4SPavel Dovgalyuk #endif
3553d4d16f4SPavel Dovgalyuk }
3563d4d16f4SPavel Dovgalyuk 
3573d4d16f4SPavel Dovgalyuk void audio_sample_from_uint64(void *samples, int pos,
3583d4d16f4SPavel Dovgalyuk                             uint64_t left, uint64_t right)
3593d4d16f4SPavel Dovgalyuk {
3603d4d16f4SPavel Dovgalyuk #ifdef FLOAT_MIXENG
3613d4d16f4SPavel Dovgalyuk     error_report(
3623d4d16f4SPavel Dovgalyuk         "Coreaudio and floating point samples are not supported by replay yet");
3633d4d16f4SPavel Dovgalyuk     abort();
3643d4d16f4SPavel Dovgalyuk #else
365*832061a2SAkihiko Odaki     struct st_sample *sample = samples;
366*832061a2SAkihiko Odaki     sample += pos;
3673d4d16f4SPavel Dovgalyuk     sample->l = left;
3683d4d16f4SPavel Dovgalyuk     sample->r = right;
3693d4d16f4SPavel Dovgalyuk #endif
3703d4d16f4SPavel Dovgalyuk }
3713d4d16f4SPavel Dovgalyuk 
37285571bc7Sbellard /*
37385571bc7Sbellard  * August 21, 1998
37485571bc7Sbellard  * Copyright 1998 Fabrice Bellard.
37585571bc7Sbellard  *
376cb8d4c8fSStefan Weil  * [Rewrote completely the code of Lance Norskog And Sundry
37785571bc7Sbellard  * Contributors with a more efficient algorithm.]
37885571bc7Sbellard  *
37985571bc7Sbellard  * This source code is freely redistributable and may be used for
38085571bc7Sbellard  * any purpose.  This copyright notice must be maintained.
38185571bc7Sbellard  * Lance Norskog And Sundry Contributors are not responsible for
38285571bc7Sbellard  * the consequences of using this software.
38385571bc7Sbellard  */
38485571bc7Sbellard 
38585571bc7Sbellard /*
38685571bc7Sbellard  * Sound Tools rate change effect file.
38785571bc7Sbellard  */
38885571bc7Sbellard /*
38985571bc7Sbellard  * Linear Interpolation.
39085571bc7Sbellard  *
39185571bc7Sbellard  * The use of fractional increment allows us to use no buffer. It
39285571bc7Sbellard  * avoid the problems at the end of the buffer we had with the old
39385571bc7Sbellard  * method which stored a possibly big buffer of size
39485571bc7Sbellard  * lcm(in_rate,out_rate).
39585571bc7Sbellard  *
39685571bc7Sbellard  * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
39785571bc7Sbellard  * the input & output frequencies are equal, a delay of one sample is
39885571bc7Sbellard  * introduced.  Limited to processing 32-bit count worth of samples.
39985571bc7Sbellard  *
40085571bc7Sbellard  * 1 << FRAC_BITS evaluating to zero in several places.  Changed with
40185571bc7Sbellard  * an (unsigned long) cast to make it safe.  MarkMLl 2/1/99
40285571bc7Sbellard  */
40385571bc7Sbellard 
40485571bc7Sbellard /* Private data */
405c0fe3827Sbellard struct rate {
40685571bc7Sbellard     uint64_t opos;
40785571bc7Sbellard     uint64_t opos_inc;
40885571bc7Sbellard     uint32_t ipos;              /* position in the input stream (integer) */
4091ea879e5Smalc     struct st_sample ilast;          /* last sample in the input stream */
410c0fe3827Sbellard };
41185571bc7Sbellard 
41285571bc7Sbellard /*
41385571bc7Sbellard  * Prepare processing.
41485571bc7Sbellard  */
41585571bc7Sbellard void *st_rate_start (int inrate, int outrate)
41685571bc7Sbellard {
417470bcabdSAlistair Francis     struct rate *rate = audio_calloc(__func__, 1, sizeof(*rate));
41885571bc7Sbellard 
41985571bc7Sbellard     if (!rate) {
420e7cad338Sbellard         dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate));
4211d14ffa9Sbellard         return NULL;
42285571bc7Sbellard     }
42385571bc7Sbellard 
42485571bc7Sbellard     rate->opos = 0;
42585571bc7Sbellard 
42685571bc7Sbellard     /* increment */
4271d14ffa9Sbellard     rate->opos_inc = ((uint64_t) inrate << 32) / outrate;
42885571bc7Sbellard 
42985571bc7Sbellard     rate->ipos = 0;
43085571bc7Sbellard     rate->ilast.l = 0;
43185571bc7Sbellard     rate->ilast.r = 0;
43285571bc7Sbellard     return rate;
43385571bc7Sbellard }
43485571bc7Sbellard 
4351d14ffa9Sbellard #define NAME st_rate_flow_mix
4361d14ffa9Sbellard #define OP(a, b) a += b
4371d14ffa9Sbellard #include "rate_template.h"
43885571bc7Sbellard 
4391d14ffa9Sbellard #define NAME st_rate_flow
4401d14ffa9Sbellard #define OP(a, b) a = b
4411d14ffa9Sbellard #include "rate_template.h"
44285571bc7Sbellard 
44385571bc7Sbellard void st_rate_stop (void *opaque)
44485571bc7Sbellard {
4457267c094SAnthony Liguori     g_free (opaque);
44685571bc7Sbellard }
4471d14ffa9Sbellard 
4481ea879e5Smalc void mixeng_clear (struct st_sample *buf, int len)
4491d14ffa9Sbellard {
4501ea879e5Smalc     memset (buf, 0, len * sizeof (struct st_sample));
4511d14ffa9Sbellard }
45200e07679SMichael Walle 
45300e07679SMichael Walle void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol)
45400e07679SMichael Walle {
45500e07679SMichael Walle     if (vol->mute) {
45600e07679SMichael Walle         mixeng_clear (buf, len);
45700e07679SMichael Walle         return;
45800e07679SMichael Walle     }
45900e07679SMichael Walle 
46000e07679SMichael Walle     while (len--) {
46100e07679SMichael Walle #ifdef FLOAT_MIXENG
46200e07679SMichael Walle         buf->l = buf->l * vol->l;
46300e07679SMichael Walle         buf->r = buf->r * vol->r;
46400e07679SMichael Walle #else
46500e07679SMichael Walle         buf->l = (buf->l * vol->l) >> 32;
46600e07679SMichael Walle         buf->r = (buf->r * vol->r) >> 32;
46700e07679SMichael Walle #endif
46800e07679SMichael Walle         buf += 1;
46900e07679SMichael Walle     }
47000e07679SMichael Walle }
471