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" 2687ecb68bSpbrook #include "qemu-common.h" 2758369e22SPaolo Bonzini #include "qemu/bswap.h" 283d4d16f4SPavel Dovgalyuk #include "qemu/error-report.h" 2987ecb68bSpbrook #include "audio.h" 3085571bc7Sbellard 311d14ffa9Sbellard #define AUDIO_CAP "mixeng" 321d14ffa9Sbellard #include "audio_int.h" 331d14ffa9Sbellard 341d14ffa9Sbellard /* 8 bit */ 351d14ffa9Sbellard #define ENDIAN_CONVERSION natural 361d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v) 371d14ffa9Sbellard 381d14ffa9Sbellard /* Signed 8 bit */ 39a2885387SRoger Pau Monne #define BSIZE 8 40a2885387SRoger Pau Monne #define ITYPE int 411d14ffa9Sbellard #define IN_MIN SCHAR_MIN 421d14ffa9Sbellard #define IN_MAX SCHAR_MAX 4385571bc7Sbellard #define SIGNED 441d14ffa9Sbellard #define SHIFT 8 4585571bc7Sbellard #include "mixeng_template.h" 4685571bc7Sbellard #undef SIGNED 4785571bc7Sbellard #undef IN_MAX 4885571bc7Sbellard #undef IN_MIN 49a2885387SRoger Pau Monne #undef BSIZE 50a2885387SRoger Pau Monne #undef ITYPE 511d14ffa9Sbellard #undef SHIFT 5285571bc7Sbellard 531d14ffa9Sbellard /* Unsigned 8 bit */ 54a2885387SRoger Pau Monne #define BSIZE 8 55a2885387SRoger Pau Monne #define ITYPE uint 5685571bc7Sbellard #define IN_MIN 0 5785571bc7Sbellard #define IN_MAX UCHAR_MAX 581d14ffa9Sbellard #define SHIFT 8 5985571bc7Sbellard #include "mixeng_template.h" 6085571bc7Sbellard #undef IN_MAX 6185571bc7Sbellard #undef IN_MIN 62a2885387SRoger Pau Monne #undef BSIZE 63a2885387SRoger Pau Monne #undef ITYPE 641d14ffa9Sbellard #undef SHIFT 6585571bc7Sbellard 661d14ffa9Sbellard #undef ENDIAN_CONVERT 671d14ffa9Sbellard #undef ENDIAN_CONVERSION 681d14ffa9Sbellard 691d14ffa9Sbellard /* Signed 16 bit */ 70a2885387SRoger Pau Monne #define BSIZE 16 71a2885387SRoger Pau Monne #define ITYPE int 7285571bc7Sbellard #define IN_MIN SHRT_MIN 7385571bc7Sbellard #define IN_MAX SHRT_MAX 7485571bc7Sbellard #define SIGNED 751d14ffa9Sbellard #define SHIFT 16 761d14ffa9Sbellard #define ENDIAN_CONVERSION natural 771d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v) 7885571bc7Sbellard #include "mixeng_template.h" 791d14ffa9Sbellard #undef ENDIAN_CONVERT 801d14ffa9Sbellard #undef ENDIAN_CONVERSION 811d14ffa9Sbellard #define ENDIAN_CONVERSION swap 821d14ffa9Sbellard #define ENDIAN_CONVERT(v) bswap16 (v) 831d14ffa9Sbellard #include "mixeng_template.h" 841d14ffa9Sbellard #undef ENDIAN_CONVERT 851d14ffa9Sbellard #undef ENDIAN_CONVERSION 8685571bc7Sbellard #undef SIGNED 8785571bc7Sbellard #undef IN_MAX 8885571bc7Sbellard #undef IN_MIN 89a2885387SRoger Pau Monne #undef BSIZE 90a2885387SRoger Pau Monne #undef ITYPE 911d14ffa9Sbellard #undef SHIFT 9285571bc7Sbellard 93f941aa25Sths /* Unsigned 16 bit */ 94a2885387SRoger Pau Monne #define BSIZE 16 95a2885387SRoger Pau Monne #define ITYPE uint 9685571bc7Sbellard #define IN_MIN 0 9785571bc7Sbellard #define IN_MAX USHRT_MAX 981d14ffa9Sbellard #define SHIFT 16 991d14ffa9Sbellard #define ENDIAN_CONVERSION natural 1001d14ffa9Sbellard #define ENDIAN_CONVERT(v) (v) 10185571bc7Sbellard #include "mixeng_template.h" 1021d14ffa9Sbellard #undef ENDIAN_CONVERT 1031d14ffa9Sbellard #undef ENDIAN_CONVERSION 1041d14ffa9Sbellard #define ENDIAN_CONVERSION swap 1051d14ffa9Sbellard #define ENDIAN_CONVERT(v) bswap16 (v) 1061d14ffa9Sbellard #include "mixeng_template.h" 1071d14ffa9Sbellard #undef ENDIAN_CONVERT 1081d14ffa9Sbellard #undef ENDIAN_CONVERSION 10985571bc7Sbellard #undef IN_MAX 11085571bc7Sbellard #undef IN_MIN 111a2885387SRoger Pau Monne #undef BSIZE 112a2885387SRoger Pau Monne #undef ITYPE 1131d14ffa9Sbellard #undef SHIFT 11485571bc7Sbellard 115f941aa25Sths /* Signed 32 bit */ 116a2885387SRoger Pau Monne #define BSIZE 32 117a2885387SRoger Pau Monne #define ITYPE int 118f941aa25Sths #define IN_MIN INT32_MIN 119f941aa25Sths #define IN_MAX INT32_MAX 120f941aa25Sths #define SIGNED 121f941aa25Sths #define SHIFT 32 122f941aa25Sths #define ENDIAN_CONVERSION natural 123f941aa25Sths #define ENDIAN_CONVERT(v) (v) 124f941aa25Sths #include "mixeng_template.h" 125f941aa25Sths #undef ENDIAN_CONVERT 126f941aa25Sths #undef ENDIAN_CONVERSION 127f941aa25Sths #define ENDIAN_CONVERSION swap 128f941aa25Sths #define ENDIAN_CONVERT(v) bswap32 (v) 129f941aa25Sths #include "mixeng_template.h" 130f941aa25Sths #undef ENDIAN_CONVERT 131f941aa25Sths #undef ENDIAN_CONVERSION 132f941aa25Sths #undef SIGNED 133f941aa25Sths #undef IN_MAX 134f941aa25Sths #undef IN_MIN 135a2885387SRoger Pau Monne #undef BSIZE 136a2885387SRoger Pau Monne #undef ITYPE 137f941aa25Sths #undef SHIFT 138f941aa25Sths 139ad483a51Smalc /* Unsigned 32 bit */ 140a2885387SRoger Pau Monne #define BSIZE 32 141a2885387SRoger Pau Monne #define ITYPE uint 142f941aa25Sths #define IN_MIN 0 143f941aa25Sths #define IN_MAX UINT32_MAX 144f941aa25Sths #define SHIFT 32 145f941aa25Sths #define ENDIAN_CONVERSION natural 146f941aa25Sths #define ENDIAN_CONVERT(v) (v) 147f941aa25Sths #include "mixeng_template.h" 148f941aa25Sths #undef ENDIAN_CONVERT 149f941aa25Sths #undef ENDIAN_CONVERSION 150f941aa25Sths #define ENDIAN_CONVERSION swap 151f941aa25Sths #define ENDIAN_CONVERT(v) bswap32 (v) 152f941aa25Sths #include "mixeng_template.h" 153f941aa25Sths #undef ENDIAN_CONVERT 154f941aa25Sths #undef ENDIAN_CONVERSION 155f941aa25Sths #undef IN_MAX 156f941aa25Sths #undef IN_MIN 157a2885387SRoger Pau Monne #undef BSIZE 158a2885387SRoger Pau Monne #undef ITYPE 159f941aa25Sths #undef SHIFT 160f941aa25Sths 161f941aa25Sths t_sample *mixeng_conv[2][2][2][3] = { 16285571bc7Sbellard { 16385571bc7Sbellard { 1641d14ffa9Sbellard { 1651d14ffa9Sbellard conv_natural_uint8_t_to_mono, 166f941aa25Sths conv_natural_uint16_t_to_mono, 167f941aa25Sths conv_natural_uint32_t_to_mono 16885571bc7Sbellard }, 16985571bc7Sbellard { 1701d14ffa9Sbellard conv_natural_uint8_t_to_mono, 171f941aa25Sths conv_swap_uint16_t_to_mono, 172f941aa25Sths conv_swap_uint32_t_to_mono, 17385571bc7Sbellard } 17485571bc7Sbellard }, 17585571bc7Sbellard { 17685571bc7Sbellard { 1771d14ffa9Sbellard conv_natural_int8_t_to_mono, 178f941aa25Sths conv_natural_int16_t_to_mono, 179f941aa25Sths conv_natural_int32_t_to_mono 18085571bc7Sbellard }, 18185571bc7Sbellard { 1821d14ffa9Sbellard conv_natural_int8_t_to_mono, 183f941aa25Sths conv_swap_int16_t_to_mono, 184f941aa25Sths conv_swap_int32_t_to_mono 1851d14ffa9Sbellard } 1861d14ffa9Sbellard } 1871d14ffa9Sbellard }, 1881d14ffa9Sbellard { 1891d14ffa9Sbellard { 1901d14ffa9Sbellard { 1911d14ffa9Sbellard conv_natural_uint8_t_to_stereo, 192f941aa25Sths conv_natural_uint16_t_to_stereo, 193f941aa25Sths conv_natural_uint32_t_to_stereo 1941d14ffa9Sbellard }, 1951d14ffa9Sbellard { 1961d14ffa9Sbellard conv_natural_uint8_t_to_stereo, 197f941aa25Sths conv_swap_uint16_t_to_stereo, 198f941aa25Sths conv_swap_uint32_t_to_stereo 1991d14ffa9Sbellard } 2001d14ffa9Sbellard }, 2011d14ffa9Sbellard { 2021d14ffa9Sbellard { 2031d14ffa9Sbellard conv_natural_int8_t_to_stereo, 204f941aa25Sths conv_natural_int16_t_to_stereo, 205f941aa25Sths conv_natural_int32_t_to_stereo 2061d14ffa9Sbellard }, 2071d14ffa9Sbellard { 2081d14ffa9Sbellard conv_natural_int8_t_to_stereo, 209f941aa25Sths conv_swap_int16_t_to_stereo, 210f941aa25Sths conv_swap_int32_t_to_stereo, 2111d14ffa9Sbellard } 21285571bc7Sbellard } 21385571bc7Sbellard } 21485571bc7Sbellard }; 21585571bc7Sbellard 216f941aa25Sths f_sample *mixeng_clip[2][2][2][3] = { 21785571bc7Sbellard { 21885571bc7Sbellard { 2191d14ffa9Sbellard { 2201d14ffa9Sbellard clip_natural_uint8_t_from_mono, 221f941aa25Sths clip_natural_uint16_t_from_mono, 222f941aa25Sths clip_natural_uint32_t_from_mono 22385571bc7Sbellard }, 22485571bc7Sbellard { 2251d14ffa9Sbellard clip_natural_uint8_t_from_mono, 226f941aa25Sths clip_swap_uint16_t_from_mono, 227f941aa25Sths clip_swap_uint32_t_from_mono 22885571bc7Sbellard } 22985571bc7Sbellard }, 23085571bc7Sbellard { 23185571bc7Sbellard { 2321d14ffa9Sbellard clip_natural_int8_t_from_mono, 233f941aa25Sths clip_natural_int16_t_from_mono, 234f941aa25Sths clip_natural_int32_t_from_mono 23585571bc7Sbellard }, 23685571bc7Sbellard { 2371d14ffa9Sbellard clip_natural_int8_t_from_mono, 238f941aa25Sths clip_swap_int16_t_from_mono, 239f941aa25Sths clip_swap_int32_t_from_mono 2401d14ffa9Sbellard } 2411d14ffa9Sbellard } 2421d14ffa9Sbellard }, 2431d14ffa9Sbellard { 2441d14ffa9Sbellard { 2451d14ffa9Sbellard { 2461d14ffa9Sbellard clip_natural_uint8_t_from_stereo, 247f941aa25Sths clip_natural_uint16_t_from_stereo, 248f941aa25Sths clip_natural_uint32_t_from_stereo 2491d14ffa9Sbellard }, 2501d14ffa9Sbellard { 2511d14ffa9Sbellard clip_natural_uint8_t_from_stereo, 252f941aa25Sths clip_swap_uint16_t_from_stereo, 253f941aa25Sths clip_swap_uint32_t_from_stereo 2541d14ffa9Sbellard } 2551d14ffa9Sbellard }, 2561d14ffa9Sbellard { 2571d14ffa9Sbellard { 2581d14ffa9Sbellard clip_natural_int8_t_from_stereo, 259f941aa25Sths clip_natural_int16_t_from_stereo, 260f941aa25Sths clip_natural_int32_t_from_stereo 2611d14ffa9Sbellard }, 2621d14ffa9Sbellard { 2631d14ffa9Sbellard clip_natural_int8_t_from_stereo, 264f941aa25Sths clip_swap_int16_t_from_stereo, 265f941aa25Sths clip_swap_int32_t_from_stereo 2661d14ffa9Sbellard } 26785571bc7Sbellard } 26885571bc7Sbellard } 26985571bc7Sbellard }; 27085571bc7Sbellard 2713d4d16f4SPavel Dovgalyuk 2723d4d16f4SPavel Dovgalyuk void audio_sample_to_uint64(void *samples, int pos, 2733d4d16f4SPavel Dovgalyuk uint64_t *left, uint64_t *right) 2743d4d16f4SPavel Dovgalyuk { 2753d4d16f4SPavel Dovgalyuk struct st_sample *sample = samples; 2763d4d16f4SPavel Dovgalyuk sample += pos; 2773d4d16f4SPavel Dovgalyuk #ifdef FLOAT_MIXENG 2783d4d16f4SPavel Dovgalyuk error_report( 2793d4d16f4SPavel Dovgalyuk "Coreaudio and floating point samples are not supported by replay yet"); 2803d4d16f4SPavel Dovgalyuk abort(); 2813d4d16f4SPavel Dovgalyuk #else 2823d4d16f4SPavel Dovgalyuk *left = sample->l; 2833d4d16f4SPavel Dovgalyuk *right = sample->r; 2843d4d16f4SPavel Dovgalyuk #endif 2853d4d16f4SPavel Dovgalyuk } 2863d4d16f4SPavel Dovgalyuk 2873d4d16f4SPavel Dovgalyuk void audio_sample_from_uint64(void *samples, int pos, 2883d4d16f4SPavel Dovgalyuk uint64_t left, uint64_t right) 2893d4d16f4SPavel Dovgalyuk { 2903d4d16f4SPavel Dovgalyuk struct st_sample *sample = samples; 2913d4d16f4SPavel Dovgalyuk sample += pos; 2923d4d16f4SPavel Dovgalyuk #ifdef FLOAT_MIXENG 2933d4d16f4SPavel Dovgalyuk error_report( 2943d4d16f4SPavel Dovgalyuk "Coreaudio and floating point samples are not supported by replay yet"); 2953d4d16f4SPavel Dovgalyuk abort(); 2963d4d16f4SPavel Dovgalyuk #else 2973d4d16f4SPavel Dovgalyuk sample->l = left; 2983d4d16f4SPavel Dovgalyuk sample->r = right; 2993d4d16f4SPavel Dovgalyuk #endif 3003d4d16f4SPavel Dovgalyuk } 3013d4d16f4SPavel Dovgalyuk 30285571bc7Sbellard /* 30385571bc7Sbellard * August 21, 1998 30485571bc7Sbellard * Copyright 1998 Fabrice Bellard. 30585571bc7Sbellard * 306cb8d4c8fSStefan Weil * [Rewrote completely the code of Lance Norskog And Sundry 30785571bc7Sbellard * Contributors with a more efficient algorithm.] 30885571bc7Sbellard * 30985571bc7Sbellard * This source code is freely redistributable and may be used for 31085571bc7Sbellard * any purpose. This copyright notice must be maintained. 31185571bc7Sbellard * Lance Norskog And Sundry Contributors are not responsible for 31285571bc7Sbellard * the consequences of using this software. 31385571bc7Sbellard */ 31485571bc7Sbellard 31585571bc7Sbellard /* 31685571bc7Sbellard * Sound Tools rate change effect file. 31785571bc7Sbellard */ 31885571bc7Sbellard /* 31985571bc7Sbellard * Linear Interpolation. 32085571bc7Sbellard * 32185571bc7Sbellard * The use of fractional increment allows us to use no buffer. It 32285571bc7Sbellard * avoid the problems at the end of the buffer we had with the old 32385571bc7Sbellard * method which stored a possibly big buffer of size 32485571bc7Sbellard * lcm(in_rate,out_rate). 32585571bc7Sbellard * 32685571bc7Sbellard * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If 32785571bc7Sbellard * the input & output frequencies are equal, a delay of one sample is 32885571bc7Sbellard * introduced. Limited to processing 32-bit count worth of samples. 32985571bc7Sbellard * 33085571bc7Sbellard * 1 << FRAC_BITS evaluating to zero in several places. Changed with 33185571bc7Sbellard * an (unsigned long) cast to make it safe. MarkMLl 2/1/99 33285571bc7Sbellard */ 33385571bc7Sbellard 33485571bc7Sbellard /* Private data */ 335c0fe3827Sbellard struct rate { 33685571bc7Sbellard uint64_t opos; 33785571bc7Sbellard uint64_t opos_inc; 33885571bc7Sbellard uint32_t ipos; /* position in the input stream (integer) */ 3391ea879e5Smalc struct st_sample ilast; /* last sample in the input stream */ 340c0fe3827Sbellard }; 34185571bc7Sbellard 34285571bc7Sbellard /* 34385571bc7Sbellard * Prepare processing. 34485571bc7Sbellard */ 34585571bc7Sbellard void *st_rate_start (int inrate, int outrate) 34685571bc7Sbellard { 347*470bcabdSAlistair Francis struct rate *rate = audio_calloc(__func__, 1, sizeof(*rate)); 34885571bc7Sbellard 34985571bc7Sbellard if (!rate) { 350e7cad338Sbellard dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate)); 3511d14ffa9Sbellard return NULL; 35285571bc7Sbellard } 35385571bc7Sbellard 35485571bc7Sbellard rate->opos = 0; 35585571bc7Sbellard 35685571bc7Sbellard /* increment */ 3571d14ffa9Sbellard rate->opos_inc = ((uint64_t) inrate << 32) / outrate; 35885571bc7Sbellard 35985571bc7Sbellard rate->ipos = 0; 36085571bc7Sbellard rate->ilast.l = 0; 36185571bc7Sbellard rate->ilast.r = 0; 36285571bc7Sbellard return rate; 36385571bc7Sbellard } 36485571bc7Sbellard 3651d14ffa9Sbellard #define NAME st_rate_flow_mix 3661d14ffa9Sbellard #define OP(a, b) a += b 3671d14ffa9Sbellard #include "rate_template.h" 36885571bc7Sbellard 3691d14ffa9Sbellard #define NAME st_rate_flow 3701d14ffa9Sbellard #define OP(a, b) a = b 3711d14ffa9Sbellard #include "rate_template.h" 37285571bc7Sbellard 37385571bc7Sbellard void st_rate_stop (void *opaque) 37485571bc7Sbellard { 3757267c094SAnthony Liguori g_free (opaque); 37685571bc7Sbellard } 3771d14ffa9Sbellard 3781ea879e5Smalc void mixeng_clear (struct st_sample *buf, int len) 3791d14ffa9Sbellard { 3801ea879e5Smalc memset (buf, 0, len * sizeof (struct st_sample)); 3811d14ffa9Sbellard } 38200e07679SMichael Walle 38300e07679SMichael Walle void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol) 38400e07679SMichael Walle { 38500e07679SMichael Walle if (vol->mute) { 38600e07679SMichael Walle mixeng_clear (buf, len); 38700e07679SMichael Walle return; 38800e07679SMichael Walle } 38900e07679SMichael Walle 39000e07679SMichael Walle while (len--) { 39100e07679SMichael Walle #ifdef FLOAT_MIXENG 39200e07679SMichael Walle buf->l = buf->l * vol->l; 39300e07679SMichael Walle buf->r = buf->r * vol->r; 39400e07679SMichael Walle #else 39500e07679SMichael Walle buf->l = (buf->l * vol->l) >> 32; 39600e07679SMichael Walle buf->r = (buf->r * vol->r) >> 32; 39700e07679SMichael Walle #endif 39800e07679SMichael Walle buf += 1; 39900e07679SMichael Walle } 40000e07679SMichael Walle } 401