diff options
Diffstat (limited to 'src/post/audio/stretch.c')
-rw-r--r-- | src/post/audio/stretch.c | 194 |
1 files changed, 97 insertions, 97 deletions
diff --git a/src/post/audio/stretch.c b/src/post/audio/stretch.c index d4621a800..154202da4 100644 --- a/src/post/audio/stretch.c +++ b/src/post/audio/stretch.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -70,19 +70,19 @@ static void stretchscr_set_pivot (stretchscr_t *this) { struct timeval tv; int64_t pts; - double pts_calc; + double pts_calc; xine_monotonic_clock(&tv, NULL); pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc; -/* This next part introduces a one off inaccuracy - * to the scr due to rounding tv to pts. +/* This next part introduces a one off inaccuracy + * to the scr due to rounding tv to pts. */ this->cur_time.tv_sec=tv.tv_sec; this->cur_time.tv_usec=tv.tv_usec; - this->cur_pts=pts; + this->cur_pts=pts; return ; } @@ -94,7 +94,7 @@ static int stretchscr_set_speed (scr_plugin_t *scr, int speed) { stretchscr_set_pivot( this ); this->xine_speed = speed; - this->speed_factor = (double) speed * 90000.0 / XINE_FINE_SPEED_NORMAL / + this->speed_factor = (double) speed * 90000.0 / XINE_FINE_SPEED_NORMAL / (*this->stretch_factor); pthread_mutex_unlock (&this->lock); @@ -125,7 +125,7 @@ static void stretchscr_start (scr_plugin_t *scr, int64_t start_vpts) { this->cur_pts = start_vpts; pthread_mutex_unlock (&this->lock); - + stretchscr_set_speed (&this->scr, XINE_FINE_SPEED_NORMAL); } @@ -134,16 +134,16 @@ static int64_t stretchscr_get_current (scr_plugin_t *scr) { struct timeval tv; int64_t pts; - double pts_calc; + double pts_calc; pthread_mutex_lock (&this->lock); xine_monotonic_clock(&tv, NULL); - + pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc; - + pthread_mutex_unlock (&this->lock); return pts; @@ -168,9 +168,9 @@ static stretchscr_t *XINE_MALLOC stretchscr_init (double *stretch_factor) { this->scr.start = stretchscr_start; this->scr.get_current = stretchscr_get_current; this->scr.exit = stretchscr_exit; - + pthread_mutex_init (&this->lock, NULL); - + this->stretch_factor = stretch_factor; stretchscr_set_speed (&this->scr, XINE_SPEED_PAUSE); @@ -202,21 +202,21 @@ typedef struct stretch_parameters_s { START_PARAM_DESCR( stretch_parameters_t ) PARAM_ITEM( POST_PARAM_TYPE_BOOL, preserve_pitch, NULL, 0, 1, 0, "Preserve pitch" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, factor, NULL, 0.5, 1.5, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, factor, NULL, 0.5, 1.5, 0, "Time stretch factor (<1.0 shorten duration)" ) END_PARAM_DESCR( param_descr ) /* plugin structure */ struct post_plugin_stretch_s { post_plugin_t post; - + stretchscr_t* scr; /* private data */ stretch_parameters_t params; xine_post_in_t params_input; int params_changed; - + int channels; int bytes_per_frame; @@ -228,9 +228,9 @@ struct post_plugin_stretch_s { int num_frames; /* current # of frames on audiofrag */ int16_t last_sample[RESAMPLE_MAX_CHANNELS]; - + int64_t pts; /* pts for audiofrag */ - + pthread_mutex_t lock; }; @@ -290,16 +290,16 @@ static int stretch_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_stretch_t *this = (post_plugin_stretch_t *)port->post; int64_t time; - + _x_post_rewire(&this->post); _x_post_inc_usage(port); - + port->stream = stream; port->bits = bits; port->rate = rate; port->mode = mode; - - /* register our own scr provider */ + + /* register our own scr provider */ time = port->stream->xine->clock->get_current_time(port->stream->xine->clock); this->scr = stretchscr_init(&this->params.factor); this->scr->scr.start(&this->scr->scr, time); @@ -307,7 +307,7 @@ static int stretch_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, /* force updating on stretch_port_put_buffer */ this->params_changed = 1; - + return (port->original_port->open) (port->original_port, stream, bits, rate, mode); } @@ -320,34 +320,34 @@ static void stretch_port_close(xine_audio_port_t *port_gen, xine_stream_t *strea port->stream->xine->clock->unregister_scr(port->stream->xine->clock, &this->scr->scr); this->scr->scr.exit(&this->scr->scr); } - + if(this->audiofrag) { free(this->audiofrag); this->audiofrag = NULL; } - + if(this->outfrag) { free(this->outfrag); this->outfrag = NULL; } - + if(this->w) { free(this->w); this->w = NULL; } - + port->stream = NULL; port->original_port->close(port->original_port, stream ); - + _x_post_dec_usage(port); } -static void stretch_process_fragment( post_audio_port_t *port, +static void stretch_process_fragment( post_audio_port_t *port, xine_stream_t *stream, extra_info_t *extra_info ) { post_plugin_stretch_t *this = (post_plugin_stretch_t *)port->post; - + audio_buffer_t *outbuf; int16_t *data_out = this->outfrag; int num_frames_in = this->num_frames; @@ -374,52 +374,52 @@ static void stretch_process_fragment( post_audio_port_t *port, * input chunk has two halves, A and B. * output chunk is composed as follow: * - some frames copied directly from A - * - some frames copied from A merged with frames from B + * - some frames copied from A merged with frames from B * weighted by an increasing factor (0 -> 1.0) * - frames from A weighted by a decreasing factor (1.0 -> 0) * merged with frames copied from B * - some frames copied directly from B */ - + int merge_frames = num_frames_in - num_frames_out; int copy_frames; int16_t *src = this->audiofrag; int16_t *dst = this->outfrag; int i, j; - + if( merge_frames > num_frames_out ) merge_frames = num_frames_out; copy_frames = num_frames_out - merge_frames; - + memcpy(dst, src, copy_frames/2 * this->bytes_per_frame); dst += copy_frames/2 * this->channels; src += copy_frames/2 * this->channels; - + for( i = 0; i < merge_frames/2; i++ ) { for( j = 0; j < this->channels; j++, src++, dst++ ) { - + int32_t s = (int32_t) ((_ftype_t) src[0] + src[merge_frames * this->channels] * this->w[i]); *dst = CLIP_INT16(s); } } - + for( ; i < merge_frames; i++ ) { for( j = 0; j < this->channels; j++, src++, dst++ ) { - + int32_t s = (int32_t) ((_ftype_t) src[0] * this->w[i] + src[merge_frames * this->channels]); *dst = CLIP_INT16(s); } } - + src += merge_frames * this->channels; - + memcpy(dst, src, (copy_frames - copy_frames/2) * this->bytes_per_frame); - + } else { /* * time expansion strategy @@ -427,13 +427,13 @@ static void stretch_process_fragment( post_audio_port_t *port, * output chunk is composed of two versions of the * input chunk: * - first part copied directly from input, and then - * merged with the second (delayed) part using a + * merged with the second (delayed) part using a * decreasing factor (1.0 -> 0) * - the delayed version of the input is merged with - * an increasing factor (0 -> 1.0) and then (when - * factor reaches 1.0) just copied until the end. + * an increasing factor (0 -> 1.0) and then (when + * factor reaches 1.0) just copied until the end. */ - + int merge_frames = num_frames_out - num_frames_in; int copy_frames = num_frames_out - merge_frames; int16_t *src1 = this->audiofrag; @@ -449,67 +449,67 @@ static void stretch_process_fragment( post_audio_port_t *port, for( i = 0; i < merge_frames/2; i++ ) { for( j = 0; j < this->channels; j++, src1++, src2++, dst++ ) { - + int32_t s = (int32_t) ((_ftype_t) *src1 + *src2 * this->w[i]); *dst = CLIP_INT16(s); } } - + for( ; i < merge_frames; i++ ) { for( j = 0; j < this->channels; j++, src1++, src2++, dst++ ) { - + int32_t s = (int32_t) ((_ftype_t) *src1 * this->w[i] + *src2); *dst = CLIP_INT16(s); } } - + memcpy(dst, src2, (copy_frames - copy_frames/2) * this->bytes_per_frame); } } - + /* copy processed fragment into multiple audio buffers, if needed */ while( num_frames_out ) { - outbuf = port->original_port->get_buffer(port->original_port); - + outbuf = port->original_port->get_buffer(port->original_port); + outbuf->num_frames = outbuf->mem_size / this->bytes_per_frame; if( outbuf->num_frames > num_frames_out ) outbuf->num_frames = num_frames_out; - - memcpy( outbuf->mem, data_out, + + memcpy( outbuf->mem, data_out, outbuf->num_frames * this->bytes_per_frame ); num_frames_out -= outbuf->num_frames; data_out = (uint16_t *)((uint8_t *)data_out + outbuf->num_frames * this->bytes_per_frame); - + outbuf->vpts = this->pts; this->pts = 0; outbuf->stream = stream; outbuf->format.bits = port->bits; outbuf->format.rate = port->rate; outbuf->format.mode = port->mode; - + _x_extra_info_merge( outbuf->extra_info, extra_info ); - - port->original_port->put_buffer(port->original_port, outbuf, stream ); + + port->original_port->put_buffer(port->original_port, outbuf, stream ); } - + this->num_frames = 0; } -static void stretch_port_put_buffer (xine_audio_port_t *port_gen, +static void stretch_port_put_buffer (xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream) { - + post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_stretch_t *this = (post_plugin_stretch_t *)port->post; int16_t *data_in; - + pthread_mutex_lock (&this->lock); - + if( this->params_changed ) { int64_t audio_step; @@ -517,40 +517,40 @@ static void stretch_port_put_buffer (xine_audio_port_t *port_gen, /* output whatever we have before changing parameters */ stretch_process_fragment( port, stream, buf->extra_info ); } - + this->channels = _x_ao_mode2channels(port->mode); this->bytes_per_frame = port->bits / 8 * this->channels; - + audio_step = ((int64_t)90000 * (int64_t)32768) / (int64_t)port->rate; audio_step = (int64_t) ((double)audio_step / this->params.factor); stream->metronom->set_audio_rate(stream->metronom, audio_step); stretchscr_set_speed(&this->scr->scr, this->scr->xine_speed); - + if(this->audiofrag) { free(this->audiofrag); this->audiofrag = NULL; } - + if(this->outfrag) { free(this->outfrag); this->outfrag = NULL; } - + if(this->w) { free(this->w); this->w = NULL; } - + this->frames_per_frag = port->rate * AUDIO_FRAGMENT; this->frames_per_outfrag = (int) ((double)this->params.factor * this->frames_per_frag); if( this->frames_per_frag != this->frames_per_outfrag ) { int wsize; - - this->audiofrag = malloc( this->frames_per_frag * this->bytes_per_frame ); - this->outfrag = malloc( this->frames_per_outfrag * this->bytes_per_frame ); - + + this->audiofrag = malloc( this->frames_per_frag * this->bytes_per_frame ); + this->outfrag = malloc( this->frames_per_outfrag * this->bytes_per_frame ); + if( this->frames_per_frag > this->frames_per_outfrag ) wsize = this->frames_per_frag - this->frames_per_outfrag; else @@ -559,41 +559,41 @@ static void stretch_port_put_buffer (xine_audio_port_t *port_gen, this->w = (_ftype_t*) malloc( wsize * sizeof(_ftype_t) ); triang(wsize, this->w); } - + this->num_frames = 0; this->pts = 0; - + this->params_changed = 0; } - + pthread_mutex_unlock (&this->lock); /* just pass data through if we have nothing to do */ if( this->frames_per_frag == this->frames_per_outfrag || /* FIXME: we only handle 1 or 2 channels, 16 bits for now */ - (this->channels != 1 && this->channels != 2) || + (this->channels != 1 && this->channels != 2) || port->bits != 16 ) { - - port->original_port->put_buffer(port->original_port, buf, stream ); - + + port->original_port->put_buffer(port->original_port, buf, stream ); + return; } - + /* update pts for our current audio fragment */ if( buf->vpts ) this->pts = buf->vpts - (this->num_frames * 90000 / port->rate); - + data_in = buf->mem; while( buf->num_frames ) { int frames_to_copy = this->frames_per_frag - this->num_frames; - + if( frames_to_copy > buf->num_frames ) frames_to_copy = buf->num_frames; /* copy up to one fragment from input buf to our buffer */ memcpy( (uint8_t *)this->audiofrag + this->num_frames * this->bytes_per_frame, data_in, frames_to_copy * this->bytes_per_frame ); - + data_in = (uint16_t *)((uint8_t *)data_in + frames_to_copy * this->bytes_per_frame); this->num_frames += frames_to_copy; buf->num_frames -= frames_to_copy; @@ -603,10 +603,10 @@ static void stretch_port_put_buffer (xine_audio_port_t *port_gen, stretch_process_fragment( port, stream, buf->extra_info ); } } - + buf->num_frames=0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */ - port->original_port->put_buffer(port->original_port, buf, stream ); - + port->original_port->put_buffer(port->original_port, buf, stream ); + return; } @@ -630,21 +630,21 @@ static post_plugin_t *stretch_open_plugin(post_class_t *class_gen, int inputs, xine_post_in_t *input_api; post_audio_port_t *port; stretch_parameters_t init_params; - + if (!this || !audio_target || !audio_target[0] ) { free(this); return NULL; } - + _x_post_init(&this->post, 1, 0); init_params.preserve_pitch = 1; init_params.factor = 0.80; - + pthread_mutex_init (&this->lock, NULL); set_parameters ((xine_post_t *)&this->post, &init_params); - + port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output); port->new_port.open = stretch_port_open; port->new_port.close = stretch_port_close; @@ -682,16 +682,16 @@ static void stretch_class_dispose(post_class_t *class_gen) void *stretch_init_plugin(xine_t *xine, void *data) { post_class_stretch_t *class = (post_class_stretch_t *)malloc(sizeof(post_class_stretch_t)); - + if (!class) return NULL; - + class->post_class.open_plugin = stretch_open_plugin; class->post_class.get_identifier = stretch_get_identifier; class->post_class.get_description = stretch_get_description; class->post_class.dispose = stretch_class_dispose; - + class->xine = xine; - + return class; } |