stretch.c

来自「linux下的MPEG1」· C语言 代码 · 共 697 行 · 第 1/2 页

C
697
字号
/* * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA * * Time stretch by a given factor, optionally preserving pitch * * $Id: stretch.c,v 1.8 2006/01/27 07:46:12 tmattern Exp $ * */#include <stdio.h>#include "xine_internal.h"#include "xineutils.h"#include "post.h"#include "dsp.h"#include "resample.h"#include "audio_filters.h"#define AUDIO_FRAGMENT  120/1000  /* ms of audio */#define CLIP_INT16(s) ((s) < INT16_MIN) ? INT16_MIN : \                      (((s) > INT16_MAX) ? INT16_MAX : (s))/* * *************************************************** * stretchable unix System Clock Reference * use stretch factor to calculate speed * *************************************************** */struct stretchscr_s {  scr_plugin_t     scr;  struct timeval   cur_time;  int64_t          cur_pts;  int              xine_speed;  double           speed_factor;  double           *stretch_factor;  pthread_mutex_t  lock;};typedef struct stretchscr_s stretchscr_t;static int stretchscr_get_priority (scr_plugin_t *scr) {  return 10; /* high priority */}/* Only call this when already mutex locked */static void stretchscr_set_pivot (stretchscr_t *this) {  struct   timeval tv;  int64_t  pts;  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->cur_time.tv_sec=tv.tv_sec;  this->cur_time.tv_usec=tv.tv_usec;  this->cur_pts=pts;   return ;}static int stretchscr_set_speed (scr_plugin_t *scr, int speed) {  stretchscr_t *this = (stretchscr_t*) scr;  pthread_mutex_lock (&this->lock);  stretchscr_set_pivot( this );  this->xine_speed   = speed;  this->speed_factor = (double) speed * 90000.0 / XINE_FINE_SPEED_NORMAL /                        (*this->stretch_factor);  pthread_mutex_unlock (&this->lock);  return speed;}static void stretchscr_adjust (scr_plugin_t *scr, int64_t vpts) {  stretchscr_t *this = (stretchscr_t*) scr;  struct   timeval tv;  pthread_mutex_lock (&this->lock);  xine_monotonic_clock(&tv, NULL);  this->cur_time.tv_sec=tv.tv_sec;  this->cur_time.tv_usec=tv.tv_usec;  this->cur_pts = vpts;  pthread_mutex_unlock (&this->lock);}static void stretchscr_start (scr_plugin_t *scr, int64_t start_vpts) {  stretchscr_t *this = (stretchscr_t*) scr;  pthread_mutex_lock (&this->lock);  xine_monotonic_clock(&this->cur_time, NULL);  this->cur_pts = start_vpts;  pthread_mutex_unlock (&this->lock);    stretchscr_set_speed (&this->scr, XINE_FINE_SPEED_NORMAL);}static int64_t stretchscr_get_current (scr_plugin_t *scr) {  stretchscr_t *this = (stretchscr_t*) scr;  struct   timeval tv;  int64_t pts;  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;}static void stretchscr_exit (scr_plugin_t *scr) {  stretchscr_t *this = (stretchscr_t*) scr;  pthread_mutex_destroy (&this->lock);  free(this);}static stretchscr_t* stretchscr_init (double *stretch_factor) {  stretchscr_t *this;  this = (stretchscr_t *) xine_xmalloc(sizeof(stretchscr_t));  this->scr.interface_version = 3;  this->scr.get_priority      = stretchscr_get_priority;  this->scr.set_fine_speed    = stretchscr_set_speed;  this->scr.adjust            = stretchscr_adjust;  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);  return this;}/*****************************************************/typedef struct post_plugin_stretch_s post_plugin_stretch_t;typedef struct post_class_stretch_s post_class_stretch_t;struct post_class_stretch_s {  post_class_t        post_class;  xine_t             *xine;};typedef struct stretch_parameters_s {  int preserve_pitch;  double factor;} stretch_parameters_t;/* * description of params struct */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,             "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;  int16_t             *audiofrag;         /* audio fragment to work on */  int16_t             *outfrag;           /* processed audio fragment  */  _ftype_t            *w;  int                  frames_per_frag;  int                  frames_per_outfrag;  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;};/************************************************************************** * stretch parameters functions *************************************************************************/static int set_parameters (xine_post_t *this_gen, void *param_gen) {  post_plugin_stretch_t *this = (post_plugin_stretch_t *)this_gen;  stretch_parameters_t *param = (stretch_parameters_t *)param_gen;  pthread_mutex_lock (&this->lock);  memcpy( &this->params, param, sizeof(stretch_parameters_t) );  this->params_changed = 1;  pthread_mutex_unlock (&this->lock);  return 1;}static int get_parameters (xine_post_t *this_gen, void *param_gen) {  post_plugin_stretch_t *this = (post_plugin_stretch_t *)this_gen;  stretch_parameters_t *param = (stretch_parameters_t *)param_gen;  pthread_mutex_lock (&this->lock);  memcpy( param, &this->params, sizeof(stretch_parameters_t) );  pthread_mutex_unlock (&this->lock);  return 1;}static xine_post_api_descr_t * get_param_descr (void) {  return &param_descr;}static char * get_help (void) {  return _("This filter will perform a time stretch, playing the "           "stream faster or slower by a factor. Pitch is optionally "           "preserved, so it is possible, for example, to use it to "           "watch a movie in less time than it was originaly shot.\n"           );}static xine_post_api_t post_api = {  set_parameters,  get_parameters,  get_param_descr,  get_help,};/************************************************************************** * xine audio post plugin functions *************************************************************************/static int stretch_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream,		   uint32_t bits, uint32_t rate, int mode) {  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 */     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);  port->stream->xine->clock->register_scr(port->stream->xine->clock, &this->scr->scr);  /* force updating on stretch_port_put_buffer */  this->params_changed = 1;      return (port->original_port->open) (port->original_port, stream, bits, rate, mode);}static void stretch_port_close(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;  if (this->scr) {    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,   xine_stream_t *stream, extra_info_t *extra_info ){  post_plugin_stretch_t *this = (post_plugin_stretch_t *)port->post;  

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?