]> git.proxmox.com Git - qemu.git/blobdiff - audio/mixeng.c
Merge remote-tracking branch 'stefanha/block' into staging
[qemu.git] / audio / mixeng.c
index b0bb412c63894ec36bd0c340089f67c5d6f9bcd3..02a9d9fb92ba3bdc7c3ba587c77c5a48dda4d73d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * QEMU Mixing engine
  *
- * Copyright (c) 2004 Vassili Karpov (malc)
+ * 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
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "vl.h"
-//#define DEBUG_FP
-#include "audio/mixeng.h"
+#include "qemu-common.h"
+#include "audio.h"
 
-#define IN_T int8_t
-#define IN_MIN CHAR_MIN
-#define IN_MAX CHAR_MAX
+#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 IN_T
+#undef BSIZE
+#undef ITYPE
+#undef SHIFT
 
-#define IN_T uint8_t
+/* 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 IN_T
+#undef BSIZE
+#undef ITYPE
+#undef SHIFT
+
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
 
-#define IN_T int16_t
+/* 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 IN_T
+#undef BSIZE
+#undef ITYPE
+#undef SHIFT
 
-#define IN_T uint16_t
+/* 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 IN_T
+#undef BSIZE
+#undef ITYPE
+#undef SHIFT
 
-t_sample *mixeng_conv[2][2][2] = {
+t_sample *mixeng_conv[2][2][2][3] = {
     {
         {
-            conv_uint8_t_to_mono,
-            conv_uint16_t_to_mono
+            {
+                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_int8_t_to_mono,
-            conv_int16_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_uint8_t_to_stereo,
-            conv_uint16_t_to_stereo
+            {
+                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_int8_t_to_stereo,
-            conv_int16_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] = {
+f_sample *mixeng_clip[2][2][2][3] = {
     {
         {
-            clip_uint8_t_from_mono,
-            clip_uint16_t_from_mono
+            {
+                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_int8_t_from_mono,
-            clip_int16_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_uint8_t_from_stereo,
-            clip_uint16_t_from_stereo
+            {
+                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_int8_t_from_stereo,
-            clip_int16_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
+            }
         }
     }
 };
@@ -116,9 +273,9 @@ f_sample *mixeng_clip[2][2][2] = {
  * 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.  
+ * any purpose.  This copyright notice must be maintained.
+ * Lance Norskog And Sundry Contributors are not responsible for
+ * the consequences of using this software.
  */
 
 /*
@@ -141,36 +298,29 @@ f_sample *mixeng_clip[2][2][2] = {
  */
 
 /* Private data */
-typedef struct ratestuff {
+struct rate {
     uint64_t opos;
     uint64_t opos_inc;
     uint32_t ipos;              /* position in the input stream (integer) */
-    st_sample_t ilast;          /* last sample in the input stream */
-} *rate_t;
+    struct st_sample ilast;          /* last sample in the input stream */
+};
 
 /*
  * Prepare processing.
  */
 void *st_rate_start (int inrate, int outrate)
 {
-    rate_t rate = (rate_t) qemu_mallocz (sizeof (struct ratestuff));
+    struct rate *rate = audio_calloc (AUDIO_FUNC, 1, sizeof (*rate));
 
     if (!rate) {
-        exit (EXIT_FAILURE);
-    }
-
-    if (inrate == outrate) {
-        // exit (EXIT_FAILURE);
-    }
-
-    if (inrate >= 65535 || outrate >= 65535) {
-        // exit (EXIT_FAILURE);
+        dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate));
+        return NULL;
     }
 
     rate->opos = 0;
 
     /* increment */
-    rate->opos_inc = (inrate * ((int64_t) UINT_MAX)) / outrate;
+    rate->opos_inc = ((uint64_t) inrate << 32) / outrate;
 
     rate->ipos = 0;
     rate->ilast.l = 0;
@@ -178,78 +328,45 @@ void *st_rate_start (int inrate, int outrate)
     return rate;
 }
 
-/*
- * Processed signed long samples from ibuf to obuf.
- * Return number of samples processed.
- */
-void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
-                   int *isamp, int *osamp)
-{
-    rate_t rate = (rate_t) opaque;
-    st_sample_t *istart, *iend;
-    st_sample_t *ostart, *oend;
-    st_sample_t ilast, icur, out;
-    int64_t t;
+#define NAME st_rate_flow_mix
+#define OP(a, b) a += b
+#include "rate_template.h"
 
-    ilast = rate->ilast;
+#define NAME st_rate_flow
+#define OP(a, b) a = b
+#include "rate_template.h"
 
-    istart = ibuf;
-    iend = ibuf + *isamp;
+void st_rate_stop (void *opaque)
+{
+    g_free (opaque);
+}
 
-    ostart = obuf;
-    oend = obuf + *osamp;
+void mixeng_clear (struct st_sample *buf, int len)
+{
+    memset (buf, 0, len * sizeof (struct st_sample));
+}
 
-    if (rate->opos_inc == 1ULL << 32) {
-        int i, n = *isamp > *osamp ? *osamp : *isamp;
-        for (i = 0; i < n; i++) {
-            obuf[i].l += ibuf[i].r;
-            obuf[i].r += ibuf[i].r;
-        }
-        *isamp = n;
-        *osamp = n;
+void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol)
+{
+#ifdef CONFIG_MIXEMU
+    if (vol->mute) {
+        mixeng_clear (buf, len);
         return;
     }
 
-    while (obuf < oend) {
-
-        /* Safety catch to make sure we have input samples.  */
-        if (ibuf >= iend)
-            break;
-
-        /* read as many input samples so that ipos > opos */
-
-        while (rate->ipos <= (rate->opos >> 32)) {
-            ilast = *ibuf++;
-            rate->ipos++;
-            /* See if we finished the input buffer yet */
-            if (ibuf >= iend) goto the_end;
-        }
-
-        icur = *ibuf;
-
-        /* interpolate */
-        t = rate->opos & 0xffffffff;
-        out.l = (ilast.l * (INT_MAX - t) + icur.l * t) / INT_MAX;
-        out.r = (ilast.r * (INT_MAX - t) + icur.r * t) / INT_MAX;
-
-        /* output sample & increment position */
-#if 0
-        *obuf++ = out;
+    while (len--) {
+#ifdef FLOAT_MIXENG
+        buf->l = buf->l * vol->l;
+        buf->r = buf->r * vol->r;
 #else
-        obuf->l += out.l;
-        obuf->r += out.r;
-        obuf += 1;
+        buf->l = (buf->l * vol->l) >> 32;
+        buf->r = (buf->r * vol->r) >> 32;
 #endif
-        rate->opos += rate->opos_inc;
+        buf += 1;
     }
-
-the_end:
-    *isamp = ibuf - istart;
-    *osamp = obuf - ostart;
-    rate->ilast = ilast;
-}
-
-void st_rate_stop (void *opaque)
-{
-    qemu_free (opaque);
+#else
+    (void) buf;
+    (void) len;
+    (void) vol;
+#endif
 }