* 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
*****************************************************************************/
#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")
/*****************************************************************************
* 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;
}
*****************************************************************************/
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;
}
}
}
-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;
}