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