changeset 2874:11ef2164d90b

re-written format conversion using libSAD; please test this on Big Endian system
author Andrew O. Shadoura <bugzilla@tut.by>
date Thu, 07 Aug 2008 04:16:17 +0300
parents 31d6c44ffef2
children 9d06c6456f98
files src/filewriter/Makefile src/filewriter/convert.c src/filewriter/convert.h src/filewriter/filewriter.c src/filewriter/filewriter.h
diffstat 5 files changed, 91 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/src/filewriter/Makefile	Wed Jul 16 23:09:38 2008 +0300
+++ b/src/filewriter/Makefile	Thu Aug 07 04:16:17 2008 +0300
@@ -4,7 +4,8 @@
        wav.c		\
        mp3.c		\
        vorbis.c		\
-       flac.c
+       flac.c           \
+       convert.c
 
 include ../../buildsys.mk
 include ../../extra.mk
@@ -13,4 +14,4 @@
 
 CFLAGS += ${PLUGIN_CFLAGS}
 CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${GTK_CFLAGS}  ${MOWGLI_CFLAGS}  ${FILEWRITER_CFLAGS} ${OGG_VORBIS_CFLAGS} -I../..
-LIBS += ${GTK_LIBS} ${FILEWRITER_LIBS}
+LIBS += ${GTK_LIBS} ${FILEWRITER_LIBS} -lSAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/filewriter/convert.c	Thu Aug 07 04:16:17 2008 +0300
@@ -0,0 +1,64 @@
+#include "convert.h"
+
+static SAD_dither_t *sad_state = NULL;
+gpointer convert_output = NULL;
+static gsize convert_output_length = 0;
+static gint nch;
+static AFormat in_fmt;
+static AFormat out_fmt;
+
+gboolean convert_init(AFormat input_fmt, AFormat output_fmt, gint channels)
+{
+    gint ret;
+    SAD_buffer_format input_sad_fmt;
+    SAD_buffer_format output_sad_fmt;
+
+
+    input_sad_fmt.sample_format = aud_sadfmt_from_afmt(input_fmt);
+    if (input_sad_fmt.sample_format < 0) return FALSE;
+    input_sad_fmt.fracbits = FMT_FRACBITS(input_fmt);
+    input_sad_fmt.channels = channels;
+    input_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
+    input_sad_fmt.samplerate = 0;
+
+    output_sad_fmt.sample_format = aud_sadfmt_from_afmt(output_fmt);
+    if (output_sad_fmt.sample_format < 0) return FALSE;
+    output_sad_fmt.fracbits = FMT_FRACBITS(output_fmt);
+    output_sad_fmt.channels = channels;
+    output_sad_fmt.channels_order = SAD_CHORDER_INTERLEAVED;
+    output_sad_fmt.samplerate = 0;
+
+    sad_state = SAD_dither_init(&input_sad_fmt, &output_sad_fmt, &ret);
+    if (sad_state == NULL) {
+        AUDDBG("ditherer init failed\n");
+        return FALSE;
+    }
+
+    in_fmt = input_fmt;
+    out_fmt = output_fmt;
+    nch = channels;
+
+    SAD_dither_set_dither(sad_state, FALSE);
+    return TRUE;
+}
+
+gint convert_process(gpointer ptr, gint length)
+{
+    gint frames, len;
+    frames = length / nch / FMT_SIZEOF(in_fmt);
+    len = frames * nch * FMT_SIZEOF(out_fmt);
+    
+    if (convert_output == NULL || convert_output_length < len)
+    {
+        convert_output_length = len;
+        convert_output = aud_smart_realloc(convert_output, &convert_output_length);
+    }
+
+    SAD_dither_process_buffer(sad_state, ptr, convert_output, frames);
+    return len;
+}
+
+void convert_free(void)
+{
+    if (sad_state != NULL) {SAD_dither_free(sad_state); sad_state = NULL;}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/filewriter/convert.h	Thu Aug 07 04:16:17 2008 +0300
@@ -0,0 +1,14 @@
+#ifndef CONVERT_H
+#define CONVERT_H
+
+#include "filewriter.h"
+
+gpointer convert_output;
+
+gboolean convert_init(AFormat input_fmt, AFormat output_fmt, gint channels);
+
+gint convert_process(gpointer ptr, gint length);
+
+void convert_free(void);
+
+#endif
--- a/src/filewriter/filewriter.c	Wed Jul 16 23:09:38 2008 +0300
+++ b/src/filewriter/filewriter.c	Thu Aug 07 04:16:17 2008 +0300
@@ -22,6 +22,7 @@
 
 #include "filewriter.h"
 #include "plugins.h"
+#include "convert.h"
 
 struct format_info input;
 
@@ -261,77 +262,20 @@
     if (!output_file)
         return 0;
 
+    convert_init(fmt, plugin.format_required, nch);
+
     rv = (plugin.open)();
 
     return rv;
 }
 
-static void convert_buffer(gpointer buffer, gint length)
-{
-    gint i;
-
-    if (input.format == FMT_S8)
-    {
-        guint8 *ptr1 = buffer;
-        gint8 *ptr2 = buffer;
-
-        for (i = 0; i < length; i++)
-            *(ptr1++) = *(ptr2++) + 128;
-    }
-    if (input.format == FMT_S16_BE)
-    {
-        gint16 *ptr = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr++)
-            *ptr = GINT16_FROM_BE(*ptr);
-    }
-    if (input.format == FMT_S16_LE)
-    {
-        gint16 *ptr = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr++)
-            *ptr = GINT16_FROM_LE(*ptr);
-    }
-    if (input.format == FMT_U16_BE)
-    {
-        gint16 *ptr1 = buffer;
-        guint16 *ptr2 = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr2++)
-            *(ptr1++) = GUINT16_FROM_BE(*ptr2) - 32768;
-    }
-    if (input.format == FMT_U16_LE)
-    {
-        gint16 *ptr1 = buffer;
-        guint16 *ptr2 = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr2++)
-            *(ptr1++) = GUINT16_FROM_LE(*ptr2) - 32768;
-    }
-    if (input.format == FMT_U16_NE)
-    {
-        gint16 *ptr1 = buffer;
-        guint16 *ptr2 = buffer;
-
-        for (i = 0; i < length >> 1; i++, ptr2++)
-            *(ptr1++) = (*ptr2) - 32768;
-    }
-}
-
 static void file_write(void *ptr, gint length)
 {
-    if (input.format == FMT_S8 || input.format == FMT_U16_NE ||
-        input.format == FMT_U16_LE || input.format == FMT_U16_BE)
-        convert_buffer(ptr, length);
-#ifdef WORDS_BIGENDIAN
-    if (input.format == FMT_S16_LE)
-        convert_buffer(ptr, length);
-#else
-    if (input.format == FMT_S16_BE)
-        convert_buffer(ptr, length);
-#endif
+    int len;
 
-    plugin.write(ptr, length);
+    len = convert_process(ptr, length);
+
+    plugin.write(convert_output, len);
 }
 
 static gint file_write_output(void *ptr, gint length)
@@ -342,6 +286,7 @@
 static void file_close(void)
 {
     plugin.close();
+    convert_free();
 
     if (output_file)
     {
--- a/src/filewriter/filewriter.h	Wed Jul 16 23:09:38 2008 +0300
+++ b/src/filewriter/filewriter.h	Thu Aug 07 04:16:17 2008 +0300
@@ -37,6 +37,8 @@
 #include <audacious/util.h>
 #include <audacious/vfs.h>
 
+#include <libSAD/libSAD.h>
+
 struct format_info { 
     AFormat format;
     int frequency;