From a3d8d5b4ec8d1b5d01c2079fdfdeb9c6cc41de3c Mon Sep 17 00:00:00 2001 From: James Courtier-Dutton Date: Sun, 16 May 2004 14:44:42 +0000 Subject: Plugin is now a XINE_POST_TYPE_AUDIO_FILTER. Some updates so that upmixing 8,16,24 and floats works. The output of the upmixer is currently 32bit floats, so it currently only works with alsa. New audio plugins could be added to change it back to 16bit before reaching audio out so that it works with OSS etc. We just need Frontend GUIs to catch up and support AUDIO_FILTER post plugins. CVS patchset: 6548 CVS date: 2004/05/16 14:44:42 --- src/post/audio/upmix.c | 100 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 32 deletions(-) diff --git a/src/post/audio/upmix.c b/src/post/audio/upmix.c index f0e40c83a..168411fd3 100644 --- a/src/post/audio/upmix.c +++ b/src/post/audio/upmix.c @@ -23,7 +23,7 @@ * process. It simply paints the screen a solid color and rotates through * colors on each iteration. * - * $Id: upmix.c,v 1.3 2004/05/16 02:56:35 jcdutton Exp $ + * $Id: upmix.c,v 1.4 2004/05/16 14:44:42 jcdutton Exp $ * */ @@ -158,9 +158,10 @@ static int upmix_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, this->ratio = (double)FOO_WIDTH/(double)FOO_HEIGHT; this->channels = _x_ao_mode2channels(mode); /* FIXME: Handle all desired output formats */ - if (capabilities & AO_CAP_MODE_5_1CHANNEL) { + if ((capabilities & AO_CAP_MODE_5_1CHANNEL) && (capabilities & AO_CAP_32BITS)) { this->channels_out=6; mode = AO_CAP_MODE_5_1CHANNEL; + bits = 32; /* Upmix to Floats */ } else { this->channels_out=2; } @@ -204,36 +205,74 @@ static void upmix_port_close(xine_audio_port_t *port_gen, xine_stream_t *stream _x_post_dec_usage(port); } -static int upmix_frames_2to51_16bit(uint8_t *dst8, uint8_t *src8, int num_frames, af_sub_t *sub) { - int16_t *dst=(int16_t *)dst8; - int16_t *src=(int16_t *)src8; - - int frame; - int bytes_per_sample=1; /* Actually int16 per sample here */ +static int upmix_frames_2to51_any_to_float(uint8_t *dst8, uint8_t *src8, int num_frames, int step_channel_in, af_sub_t *sub) { + float *dst=(float *)dst8; + int16_t *src16=(int16_t *)src8; + float *src_float=(float *)src8; int src_num_channels=2; int dst_num_channels=6; int src_frame; int dst_frame; + int32_t sample24; float sample; - int32_t sum; + float left; + float right; + float sum; + int frame; + int src_units_per_sample=1; + if (step_channel_in == 3) src_units_per_sample=step_channel_in; /* Special handling for 24 bit 3byte input */ for (frame=0;frame < num_frames; frame++) { - dst_frame=frame*dst_num_channels*bytes_per_sample; - src_frame=frame*src_num_channels*bytes_per_sample; - dst[dst_frame] = src[src_frame]; - dst[dst_frame+(1*bytes_per_sample)] = src[src_frame+(1*bytes_per_sample)]; + dst_frame=frame*dst_num_channels; + src_frame=frame*src_num_channels*src_units_per_sample; + switch (step_channel_in) { + case 1: + left = src8[src_frame]; + left = (left - 128 ) / 128; /* FIXME: Need to verify this is correct */ + right = src8[src_frame+1]; + right = (right - 128) / 128; + break; + case 2: + left = (1.0/SHRT_MAX)*((float)src16[src_frame]); + right = (1.0/SHRT_MAX)*((float)src16[src_frame+1]); + break; + case 3: +#ifdef WORDS_BIGENDIAN + sample24 = (src8[src_frame] << 24) | (src8[src_frame+1] << 16) | ( src8[src_frame+2] << 8); +#else + sample24 = (src8[src_frame] << 8) | (src8[src_frame+1] << 16) | ( src8[src_frame+2] << 24); +#endif + left = (1.0/INT32_MAX)*((float)sample24); +#ifdef WORDS_BIGENDIAN + sample24 = (src8[src_frame+3] << 24) | (src8[src_frame+4] << 16) | ( src8[src_frame+5] << 8); +#else + sample24 = (src8[src_frame+3] << 8) | (src8[src_frame+4] << 16) | ( src8[src_frame+5] << 24); +#endif + right = (1.0/INT32_MAX)*((float)sample24); + break; + case 4: + left = src_float[src_frame]; + right = src_float[src_frame+1]; + break; + default: + left = right = 0.0; + } + + dst[dst_frame] = left; + dst[dst_frame+1] = right; /* try a bit of dolby */ /* FIXME: Dobly surround is a bit more complicated than this, but this is a start. */ - dst[dst_frame+(2*bytes_per_sample)] = (src[src_frame] - src[src_frame+(1*bytes_per_sample)]) / 2; - dst[dst_frame+(3*bytes_per_sample)] = (src[src_frame] - src[src_frame+(1*bytes_per_sample)]) / 2; - sum = ((int32_t)src[src_frame] + (int32_t)src[src_frame+(1*bytes_per_sample)]) / 2; - dst[dst_frame+(4*bytes_per_sample)] = (int16_t)sum; + dst[dst_frame+2] = (left - right) / 2; + dst[dst_frame+3] = (left - right) / 2; + sum = (left + right) / 2; + dst[dst_frame+4] = sum; /* Create the LFE channel using a low pass filter */ /* filter feature ported from mplayer */ - sample = (1.0/SHRT_MAX)*((float)sum); + sample = sum; IIR(sample * sub->k, sub->w[0], sub->q[0], sample); IIR(sample , sub->w[1], sub->q[1], sample); - dst[dst_frame+(5*bytes_per_sample)] = (int16_t)(sample * SHRT_MAX); + dst[dst_frame+5] = sample; + } return frame; } @@ -243,15 +282,10 @@ static void upmix_port_put_buffer (xine_audio_port_t *port_gen, post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_upmix_t *this = (post_plugin_upmix_t *)port->post; - vo_frame_t *frame; - int16_t *data; - int8_t *data8; - int samples_used = 0; - int64_t pts = buf->vpts; - int i, j; int src_step_frame; int dst_step_frame; - int step_channel; + int step_channel_in; + int step_channel_out; uint8_t *data8src; uint8_t *data8dst; int num_bytes; @@ -270,13 +304,14 @@ static void upmix_port_put_buffer (xine_audio_port_t *port_gen, /* FIXME: The audio buffer should contain this info. * We should not have to get it from the open call. */ - this->buf->format.bits = port->bits; + this->buf->format.bits = 32; /* Upmix to floats */ this->buf->format.rate = port->rate; this->buf->format.mode = AO_CAP_MODE_5_1CHANNEL; _x_extra_info_merge( this->buf->extra_info, buf->extra_info); - step_channel = this->buf->format.bits>>3; - dst_step_frame = this->channels_out*step_channel; - src_step_frame = this->channels*step_channel; + step_channel_in = port->bits>>3; + step_channel_out = this->buf->format.bits>>3; + dst_step_frame = this->channels_out*step_channel_out; + src_step_frame = this->channels*step_channel_in; num_bytes=(buf->num_frames-num_frames_processed)*dst_step_frame; if (num_bytes > this->buf->mem_size) { num_bytes = this->buf->mem_size; @@ -285,7 +320,7 @@ static void upmix_port_put_buffer (xine_audio_port_t *port_gen, data8src=(int8_t*)buf->mem; data8src+=num_frames_processed*src_step_frame; data8dst=(int8_t*)this->buf->mem; - num_frames_done = upmix_frames_2to51_16bit(data8dst, data8src, num_frames, this->sub); + num_frames_done = upmix_frames_2to51_any_to_float(data8dst, data8src, num_frames, step_channel_in, this->sub); this->buf->num_frames = num_frames_done; num_frames_processed+= num_frames_done; /* pass data to original port */ @@ -387,7 +422,8 @@ static void *upmix_init_plugin(xine_t *xine, void *data) } /* plugin catalog information */ -post_info_t upmix_special_info = { XINE_POST_TYPE_AUDIO_VISUALIZATION }; +/* post_info_t upmix_special_info = { XINE_POST_TYPE_AUDIO_VISUALIZATION }; */ +post_info_t upmix_special_info = { XINE_POST_TYPE_AUDIO_FILTER }; plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ -- cgit v1.2.3