summaryrefslogtreecommitdiffstats
path: root/src/audio/mixeng.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio/mixeng.c')
-rw-r--r--src/audio/mixeng.c366
1 files changed, 366 insertions, 0 deletions
diff --git a/src/audio/mixeng.c b/src/audio/mixeng.c
new file mode 100644
index 0000000..0e4976f
--- /dev/null
+++ b/src/audio/mixeng.c
@@ -0,0 +1,366 @@
+/*
+ * 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-common.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 completly 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;
+ }
+}
OpenPOWER on IntegriCloud