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