normvol.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:8k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * normvol.c :  volume normalizer
  3.  *****************************************************************************
  4.  * Copyright (C) 2001 VideoLAN
  5.  * $Id: normvol.c 9126 2004-11-03 00:07:38Z gbazin $
  6.  *
  7.  * Authors: Cl閙ent Stenac <zorglub@videolan.org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*
  24.  * TODO:
  25.  *
  26.  * We should detect fast power increases and react faster to these
  27.  * This way, we can increase the buffer size to get a more stable filter */
  28. /*****************************************************************************
  29.  * Preamble
  30.  *****************************************************************************/
  31. #include <stdlib.h>                                      /* malloc(), free() */
  32. #include <string.h>
  33. #include <errno.h>                                                 /* ENOMEM */
  34. #include <stdio.h>
  35. #include <ctype.h>
  36. #include <signal.h>
  37. #include <math.h>
  38. #include <vlc/vlc.h>
  39. #include <vlc/aout.h>
  40. #include <aout_internal.h>
  41. /*****************************************************************************
  42.  * Local prototypes
  43.  *****************************************************************************/
  44. static int  Open     ( vlc_object_t * );
  45. static void Close    ( vlc_object_t * );
  46. static void DoWork   ( aout_instance_t * , aout_filter_t *,
  47.                 aout_buffer_t * , aout_buffer_t *);
  48. typedef struct aout_filter_sys_t
  49. {
  50.     int i_nb;
  51.     float *p_last;
  52.     float f_max;
  53. } aout_filter_sys_t;
  54. /*****************************************************************************
  55.  * Module descriptor
  56.  *****************************************************************************/
  57. #define BUFF_TEXT N_("Number of audio buffers" )
  58. #define BUFF_LONGTEXT N_("This is the number of audio buffers on which the " 
  59.                 "power measurement is made. A higher number of buffers will " 
  60.                 "increase the response time of the filter to a high " 
  61.                 "power but will make it less sensitive to short variations." )
  62. #define LEVEL_TEXT N_("Max level" )
  63. #define LEVEL_LONGTEXT N_("If the average power over the last N buffers " 
  64.                "is higher than this value, the volume will be normalized. " 
  65.                "This value is a positive floating point number. A value " 
  66.                "between 0.5 and 10 seems sensible." )
  67. vlc_module_begin();
  68.     set_description( _("Volume normalizer") );
  69.     add_shortcut( "volnorm" );
  70.     add_integer( "norm-buff-size", 20 ,NULL ,BUFF_TEXT, BUFF_LONGTEXT,
  71.                  VLC_TRUE);
  72.     add_float( "norm-max-level", 2.0, NULL, LEVEL_TEXT,
  73.                LEVEL_LONGTEXT, VLC_TRUE );
  74.     set_capability( "audio filter", 0 );
  75.     set_callbacks( Open, Close );
  76. vlc_module_end();
  77. /*****************************************************************************
  78.  * Open: initialize and create stuff
  79.  *****************************************************************************/
  80. static int Open( vlc_object_t *p_this )
  81. {
  82.     aout_filter_t *p_filter = (aout_filter_t*)p_this;
  83.     int i_channels;
  84.     aout_filter_sys_t *p_sys = p_filter->p_sys =
  85.         malloc( sizeof( aout_filter_sys_t ) );
  86.     if( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) ||
  87.         p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
  88.     {
  89.             msg_Warn( p_filter, "Bad input or output format" );
  90.             return VLC_EGENERIC;
  91.     }
  92.     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
  93.     {
  94.         msg_Warn( p_filter, "input and output formats are not similar" );
  95.         return VLC_EGENERIC;
  96.     }
  97.     p_filter->pf_do_work = DoWork;
  98.     p_filter->b_in_place = VLC_TRUE;
  99.     i_channels = aout_FormatNbChannels( &p_filter->input );
  100.     p_sys->i_nb = var_CreateGetInteger( p_filter->p_parent, "norm-buff-size" );
  101.     p_sys->f_max = var_CreateGetFloat( p_filter->p_parent, "norm-max-level" );
  102.     if( p_sys->f_max <= 0 ) p_sys->f_max = 0.01;
  103.     /* We need to store (nb_buffers+1)*nb_channels floats */
  104.     p_sys->p_last = malloc( sizeof( float ) * (i_channels) *
  105.                             (p_filter->p_sys->i_nb + 2) );
  106.     memset( p_sys->p_last, 0 ,sizeof( float ) * (i_channels) *
  107.             (p_filter->p_sys->i_nb + 2) );
  108.     return VLC_SUCCESS;
  109. }
  110. /*****************************************************************************
  111.  * DoWork : normalizes and sends a buffer
  112.  *****************************************************************************/
  113.  static void DoWork( aout_instance_t *p_aout, aout_filter_t *p_filter,
  114.                      aout_buffer_t *p_in_buf, aout_buffer_t *p_out_buf )
  115. {
  116.     float *pf_sum;
  117.     float *pf_gain;
  118.     float f_average = 0;
  119.     int i, i_chan;
  120.     int i_samples = p_in_buf->i_nb_samples;
  121.     int i_channels = aout_FormatNbChannels( &p_filter->input );
  122.     float *p_out = (float*)p_out_buf->p_buffer;
  123.     float *p_in =  (float*)p_in_buf->p_buffer;
  124.     struct aout_filter_sys_t *p_sys = p_filter->p_sys;
  125.     pf_sum = (float *)malloc( sizeof(float) * i_channels );
  126.     memset( pf_sum, 0, sizeof(float) * i_channels );
  127.     pf_gain = (float *)malloc( sizeof(float) * i_channels );
  128.     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
  129.     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;
  130.     /* Calculate the average power level on this buffer */
  131.     for( i = 0 ; i < i_samples; i++ )
  132.     {
  133.         for( i_chan = 0; i_chan < i_channels; i_chan++ )
  134.         {
  135.             float f_sample = p_in[i_chan];
  136.             float f_square = pow( f_sample, 2 );
  137.             pf_sum[i_chan] += f_square;
  138.         }
  139.         p_in += i_channels;
  140.     }
  141.     /* sum now contains for each channel the sigma(value