stereo = 1; ...; output.channels = 2 
--- old/xmms-jackasyn-0.1/audio.c       2002-10-30 18:11:37.000000000 +0000
+++ xmms-jackasyn-0.1/audio.c   2005-01-26 23:04:56.000000000 +0000
@@ -38,6 +38,7 @@
 static gboolean realtime, select_works;
 
 static int (*jackxmms_convert_func)(void **data, int length);
+static int (*jackxmms_stereo_convert_func)(void **data, int length, int fmt);
 
 struct format_info {
        union {
@@ -295,6 +296,10 @@
        if (jackxmms_convert_func != NULL)
                length = jackxmms_convert_func(&data, length);
 
+       if (jackxmms_stereo_convert_func != NULL)
+               length = jackxmms_stereo_convert_func(&data, length,
+                                                output.format.oss);
+
        if (effect.frequency == output.frequency)
                output_bytes += write_all(fd, data, length);
        else
@@ -478,7 +483,7 @@
                close(fd);
        }
        g_free(device_name);
-       jackxmms_get_convert_buffer(0);
+       jackxmms_free_convert_buffer();
        wr_index = 0;
        rd_index = 0;
 }
@@ -611,9 +616,14 @@
                g_warning("SNDCTL_DSP_SETFMT ioctl failed: %s",
                          strerror(errno));
 
-       /* FIXME: Handle mono/stereo only soundcards */
-       stereo = output.channels - 1;
+       /* for jackasyn, force conversion to stereo mode */
+       stereo = 1;
        ioctl(fd, SNDCTL_DSP_STEREO, &stereo);
+       output.channels = 2;
+
+       jackxmms_stereo_convert_func = 
jackxmms_get_stereo_convert_func(output.channels,
+                                                             effect.channels);
+       
        if (ioctl(fd, SNDCTL_DSP_SPEED, &output.frequency) == -1)
                g_warning("SNDCTL_DSP_SPEED ioctl failed: %s", strerror(errno));
 
--- old/xmms-jackasyn-0.1/convert.c     2002-10-15 11:55:20.000000000 +0100
+++ xmms-jackasyn-0.1/convert.c 2005-01-23 13:13:57.000000000 +0000
@@ -18,19 +18,29 @@
 
 #include "jack.h"
 
-void* jackxmms_get_convert_buffer(size_t size)
+struct buffer {
+       void *buffer;
+       int size;
+} format_buffer, stereo_buffer;
+
+
+static void* jackxmms_get_convert_buffer(struct buffer *buffer, size_t size)
 {
-       static size_t length;
-       static void *buffer;
+       if (size > 0 && size <= buffer->size)
+               return buffer->buffer;
 
-       if (size > 0 && size <= length)
-               return buffer;
+       buffer->size = size;
+       buffer->buffer = g_realloc(buffer->buffer, size);
+       return buffer->buffer;
+}
 
-       length = size;
-       buffer = g_realloc(buffer, size);
-       return buffer;
+void jackxmms_free_convert_buffer(void)
+{
+       jackxmms_get_convert_buffer(&format_buffer, 0);
+       jackxmms_get_convert_buffer(&stereo_buffer, 0);
 }
 
+
 static int convert_swap_endian(void **data, int length)
 {
        guint16 *ptr = *data;
@@ -131,7 +141,7 @@
        guint8 *input = *data;
        guint16 *output;
        int i;
-       *data = jackxmms_get_convert_buffer(length * 2);
+       *data = jackxmms_get_convert_buffer(&format_buffer, length * 2);
        output = *data;
        for (i = 0; i < length; i++)
                *output++ = *input++ << 8;
@@ -144,7 +154,7 @@
        guint8 *input = *data;
        guint16 *output;
        int i;
-       *data = jackxmms_get_convert_buffer(length * 2);
+       *data = jackxmms_get_convert_buffer(&format_buffer, length * 2);
        output = *data;
        for (i = 0; i < length; i++)
                *output++ = (*input++ << 8) ^ (1 << 15);
@@ -158,7 +168,7 @@
        guint8 *input = *data;
        guint16 *output;
        int i;
-       *data = jackxmms_get_convert_buffer(length * 2);
+       *data = jackxmms_get_convert_buffer(&format_buffer, length * 2);
        output = *data;
        for (i = 0; i < length; i++)
                *output++ = *input++;
@@ -171,7 +181,7 @@
        guint8 *input = *data;
        guint16 *output;
        int i;
-       *data = jackxmms_get_convert_buffer(length * 2);
+       *data = jackxmms_get_convert_buffer(&format_buffer, length * 2);
        output = *data;
        for (i = 0; i < length; i++)
                *output++ = *input++ ^ (1 << 7);
@@ -284,3 +294,149 @@
                  "Input: %d; Output %d.", input, output);
        return NULL;
 }
+
+static int convert_mono_to_stereo(void **data, int length, int fmt)
+{
+       int i;
+       void *outbuf = jackxmms_get_convert_buffer(&stereo_buffer, length * 2);
+
+       if (fmt == AFMT_U8 || fmt ==  AFMT_S8)
+       {
+               guint8 *output = outbuf, *input = *data;
+               for (i = 0; i < length; i++)
+               {
+                       *output++ = *input;
+                       *output++ = *input;
+                       input++;
+               }
+       }
+       else 
+       {
+               guint16 *output = outbuf, *input = *data;
+               for (i = 0; i < length / 2; i++)
+               {
+                       *output++ = *input;
+                       *output++ = *input;
+                       input++;
+               }
+       }
+       *data = outbuf;
+
+       return length * 2;
+}
+
+static int convert_stereo_to_mono(void **data, int length, int fmt)
+{
+       int i;
+
+       switch (fmt)
+       {
+               case AFMT_U8:
+               {
+                       guint8 *output = *data, *input = *data;
+                       for (i = 0; i < length / 2; i++)
+                       {
+                               guint16 tmp;
+                               tmp = *input++;
+                               tmp += *input++;
+                               *output++ = tmp / 2;
+                       }
+               }
+               break;
+               case AFMT_S8:
+               {
+                       gint8 *output = *data, *input = *data;
+                       for (i = 0; i < length / 2; i++)
+                       {
+                               gint16 tmp;
+                               tmp = *input++;
+                               tmp += *input++;
+                               *output++ = tmp / 2;
+                       }
+               }
+               break;
+               case AFMT_U16_LE:
+               {
+                       guint16 *output = *data, *input = *data;
+                       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);
+                       }
+               }
+               break;
+               case AFMT_U16_BE:
+               {
+                       guint16 *output = *data, *input = *data;
+                       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);
+                       }
+               }
+               break;
+               case AFMT_S16_LE:
+               {
+                       gint16 *output = *data, *input = *data;
+                       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);
+                       }
+               }
+               break;
+               case AFMT_S16_BE:
+               {
+                       gint16 *output = *data, *input = *data;
+                       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);
+                       }
+               }
+               break;
+               default:
+                       g_error("unknown format");
+       }
+
+       return length / 2;
+}
+
+int (*jackxmms_get_stereo_convert_func(int output, int input))(void **, int, 
int)
+{
+       if (output == input)
+               return NULL;
+
+       if (input == 1 && output == 2)
+               return convert_mono_to_stereo;
+       if (input == 2 && output == 1)
+               return convert_stereo_to_mono;
+
+       g_warning("Input has %d channels, soundcard uses %d channels\n"
+                 "No conversion is available", input, output);
+       return NULL;
+}

Reply via email to