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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * spatializer.cpp: sound reverberation
  3.  *****************************************************************************
  4.  * Copyright (C) 2004, 2006, 2007 the VideoLAN team
  5.  *
  6.  * Google Summer of Code 2007
  7.  *
  8.  * Authors: Biodun Osunkunle <biodun@videolan.org>
  9.  *
  10.  * Mentor : Jean-Baptiste Kempf <jb@videolan.org>
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  25.  *****************************************************************************/
  26. /*****************************************************************************
  27.  * Preamble
  28.  *****************************************************************************/
  29. #include <stdlib.h>                                      /* malloc(), free() */
  30. #include <math.h>
  31. #ifdef HAVE_CONFIG_H
  32. # include "config.h"
  33. #endif
  34. #include <vlc_common.h>
  35. #include <vlc_plugin.h>
  36. #include "vlc_aout.h"
  37. #include "revmodel.hpp"
  38. #define SPAT_AMP 0.3
  39. /*****************************************************************************
  40.  * Module descriptor
  41.  *****************************************************************************/
  42. static int  Open ( vlc_object_t * );
  43. static void Close( vlc_object_t * );
  44. #define ROOMSIZE_TEXT N_("Room size")
  45. #define ROOMSIZE_LONGTEXT N_("Defines the virtual surface of the room" 
  46.                                 "emulated by the filter." )
  47. #define WIDTH_TEXT N_("Room width")
  48. #define WIDTH_LONGTEXT N_("Width of the virtual room")
  49. #define WET_TEXT N_("Wet")
  50. #define WET_LONGTEXT NULL
  51. #define DRY_TEXT N_("Dry")
  52. #define DRY_LONGTEXT NULL
  53. #define DAMP_TEXT N_("Damp")
  54. #define DAMP_LONGTEXT NULL
  55. vlc_module_begin ()
  56.     set_description( N_("Audio Spatializer") )
  57.     set_shortname( N_("Spatializer" ) )
  58.     set_capability( "audio filter", 0 )
  59.     set_category( CAT_AUDIO )
  60.     set_subcategory( SUBCAT_AUDIO_AFILTER )
  61.     set_callbacks( Open, Close )
  62.     add_shortcut( "spatializer" )
  63.     add_float( "spatializer-roomsize", 1.05, NULL, ROOMSIZE_TEXT,
  64.                ROOMSIZE_LONGTEXT, true )
  65.     add_float( "spatializer-width", 10., NULL, WIDTH_TEXT,WIDTH_LONGTEXT, true )
  66.     add_float( "spatializer-wet", 3., NULL, WET_TEXT,WET_LONGTEXT, true )
  67.     add_float( "spatializer-dry", 2., NULL, DRY_TEXT,DRY_LONGTEXT, true )
  68.     add_float( "spatializer-damp", 1., NULL, DAMP_TEXT,DAMP_LONGTEXT, true )
  69. vlc_module_end ()
  70. /*****************************************************************************
  71.  * Local prototypes
  72.  *****************************************************************************/
  73. struct aout_filter_sys_t
  74. {
  75.     vlc_mutex_t lock;
  76.     revmodel *p_reverbm;
  77. };
  78. class CLocker
  79. {
  80. public:
  81.     CLocker( vlc_mutex_t *p_lock ) : p_lock(p_lock) {
  82.         vlc_mutex_lock( p_lock );
  83.     }
  84.     virtual ~CLocker() {
  85.         vlc_mutex_unlock( p_lock );
  86.     }
  87. private:
  88.     vlc_mutex_t *p_lock;
  89. };
  90. static const char *psz_control_names[] =
  91. {
  92.     "spatializer-roomsize", "spatializer-width" ,
  93.     "spatializer-wet", "spatializer-dry", "spatializer-damp"
  94. };
  95. static void DoWork( aout_instance_t *, aout_filter_t *,
  96.                     aout_buffer_t *, aout_buffer_t * );
  97. static int  SpatInit( aout_filter_t *);
  98. static void SpatFilter( aout_instance_t *,aout_filter_t *, float *, float *,
  99.                         int, int );
  100. static void SpatClean( aout_filter_t * );
  101. static int RoomCallback ( vlc_object_t *, char const *,
  102.                                            vlc_value_t, vlc_value_t, void * );
  103. static int WetCallback ( vlc_object_t *, char const *,
  104.                                            vlc_value_t, vlc_value_t, void * );
  105. static int DryCallback ( vlc_object_t *, char const *,
  106.                                            vlc_value_t, vlc_value_t, void * );
  107. static int DampCallback ( vlc_object_t *, char const *,
  108.                                            vlc_value_t, vlc_value_t, void * );
  109. static int WidthCallback ( vlc_object_t *, char const *,
  110.                                            vlc_value_t, vlc_value_t, void * );
  111. /*****************************************************************************
  112.  * Open:
  113.  *****************************************************************************/
  114. static int Open( vlc_object_t *p_this )
  115. {
  116.     aout_filter_t     *p_filter = (aout_filter_t *)p_this;
  117.     aout_filter_sys_t *p_sys;
  118.     bool         b_fit = true;
  119.     msg_Dbg(p_this, "Opening filter spatializer %s %s %d", __FILE__,__func__,__LINE__);
  120.     if( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) ||
  121.         p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
  122.     {
  123.         b_fit = false;
  124.         p_filter->input.i_format = VLC_FOURCC('f','l','3','2');
  125.         p_filter->output.i_format = VLC_FOURCC('f','l','3','2');
  126.         msg_Warn( p_filter, "bad input or output format" );
  127.     }
  128.     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
  129.     {
  130.         b_fit = false;
  131.         memcpy( &p_filter->output, &p_filter->input,
  132.                 sizeof(audio_sample_format_t) );
  133.         msg_Warn( p_filter, "input and output formats are not similar" );
  134.     }
  135.     if ( ! b_fit )
  136.     {
  137.         return VLC_EGENERIC;
  138.     }
  139.     p_filter->pf_do_work = DoWork;
  140.     p_filter->b_in_place = true;
  141.      /* Allocate structure */
  142.     p_sys = p_filter->p_sys = (aout_filter_sys_t*)malloc( sizeof( aout_filter_sys_t ) );
  143.     if( !p_sys )
  144.         return VLC_ENOMEM;
  145.     vlc_mutex_init( &p_sys->lock );
  146.     p_sys->p_reverbm = new revmodel();
  147.     p_sys->p_reverbm->setroomsize(1.05);
  148.     p_sys->p_reverbm->setwet(10.0f);
  149.     p_sys->p_reverbm->setdry(1.0f);
  150.     p_sys->p_reverbm->setdamp(0.3);
  151.     p_sys->p_reverbm->setwidth(0.9);
  152.     SpatInit( p_filter);
  153.     return VLC_SUCCESS;
  154. }
  155. /*****************************************************************************
  156.  * Close: close the plugin
  157.  *****************************************************************************/
  158. static void Close( vlc_object_t *p_this )
  159. {
  160.     aout_filter_t     *p_filter = (aout_filter_t *)p_this;
  161.     aout_filter_sys_t *p_sys = p_filter->p_sys;
  162.     SpatClean( p_filter );
  163.     delete p_sys->p_reverbm;
  164.     vlc_mutex_destroy( &p_sys->lock );
  165.     free( p_sys );
  166.     msg_Dbg(p_this, "Closing filter spatializer %s %s %d", __FILE__,__func__,__LINE__);
  167. }
  168. /*****************************************************************************
  169.  * DoWork: process samples buffer
  170.  *****************************************************************************/
  171. static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
  172.                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
  173. {
  174.     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
  175.     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;
  176.     SpatFilter( p_aout, p_filter, (float*)p_out_buf->p_buffer,
  177.                (float*)p_in_buf->p_buffer, p_in_buf->i_nb_samples,
  178.                aout_FormatNbChannels( &p_filter->input ) );
  179. }
  180. static int SpatInit( aout_filter_t *p_filter )
  181. {
  182.     aout_filter_sys_t *p_sys = p_filter->p_sys;
  183.     int i, ch;
  184.     vlc_value_t val1, val2, val3, val4, val5;
  185.     aout_instance_t *p_aout = (aout_instance_t *)p_filter->p_parent;
  186.     for( i = 0; i < 5 ; i ++ )
  187.         var_Create( p_aout, psz_control_names[i], VLC_VAR_FLOAT
  188.                             | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
  189.     /* Get initial values */
  190.     var_Get( p_aout, psz_control_names[0], &val1 );
  191.     var_Get( p_aout, psz_control_names[1], &val2 );
  192.     var_Get( p_aout, psz_control_names[2], &val3 );
  193.     var_Get( p_aout, psz_control_names[3], &val4 );
  194.     var_Get( p_aout, psz_control_names[4], &val5);
  195.     RoomCallback( VLC_OBJECT( p_aout ), NULL, val1, val1, p_sys );
  196.     WidthCallback( VLC_OBJECT( p_aout ), NULL, val2, val2, p_sys );
  197.     WetCallback( VLC_OBJECT( p_aout ), NULL, val3, val3, p_sys );
  198.     DryCallback( VLC_OBJECT( p_aout ), NULL, val4, val4, p_sys );
  199.     DampCallback( VLC_OBJECT( p_aout ), NULL, val5, val5, p_sys );
  200.     msg_Dbg( p_filter, "%f", val1.f_float );
  201.     /* Add our own callbacks */
  202.     var_AddCallback( p_aout, psz_control_names[0], RoomCallback, p_sys );
  203.     var_AddCallback( p_aout, psz_control_names[1], WidthCallback, p_sys );
  204.     var_AddCallback( p_aout, psz_control_names[2], WetCallback, p_sys );
  205.     var_AddCallback( p_aout, psz_control_names[3], DryCallback, p_sys );
  206.     var_AddCallback( p_aout, psz_control_names[4], DampCallback, p_sys );
  207.     return VLC_SUCCESS;
  208. }
  209. static void SpatFilter( aout_instance_t *p_aout,
  210.                        aout_filter_t *p_filter, float *out, float *in,
  211.                        int i_samples, int i_channels )
  212. {
  213.     aout_filter_sys_t *p_sys = p_filter->p_sys;
  214.     CLocker locker( &p_sys->lock );
  215.     int i, ch, j;
  216.     for( i = 0; i < i_samples; i++ )
  217.     {
  218.         for( ch = 0 ; ch < 2; ch++)
  219.         {
  220.             in[ch] = in[ch] * SPAT_AMP;
  221.         }
  222.         p_sys->p_reverbm->processreplace( in, out , 1, i_channels);
  223.         in  += i_channels;
  224.         out += i_channels;
  225.     }
  226. }
  227. static void SpatClean( aout_filter_t *p_filter )
  228. {
  229.     aout_instance_t *p_aout = (aout_instance_t *)p_filter->p_parent;
  230.     aout_filter_sys_t *p_sys = p_filter->p_sys;
  231.     var_DelCallback( p_aout, psz_control_names[0], RoomCallback, p_sys );
  232.     var_DelCallback( p_aout, psz_control_names[1], WidthCallback, p_sys );
  233.     var_DelCallback( p_aout, psz_control_names[2], WetCallback, p_sys );
  234.     var_DelCallback( p_aout, psz_control_names[3], DryCallback, p_sys );
  235.     var_DelCallback( p_aout, psz_control_names[4], DampCallback, p_sys );
  236. }
  237. /*****************************************************************************
  238.  * Variables callbacks
  239.  *****************************************************************************/
  240. static int RoomCallback( vlc_object_t *p_this, char const *psz_cmd,
  241.                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
  242. {
  243.     aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
  244.     CLocker locker( &p_sys->lock );
  245.     p_sys->p_reverbm->setroomsize(newval.f_float);
  246.     msg_Dbg (p_this,"room callback %3.1f %s %s %d", newval.f_float, __FILE__,__func__,__LINE__);
  247.     return VLC_SUCCESS;
  248. }
  249. static int WidthCallback( vlc_object_t *p_this, char const *psz_cmd,
  250.                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
  251. {
  252.     aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
  253.     CLocker locker( &p_sys->lock );
  254.     p_sys->p_reverbm->setwidth(newval.f_float);
  255.     msg_Dbg (p_this,"width callback %3.1f %s %s %d", newval.f_float,  __FILE__,__func__,__LINE__);
  256.     return VLC_SUCCESS;
  257. }
  258. static int WetCallback( vlc_object_t *p_this, char const *psz_cmd,
  259.                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
  260. {
  261.     aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
  262.     CLocker locker( &p_sys->lock );
  263.     p_sys->p_reverbm->setwet(newval.f_float);
  264.     msg_Dbg (p_this,"wet callback %3.1f %s %s %d", newval.f_float,  __FILE__,__func__,__LINE__);
  265.     return VLC_SUCCESS;
  266. }
  267. static int DryCallback( vlc_object_t *p_this, char const *psz_cmd,
  268.                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
  269. {
  270.     aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
  271.     CLocker locker( &p_sys->lock );
  272.     p_sys->p_reverbm->setdry(newval.f_float);
  273.     msg_Dbg (p_this,"dry callback %3.1f %s %s %d", newval.f_float, __FILE__,__func__,__LINE__);
  274.     return VLC_SUCCESS;
  275. }
  276. static int DampCallback( vlc_object_t *p_this, char const *psz_cmd,
  277.                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
  278. {
  279.     aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
  280.     CLocker locker( &p_sys->lock );
  281.     p_sys->p_reverbm->setdamp(newval.f_float);
  282.     msg_Dbg (p_this, "damp callback %3.1f %s %s %d", newval.f_float, __FILE__,__func__,__LINE__);
  283.     return VLC_SUCCESS;
  284. }