]> git.sesse.net Git - vlc/blobdiff - modules/audio_filter/spatializer/spatializer.cpp
Use var_Inherit* instead of var_CreateGet*.
[vlc] / modules / audio_filter / spatializer / spatializer.cpp
index 1e843c2256ea3c5597a8eac434099935275bf65a..a5260d8a2bc15e8d1a76da2cea20e08be478143e 100644 (file)
  * 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-1301, USA.
+ * 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-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include <stdlib.h>                                      /* malloc(), free() */
-#include <math.h>
-
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
 
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <math.h>
+
+#include <new>
+using std::nothrow;
+
 #include <vlc_common.h>
 #include <vlc_plugin.h>
-#include "vlc_aout.h"
+#include <vlc_aout.h>
+#include <vlc_filter.h>
+
 #include "revmodel.hpp"
 #define SPAT_AMP 0.3
+
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
@@ -47,7 +53,7 @@ static void Close( vlc_object_t * );
 
 #define ROOMSIZE_TEXT N_("Room size")
 #define ROOMSIZE_LONGTEXT N_("Defines the virtual surface of the room" \
-                                "emulated by the filter." )
+                             emulated by the filter." )
 
 #define WIDTH_TEXT N_("Room width")
 #define WIDTH_LONGTEXT N_("Width of the virtual room")
@@ -81,96 +87,91 @@ vlc_module_end ()
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-struct aout_filter_sys_t
+struct filter_sys_t
 {
     vlc_mutex_t lock;
     revmodel *p_reverbm;
-
 };
 
-class CLocker
-{
-public:
-    CLocker( vlc_mutex_t *p_lock ) : p_lock(p_lock) {
-        vlc_mutex_lock( p_lock );
-    }
-    virtual ~CLocker() {
-        vlc_mutex_unlock( p_lock );
-    }
-private:
-    vlc_mutex_t *p_lock;
+#define DECLARECB(fn) static int fn (vlc_object_t *,char const *, \
+                                     vlc_value_t, vlc_value_t, void *)
+DECLARECB( RoomCallback  );
+DECLARECB( WetCallback   );
+DECLARECB( DryCallback   );
+DECLARECB( DampCallback  );
+DECLARECB( WidthCallback );
+
+#undef  DECLARECB
+
+struct callback_s {
+  const char *psz_name;
+  int (*fp_callback)(vlc_object_t *,const char *,
+                     vlc_value_t,vlc_value_t,void *);
+  void (revmodel::* fp_set)(float);
 };
 
-static const char *psz_control_names[] =
-{
-    "spatializer-roomsize", "spatializer-width" ,
-    "spatializer-wet", "spatializer-dry", "spatializer-damp"
+static const callback_s callbacks[] = {
+    { "spatializer-roomsize", RoomCallback,  &revmodel::setroomsize },
+    { "spatializer-width",    WidthCallback, &revmodel::setwidth },
+    { "spatializer-wet",      WetCallback,   &revmodel::setwet },
+    { "spatializer-dry",      DryCallback,   &revmodel::setdry },
+    { "spatializer-damp",     DampCallback,  &revmodel::setdamp }
 };
-static void DoWork( aout_instance_t *, aout_filter_t *,
-                    aout_buffer_t *, aout_buffer_t * );
-
-static int  SpatInit( aout_filter_t *);
-static void SpatFilter( aout_instance_t *,aout_filter_t *, float *, float *,
-                        int, int );
-static void SpatClean( aout_filter_t * );
-static int RoomCallback ( vlc_object_t *, char const *,
-                                           vlc_value_t, vlc_value_t, void * );
-static int WetCallback ( vlc_object_t *, char const *,
-                                           vlc_value_t, vlc_value_t, void * );
-static int DryCallback ( vlc_object_t *, char const *,
-                                           vlc_value_t, vlc_value_t, void * );
-static int DampCallback ( vlc_object_t *, char const *,
-                                           vlc_value_t, vlc_value_t, void * );
-static int WidthCallback ( vlc_object_t *, char const *,
-                                           vlc_value_t, vlc_value_t, void * );
+enum { num_callbacks=sizeof(callbacks)/sizeof(callback_s) };
+
+static block_t *DoWork( filter_t *, block_t * );
 
 /*****************************************************************************
  * Open:
  *****************************************************************************/
 static int Open( vlc_object_t *p_this )
 {
-    aout_filter_t     *p_filter = (aout_filter_t *)p_this;
-    aout_filter_sys_t *p_sys;
-    bool         b_fit = true;
-    msg_Dbg(p_this, "Opening filter spatializer %s %s %d", __FILE__,__func__,__LINE__);
+    filter_t     *p_filter = (filter_t *)p_this;
+    filter_sys_t *p_sys;
+    vlc_object_t *p_aout = p_filter->p_parent;
 
-    if( p_filter->input.i_format != VLC_CODEC_FL32 ||
-        p_filter->output.i_format != VLC_CODEC_FL32 )
+    if( p_filter->fmt_in.audio.i_format != VLC_CODEC_FL32 ||
+        p_filter->fmt_out.audio.i_format != VLC_CODEC_FL32 )
     {
-        b_fit = false;
-        p_filter->input.i_format = VLC_CODEC_FL32;
-        p_filter->output.i_format = VLC_CODEC_FL32;
+        p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
+        p_filter->fmt_out.audio.i_format = VLC_CODEC_FL32;
         msg_Warn( p_filter, "bad input or output format" );
+        return VLC_EGENERIC;
     }
-    if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
+    if ( !AOUT_FMTS_SIMILAR( &p_filter->fmt_in.audio, &p_filter->fmt_out.audio ) )
     {
-        b_fit = false;
-        memcpy( &p_filter->output, &p_filter->input,
+        memcpy( &p_filter->fmt_out.audio, &p_filter->fmt_in.audio,
                 sizeof(audio_sample_format_t) );
         msg_Warn( p_filter, "input and output formats are not similar" );
-    }
-
-    if ( ! b_fit )
-    {
         return VLC_EGENERIC;
     }
 
-    p_filter->pf_do_work = DoWork;
-    p_filter->b_in_place = true;
+    p_filter->pf_audio_filter = DoWork;
 
      /* Allocate structure */
-    p_sys = p_filter->p_sys = (aout_filter_sys_t*)malloc( sizeof( aout_filter_sys_t ) );
+    p_sys = p_filter->p_sys = (filter_sys_t*)malloc( sizeof( *p_sys ) );
     if( !p_sys )
         return VLC_ENOMEM;
 
+    /* Force new to return 0 on failure instead of throwing, since we don't
+       want an exception to leak back to C code. Bad things would happen. */
+    p_sys->p_reverbm = new (nothrow) revmodel;
+    if( !p_sys->p_reverbm )
+    {
+        free( p_sys );
+        return VLC_ENOMEM;
+    }
+
     vlc_mutex_init( &p_sys->lock );
-    p_sys->p_reverbm = new revmodel();
-    p_sys->p_reverbm->setroomsize(1.05);
-    p_sys->p_reverbm->setwet(10.0f);
-    p_sys->p_reverbm->setdry(1.0f);
-    p_sys->p_reverbm->setdamp(0.3);
-    p_sys->p_reverbm->setwidth(0.9);
-    SpatInit( p_filter);
+
+    for(unsigned i=0;i<num_callbacks;++i)
+    {
+        /* NOTE: C++ pointer-to-member function call from table lookup. */
+        (p_sys->p_reverbm->*(callbacks[i].fp_set))
+            (var_CreateGetFloatCommand(p_aout,callbacks[i].psz_name));
+        var_AddCallback( p_aout, callbacks[i].psz_name,
+                         callbacks[i].fp_callback, p_sys );
+    }
 
     return VLC_SUCCESS;
 }
@@ -180,75 +181,37 @@ static int Open( vlc_object_t *p_this )
  *****************************************************************************/
 static void Close( vlc_object_t *p_this )
 {
-    aout_filter_t     *p_filter = (aout_filter_t *)p_this;
-    aout_filter_sys_t *p_sys = p_filter->p_sys;
-    SpatClean( p_filter );
+    filter_t     *p_filter = (filter_t *)p_this;
+    filter_sys_t *p_sys = p_filter->p_sys;
+    vlc_object_t *p_aout = p_filter->p_parent;
+
+    /* Delete the callbacks */
+    for(unsigned i=0;i<num_callbacks;++i)
+    {
+        var_DelCallback( p_aout, callbacks[i].psz_name,
+                         callbacks[i].fp_callback, p_sys );
+    }
+
     delete p_sys->p_reverbm;
     vlc_mutex_destroy( &p_sys->lock );
     free( p_sys );
-    msg_Dbg(p_this, "Closing filter spatializer %s %s %d", __FILE__,__func__,__LINE__);
+    msg_Dbg( p_this, "Closing filter spatializer" );
 }
 
 /*****************************************************************************
- * DoWork: process samples buffer
+ * SpatFilter: process samples buffer
+ * DoWork: call SpatFilter
  *****************************************************************************/
-static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
-                    aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
-{
-    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
-    p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;
-
-    SpatFilter( p_aout, p_filter, (float*)p_out_buf->p_buffer,
-               (float*)p_in_buf->p_buffer, p_in_buf->i_nb_samples,
-               aout_FormatNbChannels( &p_filter->input ) );
-}
-
-static int SpatInit( aout_filter_t *p_filter )
-{
-    aout_filter_sys_t *p_sys = p_filter->p_sys;
-    int i, ch;
-    vlc_value_t val1, val2, val3, val4, val5;
-    aout_instance_t *p_aout = (aout_instance_t *)p_filter->p_parent;
-
-    for( i = 0; i < 5 ; i ++ )
-        var_Create( p_aout, psz_control_names[i], VLC_VAR_FLOAT
-                            | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
-
-    /* Get initial values */
-    var_Get( p_aout, psz_control_names[0], &val1 );
-    var_Get( p_aout, psz_control_names[1], &val2 );
-    var_Get( p_aout, psz_control_names[2], &val3 );
-    var_Get( p_aout, psz_control_names[3], &val4 );
-    var_Get( p_aout, psz_control_names[4], &val5);
-
-    RoomCallback( VLC_OBJECT( p_aout ), NULL, val1, val1, p_sys );
-    WidthCallback( VLC_OBJECT( p_aout ), NULL, val2, val2, p_sys );
-    WetCallback( VLC_OBJECT( p_aout ), NULL, val3, val3, p_sys );
-    DryCallback( VLC_OBJECT( p_aout ), NULL, val4, val4, p_sys );
-    DampCallback( VLC_OBJECT( p_aout ), NULL, val5, val5, p_sys );
-
-    msg_Dbg( p_filter, "%f", val1.f_float );
-    /* Add our own callbacks */
-    var_AddCallback( p_aout, psz_control_names[0], RoomCallback, p_sys );
-    var_AddCallback( p_aout, psz_control_names[1], WidthCallback, p_sys );
-    var_AddCallback( p_aout, psz_control_names[2], WetCallback, p_sys );
-    var_AddCallback( p_aout, psz_control_names[3], DryCallback, p_sys );
-    var_AddCallback( p_aout, psz_control_names[4], DampCallback, p_sys );
-
-    return VLC_SUCCESS;
-}
 
-static void SpatFilter( aout_instance_t *p_aout,
-                       aout_filter_t *p_filter, float *out, float *in,
-                       int i_samples, int i_channels )
+static void SpatFilter( filter_t *p_filter, float *out, float *in,
+                        unsigned i_samples, unsigned i_channels )
 {
-    aout_filter_sys_t *p_sys = p_filter->p_sys;
-    CLocker locker( &p_sys->lock );
+    filter_sys_t *p_sys = p_filter->p_sys;
+    vlc_mutex_locker locker( &p_sys->lock );
 
-    int i, ch, j;
-    for( i = 0; i < i_samples; i++ )
+    for( unsigned i = 0; i < i_samples; i++ )
     {
-        for( ch = 0 ; ch < 2; ch++)
+        for( unsigned ch = 0 ; ch < 2; ch++)
         {
             in[ch] = in[ch] * SPAT_AMP;
         }
@@ -258,71 +221,71 @@ static void SpatFilter( aout_instance_t *p_aout,
     }
 }
 
-static void SpatClean( aout_filter_t *p_filter )
+static block_t *DoWork( filter_t * p_filter, block_t * p_in_buf )
 {
-    aout_instance_t *p_aout = (aout_instance_t *)p_filter->p_parent;
-    aout_filter_sys_t *p_sys = p_filter->p_sys;
-
-    var_DelCallback( p_aout, psz_control_names[0], RoomCallback, p_sys );
-    var_DelCallback( p_aout, psz_control_names[1], WidthCallback, p_sys );
-    var_DelCallback( p_aout, psz_control_names[2], WetCallback, p_sys );
-    var_DelCallback( p_aout, psz_control_names[3], DryCallback, p_sys );
-    var_DelCallback( p_aout, psz_control_names[4], DampCallback, p_sys );
+    SpatFilter( p_filter, (float*)p_in_buf->p_buffer,
+               (float*)p_in_buf->p_buffer, p_in_buf->i_nb_samples,
+               aout_FormatNbChannels( &p_filter->fmt_in.audio ) );
+    return p_in_buf;
 }
 
+
 /*****************************************************************************
  * Variables callbacks
  *****************************************************************************/
 
-static int RoomCallback( vlc_object_t *p_this, char const *psz_cmd,
-                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
+static int RoomCallback( vlc_object_t *p_this, char const *,
+                         vlc_value_t, vlc_value_t newval, void *p_data )
 {
-    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
-    CLocker locker( &p_sys->lock );
+    filter_sys_t *p_sys = (filter_sys_t*)p_data;
+    vlc_mutex_locker locker( &p_sys->lock );
 
     p_sys->p_reverbm->setroomsize(newval.f_float);
-    msg_Dbg (p_this,"room callback %3.1f %s %s %d", newval.f_float, __FILE__,__func__,__LINE__);
+    msg_Dbg( p_this, "room size is now %3.1f", newval.f_float );
     return VLC_SUCCESS;
 }
 
-static int WidthCallback( vlc_object_t *p_this, char const *psz_cmd,
-                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
+static int WidthCallback( vlc_object_t *p_this, char const *,
+                          vlc_value_t, vlc_value_t newval, void *p_data )
 {
-    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
-    CLocker locker( &p_sys->lock );
+    filter_sys_t *p_sys = (filter_sys_t*)p_data;
+    vlc_mutex_locker locker( &p_sys->lock );
 
     p_sys->p_reverbm->setwidth(newval.f_float);
-    msg_Dbg (p_this,"width callback %3.1f %s %s %d", newval.f_float,  __FILE__,__func__,__LINE__);
+    msg_Dbg( p_this, "width is now %3.1f", newval.f_float );
     return VLC_SUCCESS;
 }
-static int WetCallback( vlc_object_t *p_this, char const *psz_cmd,
-                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
+
+static int WetCallback( vlc_object_t *p_this, char const *,
+                        vlc_value_t, vlc_value_t newval, void *p_data )
 {
-    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
-    CLocker locker( &p_sys->lock );
+    filter_sys_t *p_sys = (filter_sys_t*)p_data;
+    vlc_mutex_locker locker( &p_sys->lock );
 
     p_sys->p_reverbm->setwet(newval.f_float);
-    msg_Dbg (p_this,"wet callback %3.1f %s %s %d", newval.f_float,  __FILE__,__func__,__LINE__);
+    msg_Dbg( p_this, "'wet' value is now %3.1f", newval.f_float );
     return VLC_SUCCESS;
 }
-static int DryCallback( vlc_object_t *p_this, char const *psz_cmd,
-                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
+
+static int DryCallback( vlc_object_t *p_this, char const *,
+                        vlc_value_t, vlc_value_t newval, void *p_data )
 {
-    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
-    CLocker locker( &p_sys->lock );
+    filter_sys_t *p_sys = (filter_sys_t*)p_data;
+    vlc_mutex_locker locker( &p_sys->lock );
 
     p_sys->p_reverbm->setdry(newval.f_float);
-    msg_Dbg (p_this,"dry callback %3.1f %s %s %d", newval.f_float, __FILE__,__func__,__LINE__);
+    msg_Dbg( p_this, "'dry' value is now %3.1f", newval.f_float );
     return VLC_SUCCESS;
 }
-static int DampCallback( vlc_object_t *p_this, char const *psz_cmd,
-                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
+
+static int DampCallback( vlc_object_t *p_this, char const *,
+                         vlc_value_t, vlc_value_t newval, void *p_data )
 {
-    aout_filter_sys_t *p_sys = (aout_filter_sys_t*)p_data;
-    CLocker locker( &p_sys->lock );
+    filter_sys_t *p_sys = (filter_sys_t*)p_data;
+    vlc_mutex_locker locker( &p_sys->lock );
 
     p_sys->p_reverbm->setdamp(newval.f_float);
-    msg_Dbg (p_this, "damp callback %3.1f %s %s %d", newval.f_float, __FILE__,__func__,__LINE__);
+    msg_Dbg( p_this, "'damp' value is now %3.1f", newval.f_float );
     return VLC_SUCCESS;
 }