diff libaudacious/xconvert.c @ 0:cb178e5ad177 trunk

[svn] Import audacious source.
author nenolod
date Mon, 24 Oct 2005 03:06:47 -0700
parents
children 0a73d1faeb4e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libaudacious/xconvert.c	Mon Oct 24 03:06:47 2005 -0700
@@ -0,0 +1,762 @@
+/*
+ *  Copyright (C) 2001-2003  Haavard Kvaalen <havardk@xmms.org>
+ *
+ *  Licensed under GNU LGPL version 2.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <audacious/plugin.h>
+#include "xconvert.h"
+
+#define IS_BIG_ENDIAN  (G_BYTE_ORDER==G_BIG_ENDIAN)
+
+struct buffer {
+    void *buffer;
+    int size;
+};
+
+struct xmms_convert_buffers {
+    struct buffer format_buffer, stereo_buffer, freq_buffer;
+};
+
+struct xmms_convert_buffers *
+xmms_convert_buffers_new(void)
+{
+    return g_malloc0(sizeof(struct xmms_convert_buffers));
+}
+
+static void *
+convert_get_buffer(struct buffer *buffer, size_t size)
+{
+    if (size > 0 && size <= buffer->size)
+        return buffer->buffer;
+
+    buffer->size = size;
+    buffer->buffer = g_realloc(buffer->buffer, size);
+    return buffer->buffer;
+}
+
+void
+xmms_convert_buffers_free(struct xmms_convert_buffers *buf)
+{
+    convert_get_buffer(&buf->format_buffer, 0);
+    convert_get_buffer(&buf->stereo_buffer, 0);
+    convert_get_buffer(&buf->freq_buffer, 0);
+}
+
+void
+xmms_convert_buffers_destroy(struct xmms_convert_buffers *buf)
+{
+    if (!buf)
+        return;
+    xmms_convert_buffers_free(buf);
+    g_free(buf);
+}
+
+static int
+convert_swap_endian(struct xmms_convert_buffers *buf, void **data, int length)
+{
+    guint16 *ptr = *data;
+    int i;
+    for (i = 0; i < length; i += 2, ptr++)
+        *ptr = GUINT16_SWAP_LE_BE(*ptr);
+
+    return i;
+}
+
+static int
+convert_swap_sign_and_endian_to_native(struct
+                                       xmms_convert_buffers
+                                       *buf, void **data, int length)
+{
+    guint16 *ptr = *data;
+    int i;
+    for (i = 0; i < length; i += 2, ptr++)
+        *ptr = GUINT16_SWAP_LE_BE(*ptr) ^ 1 << 15;
+
+    return i;
+}
+
+static int
+convert_swap_sign_and_endian_to_alien(struct
+                                      xmms_convert_buffers *buf,
+                                      void **data, int length)
+{
+    guint16 *ptr = *data;
+    int i;
+    for (i = 0; i < length; i += 2, ptr++)
+        *ptr = GUINT16_SWAP_LE_BE(*ptr ^ 1 << 15);
+
+    return i;
+}
+
+static int
+convert_swap_sign16(struct xmms_convert_buffers *buf, void **data, int length)
+{
+    gint16 *ptr = *data;
+    int i;
+    for (i = 0; i < length; i += 2, ptr++)
+        *ptr ^= 1 << 15;
+
+    return i;
+}
+
+static int
+convert_swap_sign8(struct xmms_convert_buffers *buf, void **data, int length)
+{
+    gint8 *ptr = *data;
+    int i;
+    for (i = 0; i < length; i++)
+        *ptr++ ^= 1 << 7;
+
+    return i;
+}
+
+static int
+convert_to_8_native_endian(struct xmms_convert_buffers *buf,
+                           void **data, int length)
+{
+    gint8 *output = *data;
+    gint16 *input = *data;
+    int i;
+    for (i = 0; i < length / 2; i++)
+        *output++ = *input++ >> 8;
+
+    return i;
+}
+
+static int
+convert_to_8_native_endian_swap_sign(struct xmms_convert_buffers
+                                     *buf, void **data, int length)
+{
+    gint8 *output = *data;
+    gint16 *input = *data;
+    int i;
+    for (i = 0; i < length / 2; i++)
+        *output++ = (*input++ >> 8) ^ (1 << 7);
+
+    return i;
+}
+
+
+static int
+convert_to_8_alien_endian(struct xmms_convert_buffers *buf,
+                          void **data, int length)
+{
+    gint8 *output = *data;
+    gint16 *input = *data;
+    int i;
+    for (i = 0; i < length / 2; i++)
+        *output++ = *input++ & 0xff;
+
+    return i;
+}
+
+static int
+convert_to_8_alien_endian_swap_sign(struct xmms_convert_buffers
+                                    *buf, void **data, int length)
+{
+    gint8 *output = *data;
+    gint16 *input = *data;
+    int i;
+    for (i = 0; i < length / 2; i++)
+        *output++ = (*input++ & 0xff) ^ (1 << 7);
+
+    return i;
+}
+
+static int
+convert_to_16_native_endian(struct xmms_convert_buffers *buf,
+                            void **data, int length)
+{
+    guint8 *input = *data;
+    guint16 *output;
+    int i;
+    *data = convert_get_buffer(&buf->format_buffer, length * 2);
+    output = *data;
+    for (i = 0; i < length; i++)
+        *output++ = *input++ << 8;
+
+    return i * 2;
+}
+
+static int
+convert_to_16_native_endian_swap_sign(struct
+                                      xmms_convert_buffers *buf,
+                                      void **data, int length)
+{
+    guint8 *input = *data;
+    guint16 *output;
+    int i;
+    *data = convert_get_buffer(&buf->format_buffer, length * 2);
+    output = *data;
+    for (i = 0; i < length; i++)
+        *output++ = (*input++ << 8) ^ (1 << 15);
+
+    return i * 2;
+}
+
+
+static int
+convert_to_16_alien_endian(struct xmms_convert_buffers *buf,
+                           void **data, int length)
+{
+    guint8 *input = *data;
+    guint16 *output;
+    int i;
+    *data = convert_get_buffer(&buf->format_buffer, length * 2);
+    output = *data;
+    for (i = 0; i < length; i++)
+        *output++ = *input++;
+
+    return i * 2;
+}
+
+static int
+convert_to_16_alien_endian_swap_sign(struct xmms_convert_buffers
+                                     *buf, void **data, int length)
+{
+    guint8 *input = *data;
+    guint16 *output;
+    int i;
+    *data = convert_get_buffer(&buf->format_buffer, length * 2);
+    output = *data;
+    for (i = 0; i < length; i++)
+        *output++ = *input++ ^ (1 << 7);
+
+    return i * 2;
+}
+
+static AFormat
+unnativize(AFormat fmt)
+{
+    if (fmt == FMT_S16_NE) {
+        if (IS_BIG_ENDIAN)
+            return FMT_S16_BE;
+        else
+            return FMT_S16_LE;
+    }
+    if (fmt == FMT_U16_NE) {
+        if (IS_BIG_ENDIAN)
+            return FMT_U16_BE;
+        else
+            return FMT_U16_LE;
+    }
+    return fmt;
+}
+
+convert_func_t
+xmms_convert_get_func(AFormat output, AFormat input)
+{
+    output = unnativize(output);
+    input = unnativize(input);
+
+    if (output == input)
+        return NULL;
+
+    if ((output == FMT_U16_BE && input == FMT_U16_LE) ||
+        (output == FMT_U16_LE && input == FMT_U16_BE) ||
+        (output == FMT_S16_BE && input == FMT_S16_LE) ||
+        (output == FMT_S16_LE && input == FMT_S16_BE))
+        return convert_swap_endian;
+
+    if ((output == FMT_U16_BE && input == FMT_S16_BE) ||
+        (output == FMT_U16_LE && input == FMT_S16_LE) ||
+        (output == FMT_S16_BE && input == FMT_U16_BE) ||
+        (output == FMT_S16_LE && input == FMT_U16_LE))
+        return convert_swap_sign16;
+
+    if ((IS_BIG_ENDIAN &&
+         ((output == FMT_U16_BE && input == FMT_S16_LE) ||
+          (output == FMT_S16_BE && input == FMT_U16_LE))) ||
+        (!IS_BIG_ENDIAN &&
+         ((output == FMT_U16_LE && input == FMT_S16_BE) ||
+          (output == FMT_S16_LE && input == FMT_U16_BE))))
+        return convert_swap_sign_and_endian_to_native;
+
+    if ((!IS_BIG_ENDIAN &&
+         ((output == FMT_U16_BE && input == FMT_S16_LE) ||
+          (output == FMT_S16_BE && input == FMT_U16_LE))) ||
+        (IS_BIG_ENDIAN &&
+         ((output == FMT_U16_LE && input == FMT_S16_BE) ||
+          (output == FMT_S16_LE && input == FMT_U16_BE))))
+        return convert_swap_sign_and_endian_to_alien;
+
+    if ((IS_BIG_ENDIAN &&
+         ((output == FMT_U8 && input == FMT_U16_BE) ||
+          (output == FMT_S8 && input == FMT_S16_BE))) ||
+        (!IS_BIG_ENDIAN &&
+         ((output == FMT_U8 && input == FMT_U16_LE) ||
+          (output == FMT_S8 && input == FMT_S16_LE))))
+        return convert_to_8_native_endian;
+
+    if ((IS_BIG_ENDIAN &&
+         ((output == FMT_U8 && input == FMT_S16_BE) ||
+          (output == FMT_S8 && input == FMT_U16_BE))) ||
+        (!IS_BIG_ENDIAN &&
+         ((output == FMT_U8 && input == FMT_S16_LE) ||
+          (output == FMT_S8 && input == FMT_U16_LE))))
+        return convert_to_8_native_endian_swap_sign;
+
+    if ((!IS_BIG_ENDIAN &&
+         ((output == FMT_U8 && input == FMT_U16_BE) ||
+          (output == FMT_S8 && input == FMT_S16_BE))) ||
+        (IS_BIG_ENDIAN &&
+         ((output == FMT_U8 && input == FMT_U16_LE) ||
+          (output == FMT_S8 && input == FMT_S16_LE))))
+        return convert_to_8_alien_endian;
+
+    if ((!IS_BIG_ENDIAN &&
+         ((output == FMT_U8 && input == FMT_S16_BE) ||
+          (output == FMT_S8 && input == FMT_U16_BE))) ||
+        (IS_BIG_ENDIAN &&
+         ((output == FMT_U8 && input == FMT_S16_LE) ||
+          (output == FMT_S8 && input == FMT_U16_LE))))
+        return convert_to_8_alien_endian_swap_sign;
+
+    if ((output == FMT_U8 && input == FMT_S8) ||
+        (output == FMT_S8 && input == FMT_U8))
+        return convert_swap_sign8;
+
+    if ((IS_BIG_ENDIAN &&
+         ((output == FMT_U16_BE && input == FMT_U8) ||
+          (output == FMT_S16_BE && input == FMT_S8))) ||
+        (!IS_BIG_ENDIAN &&
+         ((output == FMT_U16_LE && input == FMT_U8) ||
+          (output == FMT_S16_LE && input == FMT_S8))))
+        return convert_to_16_native_endian;
+
+    if ((IS_BIG_ENDIAN &&
+         ((output == FMT_U16_BE && input == FMT_S8) ||
+          (output == FMT_S16_BE && input == FMT_U8))) ||
+        (!IS_BIG_ENDIAN &&
+         ((output == FMT_U16_LE && input == FMT_S8) ||
+          (output == FMT_S16_LE && input == FMT_U8))))
+        return convert_to_16_native_endian_swap_sign;
+
+    if ((!IS_BIG_ENDIAN &&
+         ((output == FMT_U16_BE && input == FMT_U8) ||
+          (output == FMT_S16_BE && input == FMT_S8))) ||
+        (IS_BIG_ENDIAN &&
+         ((output == FMT_U16_LE && input == FMT_U8) ||
+          (output == FMT_S16_LE && input == FMT_S8))))
+        return convert_to_16_alien_endian;
+
+    if ((!IS_BIG_ENDIAN &&
+         ((output == FMT_U16_BE && input == FMT_S8) ||
+          (output == FMT_S16_BE && input == FMT_U8))) ||
+        (IS_BIG_ENDIAN &&
+         ((output == FMT_U16_LE && input == FMT_S8) ||
+          (output == FMT_S16_LE && input == FMT_U8))))
+        return convert_to_16_alien_endian_swap_sign;
+
+    g_warning("Translation needed, but not available.\n"
+              "Input: %d; Output %d.", input, output);
+    return NULL;
+}
+
+static int
+convert_mono_to_stereo(struct xmms_convert_buffers *buf,
+                       void **data, int length, int b16)
+{
+    int i;
+    void *outbuf = convert_get_buffer(&buf->stereo_buffer, length * 2);
+
+    if (b16) {
+        guint16 *output = outbuf, *input = *data;
+        for (i = 0; i < length / 2; i++) {
+            *output++ = *input;
+            *output++ = *input;
+            input++;
+        }
+    }
+    else {
+        guint8 *output = outbuf, *input = *data;
+        for (i = 0; i < length; i++) {
+            *output++ = *input;
+            *output++ = *input;
+            input++;
+        }
+    }
+    *data = outbuf;
+
+    return length * 2;
+}
+
+static int
+convert_mono_to_stereo_8(struct xmms_convert_buffers *buf,
+                         void **data, int length)
+{
+    return convert_mono_to_stereo(buf, data, length, FALSE);
+}
+
+static int
+convert_mono_to_stereo_16(struct xmms_convert_buffers *buf,
+                          void **data, int length)
+{
+    return convert_mono_to_stereo(buf, data, length, TRUE);
+}
+
+static int
+convert_stereo_to_mono_u8(struct xmms_convert_buffers *buf,
+                          void **data, int length)
+{
+    guint8 *output = *data, *input = *data;
+    int i;
+    for (i = 0; i < length / 2; i++) {
+        guint16 tmp;
+        tmp = *input++;
+        tmp += *input++;
+        *output++ = tmp / 2;
+    }
+    return length / 2;
+}
+static int
+convert_stereo_to_mono_s8(struct xmms_convert_buffers *buf,
+                          void **data, int length)
+{
+    gint8 *output = *data, *input = *data;
+    int i;
+    for (i = 0; i < length / 2; i++) {
+        gint16 tmp;
+        tmp = *input++;
+        tmp += *input++;
+        *output++ = tmp / 2;
+    }
+    return length / 2;
+}
+static int
+convert_stereo_to_mono_u16le(struct xmms_convert_buffers *buf,
+                             void **data, int length)
+{
+    guint16 *output = *data, *input = *data;
+    int i;
+    for (i = 0; i < length / 4; i++) {
+        guint32 tmp;
+        guint16 stmp;
+        tmp = GUINT16_FROM_LE(*input);
+        input++;
+        tmp += GUINT16_FROM_LE(*input);
+        input++;
+        stmp = tmp / 2;
+        *output++ = GUINT16_TO_LE(stmp);
+    }
+    return length / 2;
+}
+
+static int
+convert_stereo_to_mono_u16be(struct xmms_convert_buffers *buf,
+                             void **data, int length)
+{
+    guint16 *output = *data, *input = *data;
+    int i;
+    for (i = 0; i < length / 4; i++) {
+        guint32 tmp;
+        guint16 stmp;
+        tmp = GUINT16_FROM_BE(*input);
+        input++;
+        tmp += GUINT16_FROM_BE(*input);
+        input++;
+        stmp = tmp / 2;
+        *output++ = GUINT16_TO_BE(stmp);
+    }
+    return length / 2;
+}
+
+static int
+convert_stereo_to_mono_s16le(struct xmms_convert_buffers *buf,
+                             void **data, int length)
+{
+    gint16 *output = *data, *input = *data;
+    int i;
+    for (i = 0; i < length / 4; i++) {
+        gint32 tmp;
+        gint16 stmp;
+        tmp = GINT16_FROM_LE(*input);
+        input++;
+        tmp += GINT16_FROM_LE(*input);
+        input++;
+        stmp = tmp / 2;
+        *output++ = GINT16_TO_LE(stmp);
+    }
+    return length / 2;
+}
+
+static int
+convert_stereo_to_mono_s16be(struct xmms_convert_buffers *buf,
+                             void **data, int length)
+{
+    gint16 *output = *data, *input = *data;
+    int i;
+    for (i = 0; i < length / 4; i++) {
+        gint32 tmp;
+        gint16 stmp;
+        tmp = GINT16_FROM_BE(*input);
+        input++;
+        tmp += GINT16_FROM_BE(*input);
+        input++;
+        stmp = tmp / 2;
+        *output++ = GINT16_TO_BE(stmp);
+    }
+    return length / 2;
+}
+
+convert_channel_func_t
+xmms_convert_get_channel_func(AFormat fmt, int output, int input)
+{
+    fmt = unnativize(fmt);
+
+    if (output == input)
+        return NULL;
+
+    if (input == 1 && output == 2)
+        switch (fmt) {
+        case FMT_U8:
+        case FMT_S8:
+            return convert_mono_to_stereo_8;
+        case FMT_U16_LE:
+        case FMT_U16_BE:
+        case FMT_S16_LE:
+        case FMT_S16_BE:
+            return convert_mono_to_stereo_16;
+        default:
+            g_warning("Unknown format: %d" "No conversion available.", fmt);
+            return NULL;
+        }
+    if (input == 2 && output == 1)
+        switch (fmt) {
+        case FMT_U8:
+            return convert_stereo_to_mono_u8;
+        case FMT_S8:
+            return convert_stereo_to_mono_s8;
+        case FMT_U16_LE:
+            return convert_stereo_to_mono_u16le;
+        case FMT_U16_BE:
+            return convert_stereo_to_mono_u16be;
+        case FMT_S16_LE:
+            return convert_stereo_to_mono_s16le;
+        case FMT_S16_BE:
+            return convert_stereo_to_mono_s16be;
+        default:
+            g_warning("Unknown format: %d.  "
+                      "No conversion available.", fmt);
+            return NULL;
+
+        }
+
+    g_warning("Input has %d channels, soundcard uses %d channels\n"
+              "No conversion is available", input, output);
+    return NULL;
+}
+
+
+#define RESAMPLE_STEREO(sample_type, bswap)			\
+	const int shift = sizeof (sample_type);			\
+        int i, in_samples, out_samples, x, delta;		\
+	sample_type *inptr = *data, *outptr;			\
+	guint nlen = (((length >> shift) * ofreq) / ifreq);	\
+	void *nbuf;						\
+	if (nlen == 0)						\
+		return 0;						\
+	nlen <<= shift;						\
+	if (bswap)						\
+		convert_swap_endian(NULL, data, length);	\
+	nbuf = convert_get_buffer(&buf->freq_buffer, nlen);	\
+	outptr = nbuf;						\
+	in_samples = length >> shift;				\
+        out_samples = nlen >> shift;				\
+	delta = (in_samples << 12) / out_samples;		\
+	for (x = 0, i = 0; i < out_samples; i++)		\
+	{							\
+		int x1, frac;					\
+		x1 = (x >> 12) << 12;				\
+		frac = x - x1;					\
+		*outptr++ =					\
+			((inptr[(x1 >> 12) << 1] *		\
+			  ((1<<12) - frac) +			\
+			  inptr[((x1 >> 12) + 1) << 1] *	\
+			  frac) >> 12);				\
+		*outptr++ =					\
+			((inptr[((x1 >> 12) << 1) + 1] *	\
+			  ((1<<12) - frac) +			\
+			  inptr[(((x1 >> 12) + 1) << 1) + 1] *	\
+			  frac) >> 12);				\
+		x += delta;					\
+	}							\
+	if (bswap)						\
+		convert_swap_endian(NULL, &nbuf, nlen);		\
+	*data = nbuf;						\
+	return nlen;						\
+
+
+#define RESAMPLE_MONO(sample_type, bswap)			\
+	const int shift = sizeof (sample_type) - 1;		\
+        int i, x, delta, in_samples, out_samples;		\
+	sample_type *inptr = *data, *outptr;			\
+	guint nlen = (((length >> shift) * ofreq) / ifreq);	\
+	void *nbuf;						\
+	if (nlen == 0)						\
+		return 0;					\
+	nlen <<= shift;						\
+	if (bswap)						\
+		convert_swap_endian(NULL, data, length);	\
+	nbuf = convert_get_buffer(&buf->freq_buffer, nlen);	\
+	outptr = nbuf;						\
+	in_samples = length >> shift;				\
+        out_samples = nlen >> shift;				\
+	delta = ((length >> shift) << 12) / out_samples;	\
+	for (x = 0, i = 0; i < out_samples; i++)		\
+	{							\
+		int x1, frac;					\
+		x1 = (x >> 12) << 12;				\
+		frac = x - x1;					\
+		*outptr++ =					\
+			((inptr[x1 >> 12] * ((1<<12) - frac) +	\
+			  inptr[(x1 >> 12) + 1] * frac) >> 12);	\
+		x += delta;					\
+	}							\
+	if (bswap)						\
+		convert_swap_endian(NULL, &nbuf, nlen);		\
+	*data = nbuf;						\
+	return nlen;						\
+
+static int
+convert_resample_stereo_s16ne(struct xmms_convert_buffers *buf,
+                              void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_STEREO(gint16, FALSE);
+}
+
+static int
+convert_resample_stereo_s16ae(struct xmms_convert_buffers *buf,
+                              void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_STEREO(gint16, TRUE);
+}
+
+static int
+convert_resample_stereo_u16ne(struct xmms_convert_buffers *buf,
+                              void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_STEREO(guint16, FALSE);
+}
+
+static int
+convert_resample_stereo_u16ae(struct xmms_convert_buffers *buf,
+                              void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_STEREO(guint16, TRUE);
+}
+
+static int
+convert_resample_mono_s16ne(struct xmms_convert_buffers *buf,
+                            void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_MONO(gint16, FALSE);
+}
+
+static int
+convert_resample_mono_s16ae(struct xmms_convert_buffers *buf,
+                            void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_MONO(gint16, TRUE);
+}
+
+static int
+convert_resample_mono_u16ne(struct xmms_convert_buffers *buf,
+                            void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_MONO(guint16, FALSE);
+}
+
+static int
+convert_resample_mono_u16ae(struct xmms_convert_buffers *buf,
+                            void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_MONO(guint16, TRUE);
+}
+
+static int
+convert_resample_stereo_u8(struct xmms_convert_buffers *buf,
+                           void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_STEREO(guint8, FALSE);
+}
+
+static int
+convert_resample_mono_u8(struct xmms_convert_buffers *buf,
+                         void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_MONO(guint8, FALSE);
+}
+
+static int
+convert_resample_stereo_s8(struct xmms_convert_buffers *buf,
+                           void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_STEREO(gint8, FALSE);
+}
+
+static int
+convert_resample_mono_s8(struct xmms_convert_buffers *buf,
+                         void **data, int length, int ifreq, int ofreq)
+{
+    RESAMPLE_MONO(gint8, FALSE);
+}
+
+
+convert_freq_func_t
+xmms_convert_get_frequency_func(AFormat fmt, int channels)
+{
+    fmt = unnativize(fmt);
+    g_message("fmt %d, channels: %d", fmt, channels);
+
+    if (channels < 1 || channels > 2) {
+        g_warning("Unsupported number of channels: %d.  "
+                  "Resample function not available", channels);
+        return NULL;
+    }
+    if ((IS_BIG_ENDIAN && fmt == FMT_U16_BE) ||
+        (!IS_BIG_ENDIAN && fmt == FMT_U16_LE)) {
+        if (channels == 1)
+            return convert_resample_mono_u16ne;
+        else
+            return convert_resample_stereo_u16ne;
+    }
+    if ((IS_BIG_ENDIAN && fmt == FMT_S16_BE) ||
+        (!IS_BIG_ENDIAN && fmt == FMT_S16_LE)) {
+        if (channels == 1)
+            return convert_resample_mono_s16ne;
+        else
+            return convert_resample_stereo_s16ne;
+    }
+    if ((!IS_BIG_ENDIAN && fmt == FMT_U16_BE) ||
+        (IS_BIG_ENDIAN && fmt == FMT_U16_LE)) {
+        if (channels == 1)
+            return convert_resample_mono_u16ae;
+        else
+            return convert_resample_stereo_u16ae;
+    }
+    if ((!IS_BIG_ENDIAN && fmt == FMT_S16_BE) ||
+        (IS_BIG_ENDIAN && fmt == FMT_S16_LE)) {
+        if (channels == 1)
+            return convert_resample_mono_s16ae;
+        else
+            return convert_resample_stereo_s16ae;
+    }
+    if (fmt == FMT_U8) {
+        if (channels == 1)
+            return convert_resample_mono_u8;
+        else
+            return convert_resample_stereo_u8;
+    }
+    if (fmt == FMT_S8) {
+        if (channels == 1)
+            return convert_resample_mono_s8;
+        else
+            return convert_resample_stereo_s8;
+    }
+    g_warning("Resample function not available" "Format %d.", fmt);
+    return NULL;
+}