/*
* 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 IN_T
+#undef BSIZE
+#undef ITYPE
+#undef SHIFT
-t_sample *mixeng_conv[2][2][2] = {
+/* 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_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
+ }
}
}
};
* 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.
*/
/*
*/
/* 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;
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)
+{
+ 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);
}