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;
+}