linear.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:12k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * linear.c : linear interpolation resampler
  3.  *****************************************************************************
  4.  * Copyright (C) 2002, 2006 the VideoLAN team
  5.  * $Id: 161b754a0fd1da759487067833f9b305dc0179e2 $
  6.  *
  7.  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  8.  *          Sigmund Augdal Helberg <dnumgis@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <vlc_common.h>
  31. #include <vlc_plugin.h>
  32. #include <vlc_aout.h>
  33. #include <vlc_filter.h>
  34. #include <vlc_block.h>
  35. /*****************************************************************************
  36.  * Local prototypes
  37.  *****************************************************************************/
  38. static int  Create    ( vlc_object_t * );
  39. static void Close     ( vlc_object_t * );
  40. static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
  41.                         aout_buffer_t * );
  42. static int  OpenFilter ( vlc_object_t * );
  43. static void CloseFilter( vlc_object_t * );
  44. static block_t *Resample( filter_t *, block_t * );
  45. /*****************************************************************************
  46.  * Local structures
  47.  *****************************************************************************/
  48. struct filter_sys_t
  49. {
  50.     int32_t *p_prev_sample;       /* this filter introduces a 1 sample delay */
  51.     unsigned int i_remainder;                /* remainder of previous sample */
  52.     audio_date_t end_date;
  53. };
  54. /*****************************************************************************
  55.  * Module descriptor
  56.  *****************************************************************************/
  57. vlc_module_begin ()
  58.     set_description( N_("Audio filter for linear interpolation resampling") )
  59.     set_category( CAT_AUDIO )
  60.     set_subcategory( SUBCAT_AUDIO_MISC )
  61.     set_capability( "audio filter", 5 )
  62.     set_callbacks( Create, Close )
  63.     add_submodule ()
  64.     set_description( N_("Audio filter for linear interpolation resampling") )
  65.     set_capability( "audio filter2", 5 )
  66.     set_callbacks( OpenFilter, CloseFilter )
  67. vlc_module_end ()
  68. /*****************************************************************************
  69.  * Create: allocate linear resampler
  70.  *****************************************************************************/
  71. static int Create( vlc_object_t *p_this )
  72. {
  73.     aout_filter_t * p_filter = (aout_filter_t *)p_this;
  74.     struct filter_sys_t * p_sys;
  75.  
  76.     if ( p_filter->input.i_rate == p_filter->output.i_rate
  77.           || p_filter->input.i_format != p_filter->output.i_format
  78.           || p_filter->input.i_physical_channels
  79.               != p_filter->output.i_physical_channels
  80.           || p_filter->input.i_original_channels
  81.               != p_filter->output.i_original_channels
  82.           || p_filter->input.i_format != VLC_FOURCC('f','l','3','2') )
  83.     {
  84.         return VLC_EGENERIC;
  85.     }
  86.     /* Allocate the memory needed to store the module's structure */
  87.     p_sys = malloc( sizeof(filter_sys_t) );
  88.     p_filter->p_sys = (struct aout_filter_sys_t *)p_sys;
  89.     if( p_sys == NULL )
  90.         return VLC_ENOMEM;
  91.     p_sys->p_prev_sample = malloc(
  92.         p_filter->input.i_channels * sizeof(int32_t) );
  93.     if( p_sys->p_prev_sample == NULL )
  94.     {
  95.         free( p_sys );
  96.         return VLC_ENOMEM;
  97.     }
  98.     aout_DateInit( &p_sys->end_date, p_filter->output.i_rate );
  99.     p_filter->pf_do_work = DoWork;
  100.     /* We don't want a new buffer to be created because we're not sure we'll
  101.      * actually need to resample anything. */
  102.     p_filter->b_in_place = true;
  103.     return VLC_SUCCESS;
  104. }
  105. /*****************************************************************************
  106.  * Close: free our resources
  107.  *****************************************************************************/
  108. static void Close( vlc_object_t * p_this )
  109. {
  110.     aout_filter_t * p_filter = (aout_filter_t *)p_this;
  111.     filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
  112.  
  113.     free( p_sys->p_prev_sample );
  114.     free( p_sys );
  115. }
  116. /*****************************************************************************
  117.  * DoWork: convert a buffer
  118.  *****************************************************************************/
  119. static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
  120.                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
  121. {
  122.     filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
  123.     float *p_out = (float *)p_out_buf->p_buffer;
  124.     float *p_prev_sample = (float *)p_sys->p_prev_sample;
  125.     int i_nb_channels = p_filter->input.i_channels;
  126.     int i_in_nb = p_in_buf->i_nb_samples;
  127.     int i_chan, i_in, i_out = 0;
  128.     /* Check if we really need to run the resampler */
  129.     if( p_aout->mixer.mixer.i_rate == p_filter->input.i_rate )
  130.     {
  131.         if( p_filter->b_continuity &&
  132.             p_in_buf->i_size >=
  133.               p_in_buf->i_nb_bytes + sizeof(float) * i_nb_channels )
  134.         {
  135.             /* output the whole thing with the last sample from last time */
  136.             memmove( ((float *)(p_in_buf->p_buffer)) + i_nb_channels,
  137.                      p_in_buf->p_buffer, p_in_buf->i_nb_bytes );
  138.             memcpy( p_in_buf->p_buffer, p_prev_sample,
  139.                     i_nb_channels * sizeof(float) );
  140.         }
  141.         p_filter->b_continuity = false;
  142.         return;
  143.     }
  144.     float p_in_orig[p_in_buf->i_nb_bytes / 4], *p_in = p_in_orig;
  145.     vlc_memcpy( p_in, p_in_buf->p_buffer, p_in_buf->i_nb_bytes );
  146.     /* Take care of the previous input sample (if any) */
  147.     if( !p_filter->b_continuity )
  148.     {
  149.         p_filter->b_continuity = true;
  150.         p_sys->i_remainder = 0;
  151.         aout_DateInit( &p_sys->end_date, p_filter->output.i_rate );
  152.     }
  153.     else
  154.     {
  155.         while( p_sys->i_remainder < p_filter->output.i_rate )
  156.         {
  157.             for( i_chan = i_nb_channels ; i_chan ; )
  158.             {
  159.                 i_chan--;
  160.                 p_out[i_chan] = p_prev_sample[i_chan];
  161.                 p_out[i_chan] += ( ( p_in[i_chan] - p_prev_sample[i_chan] )
  162.                                    * p_sys->i_remainder
  163.                                    / p_filter->output.i_rate );
  164.             }
  165.             p_out += i_nb_channels;
  166.               i_out++;
  167.             p_sys->i_remainder += p_filter->input.i_rate;
  168.         }
  169.         p_sys->i_remainder -= p_filter->output.i_rate;
  170.     }
  171.     /* Take care of the current input samples (minus last one) */
  172.     for( i_in = 0; i_in < i_in_nb - 1; i_in++ )
  173.     {
  174.         while( p_sys->i_remainder < p_filter->output.i_rate )
  175.         {
  176.             for( i_chan = i_nb_channels ; i_chan ; )
  177.             {
  178.                 i_chan--;
  179.                 p_out[i_chan] = p_in[i_chan];
  180.                 p_out[i_chan] += ( ( p_in[i_chan + i_nb_channels]
  181.                     - p_in[i_chan] )
  182.                     * p_sys->i_remainder / p_filter->output.i_rate );
  183.             }
  184.             p_out += i_nb_channels;
  185.               i_out++;
  186.             p_sys->i_remainder += p_filter->input.i_rate;
  187.         }
  188.         p_in += i_nb_channels;
  189.         p_sys->i_remainder -= p_filter->output.i_rate;
  190.     }
  191.     /* Backup the last input sample for next time */
  192.     for( i_chan = i_nb_channels ; i_chan ; )
  193.     {
  194.         i_chan--;
  195.         p_prev_sample[i_chan] = p_in[i_chan];
  196.     }
  197.     p_out_buf->i_nb_samples = i_out;
  198.     p_out_buf->start_date = p_in_buf->start_date;
  199.     if( p_in_buf->start_date !=
  200.         aout_DateGet( &p_sys->end_date ) )
  201.     {
  202.         aout_DateSet( &p_sys->end_date, p_in_buf->start_date );
  203.     }
  204.     p_out_buf->end_date = aout_DateIncrement( &p_sys->end_date,
  205.                                               p_out_buf->i_nb_samples );
  206.     p_out_buf->i_nb_bytes = p_out_buf->i_nb_samples *
  207.         i_nb_channels * sizeof(int32_t);
  208. }
  209. /*****************************************************************************
  210.  * OpenFilter:
  211.  *****************************************************************************/
  212. static int OpenFilter( vlc_object_t *p_this )
  213. {
  214.     filter_t *p_filter = (filter_t *)p_this;
  215.     filter_sys_t *p_sys;
  216.     int i_out_rate  = p_filter->fmt_out.audio.i_rate;
  217.     if( p_filter->fmt_in.audio.i_rate == p_filter->fmt_out.audio.i_rate ||
  218.         p_filter->fmt_in.i_codec != VLC_FOURCC('f','l','3','2') )
  219.     {
  220.         return VLC_EGENERIC;
  221.     }
  222.  
  223.     /* Allocate the memory needed to store the module's structure */
  224.     p_filter->p_sys = p_sys = malloc( sizeof(struct filter_sys_t) );
  225.     if( p_sys == NULL )
  226.         return VLC_ENOMEM;
  227.     p_sys->p_prev_sample = malloc(
  228.         p_filter->fmt_in.audio.i_channels * sizeof(int32_t) );
  229.     if( p_sys->p_prev_sample == NULL )
  230.     {
  231.         free( p_sys );
  232.         return VLC_ENOMEM;
  233.     }
  234.     aout_DateInit( &p_sys->end_date, p_filter->fmt_in.audio.i_rate );
  235.     p_filter->pf_audio_filter = Resample;
  236.     msg_Dbg( p_this, "%4.4s/%iKHz/%i->%4.4s/%iKHz/%i",
  237.              (char *)&p_filter->fmt_in.i_codec,
  238.              p_filter->fmt_in.audio.i_rate,
  239.              p_filter->fmt_in.audio.i_channels,
  240.              (char *)&p_filter->fmt_out.i_codec,
  241.              p_filter->fmt_out.audio.i_rate,
  242.              p_filter->fmt_out.audio.i_channels);
  243.     p_filter->fmt_out = p_filter->fmt_in;
  244.     p_filter->fmt_out.audio.i_rate = i_out_rate;
  245.     return 0;
  246. }
  247. /*****************************************************************************
  248.  * CloseFilter : deallocate data structures
  249.  *****************************************************************************/
  250. static void CloseFilter( vlc_object_t *p_this )
  251. {
  252.     filter_t *p_filter = (filter_t *)p_this;
  253.     free( p_filter->p_sys->p_prev_sample );
  254.     free( p_filter->p_sys );
  255. }
  256. /*****************************************************************************
  257.  * Resample
  258.  *****************************************************************************/
  259. static block_t *Resample( filter_t *p_filter, block_t *p_block )
  260. {
  261.     aout_filter_t aout_filter;
  262.     aout_buffer_t in_buf, out_buf;
  263.     block_t *p_out;
  264.     int i_out_size;
  265.     int i_bytes_per_frame;
  266.     if( !p_block || !p_block->i_samples )
  267.     {
  268.         if( p_block )
  269.             block_Release( p_block );
  270.         return NULL;
  271.     }
  272.  
  273.     i_bytes_per_frame = p_filter->fmt_out.audio.i_channels *
  274.                   p_filter->fmt_out.audio.i_bitspersample / 8;
  275.  
  276.     i_out_size = i_bytes_per_frame * ( 1 + (p_block->i_samples *
  277.         p_filter->fmt_out.audio.i_rate / p_filter->fmt_in.audio.i_rate));
  278.     p_out = p_filter->pf_audio_buffer_new( p_filter, i_out_size );
  279.     if( !p_out )
  280.     {
  281.         msg_Warn( p_filter, "can't get output buffer" );
  282.         block_Release( p_block );
  283.         return NULL;
  284.     }
  285.     p_out->i_samples = i_out_size / i_bytes_per_frame;
  286.     p_out->i_dts = p_block->i_dts;
  287.     p_out->i_pts = p_block->i_pts;
  288.     p_out->i_length = p_block->i_length;
  289.     aout_filter.p_sys = (struct aout_filter_sys_t *)p_filter->p_sys;
  290.     aout_filter.input = p_filter->fmt_in.audio;
  291.     aout_filter.output = p_filter->fmt_out.audio;
  292.     aout_filter.b_continuity = false;
  293.     in_buf.p_buffer = p_block->p_buffer;
  294.     in_buf.i_nb_bytes = p_block->i_buffer;
  295.     in_buf.i_nb_samples = p_block->i_samples;
  296.     out_buf.p_buffer = p_out->p_buffer;
  297.     out_buf.i_nb_bytes = p_out->i_buffer;
  298.     out_buf.i_nb_samples = p_out->i_samples;
  299.     DoWork( (aout_instance_t *)p_filter, &aout_filter, &in_buf, &out_buf );
  300.     block_Release( p_block );
  301.  
  302.     p_out->i_buffer = out_buf.i_nb_bytes;
  303.     p_out->i_samples = out_buf.i_nb_samples;
  304.     return p_out;
  305. }