text: /*
   * QEMU Mixing engine
   *
   * Copyright (c) 2004-2005 Vassili Karpov (malc)
   * Copyright (c) 1998 Fabrice Bellard
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */
  #include "qemu/osdep.h"
  #include "qemu-common.h"
  #include "qemu/bswap.h"
  #include "audio.h"
  
  #define AUDIO_CAP "mixeng"
  #include "audio_int.h"
  
  /* 8 bit */
  #define ENDIAN_CONVERSION natural
  #define ENDIAN_CONVERT(v) (v)
  
  /* Signed 8 bit */
  #define BSIZE 8
  #define ITYPE int
  #define IN_MIN SCHAR_MIN
  #define IN_MAX SCHAR_MAX
  #define SIGNED
  #define SHIFT 8
  #include "mixeng_template.h"
  #undef SIGNED
  #undef IN_MAX
  #undef IN_MIN
  #undef BSIZE
  #undef ITYPE
  #undef SHIFT
  
  /* Unsigned 8 bit */
  #define BSIZE 8
  #define ITYPE uint
  #define IN_MIN 0
  #define IN_MAX UCHAR_MAX
  #define SHIFT 8
  #include "mixeng_template.h"
  #undef IN_MAX
  #undef IN_MIN
  #undef BSIZE
  #undef ITYPE
  #undef SHIFT
  
  #undef ENDIAN_CONVERT
  #undef ENDIAN_CONVERSION
  
  /* Signed 16 bit */
  #define BSIZE 16
  #define ITYPE int
  #define IN_MIN SHRT_MIN
  #define IN_MAX SHRT_MAX
  #define SIGNED
  #define SHIFT 16
  #define ENDIAN_CONVERSION natural
  #define ENDIAN_CONVERT(v) (v)
  #include "mixeng_template.h"
  #undef ENDIAN_CONVERT
  #undef ENDIAN_CONVERSION
  #define ENDIAN_CONVERSION swap
  #define ENDIAN_CONVERT(v) bswap16 (v)
  #include "mixeng_template.h"
  #undef ENDIAN_CONVERT
  #undef ENDIAN_CONVERSION
  #undef SIGNED
  #undef IN_MAX
  #undef IN_MIN
  #undef BSIZE
  #undef ITYPE
  #undef SHIFT
  
  /* Unsigned 16 bit */
  #define BSIZE 16
  #define ITYPE uint
  #define IN_MIN 0
  #define IN_MAX USHRT_MAX
  #define SHIFT 16
  #define ENDIAN_CONVERSION natural
  #define ENDIAN_CONVERT(v) (v)
  #include "mixeng_template.h"
  #undef ENDIAN_CONVERT
  #undef ENDIAN_CONVERSION
  #define ENDIAN_CONVERSION swap
  #define ENDIAN_CONVERT(v) bswap16 (v)
  #include "mixeng_template.h"
  #undef ENDIAN_CONVERT
  #undef ENDIAN_CONVERSION
  #undef IN_MAX
  #undef IN_MIN
  #undef BSIZE
  #undef ITYPE
  #undef SHIFT
  
  /* Signed 32 bit */
  #define BSIZE 32
  #define ITYPE int
  #define IN_MIN INT32_MIN
  #define IN_MAX INT32_MAX
  #define SIGNED
  #define SHIFT 32
  #define ENDIAN_CONVERSION natural
  #define ENDIAN_CONVERT(v) (v)
  #include "mixeng_template.h"
  #undef ENDIAN_CONVERT
  #undef ENDIAN_CONVERSION
  #define ENDIAN_CONVERSION swap
  #define ENDIAN_CONVERT(v) bswap32 (v)
  #include "mixeng_template.h"
  #undef ENDIAN_CONVERT
  #undef ENDIAN_CONVERSION
  #undef SIGNED
  #undef IN_MAX
  #undef IN_MIN
  #undef BSIZE
  #undef ITYPE
  #undef SHIFT
  
  /* Unsigned 32 bit */
  #define BSIZE 32
  #define ITYPE uint
  #define IN_MIN 0
  #define IN_MAX UINT32_MAX
  #define SHIFT 32
  #define ENDIAN_CONVERSION natural
  #define ENDIAN_CONVERT(v) (v)
  #include "mixeng_template.h"
  #undef ENDIAN_CONVERT
  #undef ENDIAN_CONVERSION
  #define ENDIAN_CONVERSION swap
  #define ENDIAN_CONVERT(v) bswap32 (v)
  #include "mixeng_template.h"
  #undef ENDIAN_CONVERT
  #undef ENDIAN_CONVERSION
  #undef IN_MAX
  #undef IN_MIN
  #undef BSIZE
  #undef ITYPE
  #undef SHIFT
  
  t_sample *mixeng_conv[2][2][2][3] = {
      {
          {
              {
                  conv_natural_uint8_t_to_mono,
                  conv_natural_uint16_t_to_mono,
                  conv_natural_uint32_t_to_mono
              },
              {
                  conv_natural_uint8_t_to_mono,
                  conv_swap_uint16_t_to_mono,
                  conv_swap_uint32_t_to_mono,
              }
          },
          {
              {
                  conv_natural_int8_t_to_mono,
                  conv_natural_int16_t_to_mono,
                  conv_natural_int32_t_to_mono
              },
              {
                  conv_natural_int8_t_to_mono,
                  conv_swap_int16_t_to_mono,
                  conv_swap_int32_t_to_mono
              }
          }
      },
      {
          {
              {
                  conv_natural_uint8_t_to_stereo,
                  conv_natural_uint16_t_to_stereo,
                  conv_natural_uint32_t_to_stereo
              },
              {
                  conv_natural_uint8_t_to_stereo,
                  conv_swap_uint16_t_to_stereo,
                  conv_swap_uint32_t_to_stereo
              }
          },
          {
              {
                  conv_natural_int8_t_to_stereo,
                  conv_natural_int16_t_to_stereo,
                  conv_natural_int32_t_to_stereo
              },
              {
                  conv_natural_int8_t_to_stereo,
                  conv_swap_int16_t_to_stereo,
                  conv_swap_int32_t_to_stereo,
              }
          }
      }
  };
  
  f_sample *mixeng_clip[2][2][2][3] = {
      {
          {
              {
                  clip_natural_uint8_t_from_mono,
                  clip_natural_uint16_t_from_mono,
                  clip_natural_uint32_t_from_mono
              },
              {
                  clip_natural_uint8_t_from_mono,
                  clip_swap_uint16_t_from_mono,
                  clip_swap_uint32_t_from_mono
              }
          },
          {
              {
                  clip_natural_int8_t_from_mono,
                  clip_natural_int16_t_from_mono,
                  clip_natural_int32_t_from_mono
              },
              {
                  clip_natural_int8_t_from_mono,
                  clip_swap_int16_t_from_mono,
                  clip_swap_int32_t_from_mono
              }
          }
      },
      {
          {
              {
                  clip_natural_uint8_t_from_stereo,
                  clip_natural_uint16_t_from_stereo,
                  clip_natural_uint32_t_from_stereo
              },
              {
                  clip_natural_uint8_t_from_stereo,
                  clip_swap_uint16_t_from_stereo,
                  clip_swap_uint32_t_from_stereo
              }
          },
          {
              {
                  clip_natural_int8_t_from_stereo,
                  clip_natural_int16_t_from_stereo,
                  clip_natural_int32_t_from_stereo
              },
              {
                  clip_natural_int8_t_from_stereo,
                  clip_swap_int16_t_from_stereo,
                  clip_swap_int32_t_from_stereo
              }
          }
      }
  };
  
  /*
   * August 21, 1998
   * Copyright 1998 Fabrice Bellard.
   *
   * [Rewrote completely the code of Lance Norskog And Sundry
   * Contributors with a more efficient algorithm.]
   *
   * This source code is freely redistributable and may be used for
   * any purpose.  This copyright notice must be maintained.
   * Lance Norskog And Sundry Contributors are not responsible for
   * the consequences of using this software.
   */
  
  /*
   * Sound Tools rate change effect file.
   */
  /*
   * Linear Interpolation.
   *
   * The use of fractional increment allows us to use no buffer. It
   * avoid the problems at the end of the buffer we had with the old
   * method which stored a possibly big buffer of size
   * lcm(in_rate,out_rate).
   *
   * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
   * the input & output frequencies are equal, a delay of one sample is
   * introduced.  Limited to processing 32-bit count worth of samples.
   *
   * 1 << FRAC_BITS evaluating to zero in several places.  Changed with
   * an (unsigned long) cast to make it safe.  MarkMLl 2/1/99
   */
  
  /* Private data */
  struct rate {
      uint64_t opos;
      uint64_t opos_inc;
      uint32_t ipos;              /* position in the input stream (integer) */
      struct st_sample ilast;          /* last sample in the input stream */
  };
  
  /*
   * Prepare processing.
   */
  void *st_rate_start (int inrate, int outrate)
  {
      struct rate *rate = audio_calloc (AUDIO_FUNC, 1, sizeof (*rate));
  
      if (!rate) {
          dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate));
          return NULL;
      }
  
      rate->opos = 0;
  
      /* increment */
      rate->opos_inc = ((uint64_t) inrate << 32) / outrate;
  
      rate->ipos = 0;
      rate->ilast.l = 0;
      rate->ilast.r = 0;
      return rate;
  }
  
  #define NAME st_rate_flow_mix
  #define OP(a, b) a += b
  #include "rate_template.h"
  
  #define NAME st_rate_flow
  #define OP(a, b) a = b
  #include "rate_template.h"
  
  void st_rate_stop (void *opaque)
  {
      g_free (opaque);
  }
  
  void mixeng_clear (struct st_sample *buf, int len)
  {
      memset (buf, 0, len * sizeof (struct st_sample));
  }
  
  void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol)
  {
      if (vol->mute) {
          mixeng_clear (buf, len);
          return;
      }
  
      while (len--) {
  #ifdef FLOAT_MIXENG
          buf->l = buf->l * vol->l;
          buf->r = buf->r * vol->r;
  #else
          buf->l = (buf->l * vol->l) >> 32;
          buf->r = (buf->r * vol->r) >> 32;
  #endif
          buf += 1;
      }
  }
  