summaryrefslogtreecommitdiff
path: root/src/post/audio/stretch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/post/audio/stretch.c')
-rw-r--r--src/post/audio/stretch.c194
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;
}