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