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