[vlc-devel] [PATCH 1/2] Add new API to libvlc for persistent equalizer settings.
Mark Lee
mark.lee at capricasoftware.co.uk
Sun Aug 12 10:30:45 CEST 2012
New methods are provided to:
- get the available equalizer presets;
- get the available frequency bands (useful for creating a UI);
- create a new default equalizer, or create a new equalizer from a preset;
- release a previously created equalizer;
- get/set preamp and individual frequency amplification values;
- get/set an equalizer on a media player.
Equalizer settings are persistent, can be made whether media is currently playing or not and will automatically be applied to subsequently played media.
---
include/vlc/libvlc_media_player.h | 185 ++++++++++++++++++++++++++++++
lib/audio.c | 152 ++++++++++++++++++++++++
lib/libvlc.sym | 13 +++
lib/media_player.c | 52 +++++++++
lib/media_player_internal.h | 13 +++
modules/audio_filter/equalizer.c | 11 --
modules/audio_filter/equalizer_presets.h | 16 +++
src/audio_output/common.c | 7 ++
8 files changed, 438 insertions(+), 11 deletions(-)
diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index 809ed5f..f797b8d 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -110,6 +110,13 @@ typedef enum libvlc_navigate_mode_t
} libvlc_navigate_mode_t;
/**
+ * Opaque equalizer handle.
+ *
+ * An equalizer can be associated with a media player.
+ */
+typedef struct libvlc_equalizer_t libvlc_equalizer_t;
+
+/**
* Create an empty Media Player object
*
* \param p_libvlc_instance the libvlc instance in which the Media Player
@@ -1578,6 +1585,184 @@ LIBVLC_API int64_t libvlc_audio_get_delay( libvlc_media_player_t *p_mi );
*/
LIBVLC_API int libvlc_audio_set_delay( libvlc_media_player_t *p_mi, int64_t i_delay );
+/**
+ * Get the number of equalizer presets.
+ *
+ * \return number of presets
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API unsigned libvlc_audio_equalizer_get_preset_count( void );
+
+/**
+ * Get the name of a particular equalizer preset.
+ *
+ * This name can be used, for example, to prepare a preset label or menu in a user
+ * interface.
+ *
+ * \param i_index index of the preset, counting from zero
+ * \return preset name, or NULL if there is no such preset
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API const char *libvlc_audio_equalizer_get_preset_name( int i_index );
+
+/**
+ * Get the number of distinct frequency bands for an equalizer.
+ *
+ * \return number of frequency bands
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API unsigned libvlc_audio_equalizer_get_band_count( void );
+
+/**
+ * Get a particular equalizer frequency band.
+ *
+ * This value can be used, for example, to create a label for an equalizer band control
+ * in a user interface.
+ *
+ * \param i_index index of the band, counting from zero
+ * \return equalizer band frequency, or -1 if there is no such band
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API float libvlc_audio_equalizer_get_band_frequency( int i_index );
+
+/**
+ * Create a new default equalizer, with all frequency values zeroed.
+ *
+ * The new equalizer can subsequently be associated with a media player by using
+ * libvlc_media_player_set_equalizer().
+ *
+ * When the application is finished with a particular equalizer instance it should
+ * disassociate it from the media player by invoking libvlc_media_player_set_equalizer(NULL)
+ * and then free it by using libvlc_audio_equalizer_release().
+ *
+ * It is the responsibility of the application itself to deal wth the lifecycle management
+ * of equalizer instances, and not the responsibilty of libvlc.
+ *
+ * \return opaque equalizer handle, or NULL on error
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API libvlc_equalizer_t *libvlc_audio_equalizer_new( void );
+
+/**
+ * Create a new equalizer, with initial frequency values copied from an existing
+ * preset.
+ *
+ * The new equalizer can subsequently be associated with a media player by using
+ * libvlc_media_player_set_equalizer().
+ *
+ * When the application is finished with a particular equalizer instance it should
+ * disassociate it from the media player by invoking libvlc_media_player_set_equalizer(NULL)
+ * and then free it by using libvlc_audio_equalizer_release().
+ *
+ * It is the responsibility of the application itself to deal with the lifecycle management
+ * of equalizer instances, and not the responsibilty of libvlc.
+ *
+ * \param i_index index of the preset, counting from zero
+ * \return opaque equalizer handle, or NULL on error
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API libvlc_equalizer_t *libvlc_audio_equalizer_new_from_preset( int i_index );
+
+/**
+ * Free a previously created equalizer.
+ *
+ * The equalizer was previously created by using libvlc_audio_equalizer_new() or
+ * libvlc_audio_equalizer_new_from_preset().
+ *
+ * An application must first disassociate the equalizer from any media player to which
+ * it is attached, by invoking libvlc_media_player_set_equalizer(NULL), before releasing
+ * the equalizer.
+ *
+ * \param p_equalizer opaque equalizer handle
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API void libvlc_audio_equalizer_release( libvlc_equalizer_t *p_equalizer );
+
+/**
+ * Set a new pre-amplification value for an equalizer.
+ *
+ * The new value will be stored in the equalizer immediately, but will not be applied to
+ * any associated media player audio output until libvlc_media_player_set_equalizer() is
+ * invoked, or media is played via libvlc_media_player_play().
+ *
+ * \param p_equalizer opaque equalizer handle
+ * \param f_preamp preamp value
+ * \return zero on success, -1 on error
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API int libvlc_audio_equalizer_set_preamp( libvlc_equalizer_t *p_equalizer, float f_preamp );
+
+/**
+ * Get the current pre-amplification value from an equalizer.
+ *
+ * \param p_equalizer opaque equalizer handle
+ * \return preamp value
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API float libvlc_audio_equalizer_get_preamp( libvlc_equalizer_t *p_equalizer );
+
+/**
+ * Set a new amplification value for a particular equalizer frequency band.
+ *
+ * The new value will be stored in the equalizer immediately, but will not be applied to
+ * any associated media player audio output until libvlc_media_player_set_equalizer() is
+ * invoked, or new media is played via libvlc_media_player_play().
+ *
+ * \param p_equalizer opaque equalizer handle
+ * \param f_amp amplification value
+ * \param i_band index, counting from zero, of the frequency band to set
+ * \return zero on success, -1 on error
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API int libvlc_audio_equalizer_set_amp_at_index( libvlc_equalizer_t *p_equalizer, float f_amp, int i_band );
+
+/**
+ * Get the amplification value for a particular equalizer frequency band.
+ *
+ * \param p_equalizer opaque equalizer handle
+ * \param i_band index, counting from zero, of the frequency band to get
+ * \return amplification value; this will also return zero if there is no such frequency band
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API float libvlc_audio_equalizer_get_amp_at_index( libvlc_equalizer_t *p_equalizer, int i_band );
+
+/**
+ * Associate an equalizer with a media player.
+ *
+ * The equalizer is first created by using libvlc_audio_equalizer_new() or
+ * libvlc_audio_equalizer_new_from_preset().
+ *
+ * It is possible to associate new equalizer settings with a media player whether the
+ * media player is currently playing media or not.
+ *
+ * Invoking this method will immediately apply the new equalizer settings to the audio
+ * output of the currently playing media if there is any.
+ *
+ * If there is no currently playing media, the new equalizer settings will be applied
+ * later if and when new media is played.
+ *
+ * Equalizer settings will automatically be applied to subsequently played media.
+ *
+ * To disassociate an equalizer from a media player, for example before freeing a no-
+ * longer needed equalizer instance or simply to disable the equalizer, invoke this
+ * method passing NULL for the p_equalizer parameter.
+ *
+ * \param p_mi opaque media player handle
+ * \param p_equalizer opaque equalizer handle, or NULL to disable the equalizer for this media player
+ * \return zero on success, -1 on error
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API int libvlc_media_player_set_equalizer( libvlc_media_player_t *p_mi, libvlc_equalizer_t *p_equalizer );
+
+/**
+ * Get the current equalizer associated with a media player.
+ *
+ * \param p_mi opaque media player handle
+ * \return opaque equalizer handle, or NULL if there is no equalizer associated with this media player
+ * \version LibVLC 2.1.0 or later
+ */
+LIBVLC_API libvlc_equalizer_t *libvlc_media_player_get_equalizer( libvlc_media_player_t *p_mi );
+
/** @} audio */
/** @} media_player */
diff --git a/lib/audio.c b/lib/audio.c
index 27d7cd4..8e7b959 100644
--- a/lib/audio.c
+++ b/lib/audio.c
@@ -42,6 +42,8 @@
#include "libvlc_internal.h"
#include "media_player_internal.h"
+#include "modules/audio_filter/equalizer_presets.h"
+
/*
* Remember to release the returned audio_output_t since it is locked at
* the end of this function.
@@ -507,3 +509,153 @@ int libvlc_audio_set_delay( libvlc_media_player_t *p_mi, int64_t i_delay )
}
return ret;
}
+
+/*****************************************************************************
+ * libvlc_audio_equalizer_get_preset_count : Get the number of equalizer presets
+ *****************************************************************************/
+unsigned libvlc_audio_equalizer_get_preset_count( void )
+{
+ return NB_PRESETS;
+}
+
+/*****************************************************************************
+ * libvlc_audio_equalizer_get_preset_name : Get the name for a preset
+ *****************************************************************************/
+const char *libvlc_audio_equalizer_get_preset_name( int i_index )
+{
+ if ( i_index < 0 || i_index >= NB_PRESETS )
+ return NULL;
+
+ return preset_list_text[ i_index ];
+}
+
+/*****************************************************************************
+ * libvlc_audio_equalizer_get_band_count : Get the number of equalizer frequency bands
+ *****************************************************************************/
+unsigned libvlc_audio_equalizer_get_band_count( void )
+{
+ return EQZ_BANDS_MAX;
+}
+
+/*****************************************************************************
+ * libvlc_audio_equalizer_get_band_frequency : Get the frequency for a band
+ *****************************************************************************/
+float libvlc_audio_equalizer_get_band_frequency( int i_index )
+{
+ if ( i_index < 0 || i_index >= EQZ_BANDS_MAX )
+ return -1;
+
+ return f_vlc_frequency_table_10b[ i_index ];
+}
+
+/*****************************************************************************
+ * libvlc_audio_equalizer_new : Create a new audio equalizer with zeroed values
+ *****************************************************************************/
+libvlc_equalizer_t *libvlc_audio_equalizer_new( void )
+{
+ libvlc_equalizer_t *p_equalizer;
+
+ p_equalizer = malloc( sizeof( *p_equalizer ) );
+ if ( p_equalizer == NULL )
+ return NULL;
+
+ p_equalizer->f_preamp = 0.0;
+
+ for ( int i = 0; i < EQZ_BANDS_MAX; i++ )
+ p_equalizer->f_amp[ i ] = 0.0;
+
+ return p_equalizer;
+}
+
+/*****************************************************************************
+ * libvlc_audio_equalizer_new_from_preset : Create a new audio equalizer based on a preset
+ *****************************************************************************/
+libvlc_equalizer_t *libvlc_audio_equalizer_new_from_preset( int i_index )
+{
+ libvlc_equalizer_t *p_equalizer;
+
+ if ( i_index < 0 || i_index >= NB_PRESETS )
+ return NULL;
+
+ p_equalizer = libvlc_audio_equalizer_new();
+ if ( !p_equalizer )
+ return NULL;
+
+ p_equalizer->f_preamp = eqz_preset_10b[ i_index ].f_preamp;
+
+ for ( int i = 0; i < EQZ_BANDS_MAX; i++ )
+ p_equalizer->f_amp[ i ] = eqz_preset_10b[ i_index ].f_amp[ i ];
+
+ return p_equalizer;
+}
+
+/*****************************************************************************
+ * libvlc_audio_equalizer_release : Release a previously created equalizer
+ *****************************************************************************/
+void libvlc_audio_equalizer_release( libvlc_equalizer_t *p_equalizer )
+{
+ if ( p_equalizer )
+ free( p_equalizer );
+}
+
+/*****************************************************************************
+ * libvlc_audio_equalizer_set_preamp : Set the preamp value for an equalizer
+ *****************************************************************************/
+int libvlc_audio_equalizer_set_preamp( libvlc_equalizer_t *p_equalizer, float f_preamp )
+{
+ if ( !p_equalizer )
+ return -1;
+
+ if ( f_preamp < -20.0 )
+ f_preamp = -20.0;
+ else if ( f_preamp > 20.0 )
+ f_preamp = 20.0;
+
+ p_equalizer->f_preamp = f_preamp;
+ return 0;
+}
+
+/*****************************************************************************
+ * libvlc_audio_equalizer_get_preamp : Get the preamp value for an equalizer
+ *****************************************************************************/
+float libvlc_audio_equalizer_get_preamp( libvlc_equalizer_t *p_equalizer )
+{
+ if ( !p_equalizer )
+ return 0;
+
+ return p_equalizer->f_preamp;
+}
+
+/*****************************************************************************
+ * libvlc_audio_equalizer_set_amp_at_index : Set the amplification value for an equalizer band
+ *****************************************************************************/
+int libvlc_audio_equalizer_set_amp_at_index( libvlc_equalizer_t *p_equalizer, float f_amp, int i_band )
+{
+ if ( !p_equalizer )
+ return -1;
+
+ if ( i_band < 0 || i_band >= EQZ_BANDS_MAX )
+ return -1;
+
+ if ( f_amp < -20.0 )
+ f_amp = -20.0;
+ else if ( f_amp > 20.0 )
+ f_amp = 20.0;
+
+ p_equalizer->f_amp[ i_band ] = f_amp;
+ return 0;
+}
+
+/*****************************************************************************
+ * libvlc_audio_equalizer_get_amp_at_index : Get the amplification value for an equalizer band
+ *****************************************************************************/
+float libvlc_audio_equalizer_get_amp_at_index( libvlc_equalizer_t *p_equalizer, int i_band )
+{
+ if ( !p_equalizer )
+ return 0;
+
+ if ( i_band < 0 || i_band >= EQZ_BANDS_MAX )
+ return 0;
+
+ return p_equalizer->f_amp[ i_band ];
+}
diff --git a/lib/libvlc.sym b/lib/libvlc.sym
index 974e04f..93238f7 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -3,6 +3,17 @@ libvlc_clearerr
libvlc_printerr
libvlc_vprinterr
libvlc_add_intf
+libvlc_audio_equalizer_get_amp_at_index
+libvlc_audio_equalizer_get_band_count
+libvlc_audio_equalizer_get_band_frequency
+libvlc_audio_equalizer_get_preamp
+libvlc_audio_equalizer_get_preset_count
+libvlc_audio_equalizer_get_preset_name
+libvlc_audio_equalizer_new
+libvlc_audio_equalizer_new_from_preset
+libvlc_audio_equalizer_release
+libvlc_audio_equalizer_set_amp_at_index
+libvlc_audio_equalizer_set_preamp
libvlc_audio_output_device_count
libvlc_audio_output_device_id
libvlc_audio_output_device_longname
@@ -122,6 +133,7 @@ libvlc_media_player_get_agl
libvlc_media_player_get_chapter
libvlc_media_player_get_chapter_count
libvlc_media_player_get_chapter_count_for_title
+libvlc_media_player_get_equalizer
libvlc_media_player_get_fps
libvlc_media_player_get_hwnd
libvlc_media_player_get_length
@@ -148,6 +160,7 @@ libvlc_media_player_release
libvlc_media_player_retain
libvlc_media_player_set_agl
libvlc_media_player_set_chapter
+libvlc_media_player_set_equalizer
libvlc_media_player_set_hwnd
libvlc_media_player_set_media
libvlc_media_player_set_nsobject
diff --git a/lib/media_player.c b/lib/media_player.c
index a41b8c7..f2cb46d 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -34,11 +34,14 @@
#include <vlc_input.h>
#include <vlc_vout.h>
#include <vlc_keys.h>
+#include <vlc_aout_intf.h>
#include "libvlc_internal.h"
#include "media_internal.h" // libvlc_media_set_state()
#include "media_player_internal.h"
+#include "modules/audio_filter/equalizer_presets.h"
+
/*
* mapping of libvlc_navigate_mode_t to vlc_action_t
*/
@@ -482,6 +485,9 @@ libvlc_media_player_new( libvlc_instance_t *instance )
var_Create (mp, "amem-rate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
var_Create (mp, "amem-channels", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
+ var_Create (mp, "equalizer-preamp", VLC_VAR_FLOAT );
+ var_Create (mp, "equalizer-bands", VLC_VAR_STRING );
+
mp->p_md = NULL;
mp->state = libvlc_NothingSpecial;
mp->p_libvlc_instance = instance;
@@ -1409,3 +1415,49 @@ void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi )
vlc_object_release( p_input_thread );
}
}
+
+int libvlc_media_player_set_equalizer( libvlc_media_player_t *p_mi, libvlc_equalizer_t *p_equalizer )
+{
+ if ( !p_mi )
+ return -1;
+
+ p_mi->p_equalizer = p_equalizer;
+
+ if ( p_equalizer )
+ {
+ aout_EnableFilter( p_mi, "equalizer", true );
+
+ var_SetFloat( p_mi, "equalizer-preamp", p_equalizer->f_preamp );
+
+ // This implementation slightly adapted from modules/audio_filter/equalizer.c
+ char *psz_bands = NULL;
+ for ( int i = 0; i < EQZ_BANDS_MAX; i++ )
+ {
+ lldiv_t d;
+ char *psz;
+
+ d = lldiv( p_equalizer->f_amp[i] * 10000000, 10000000 );
+ if ( asprintf( &psz, "%s %lld.%07llu", psz_bands ? psz_bands : "", d.quot, d.rem ) == -1 )
+ {
+ free( psz_bands );
+ return -1;
+ }
+ free( psz_bands );
+ psz_bands = psz;
+ }
+ var_SetString( p_mi, "equalizer-bands", psz_bands );
+ free( psz_bands );
+ }
+ else
+ aout_EnableFilter( p_mi, "equalizer", false );
+
+ return 0;
+}
+
+libvlc_equalizer_t *libvlc_media_player_get_equalizer( libvlc_media_player_t *p_mi )
+{
+ if ( !p_mi )
+ return NULL;
+
+ return p_mi->p_equalizer;
+}
diff --git a/lib/media_player_internal.h b/lib/media_player_internal.h
index 185f183..ecf994c 100644
--- a/lib/media_player_internal.h
+++ b/lib/media_player_internal.h
@@ -34,6 +34,8 @@
#include <vlc/libvlc_media.h>
#include <vlc_input.h>
+#include "modules/audio_filter/equalizer_presets.h"
+
struct libvlc_media_player_t
{
VLC_COMMON_MEMBERS
@@ -52,6 +54,8 @@ struct libvlc_media_player_t
libvlc_media_t * p_md; /* current media descriptor */
libvlc_event_manager_t * p_event_manager;
libvlc_state_t state;
+
+ libvlc_equalizer_t *p_equalizer;
};
/* Media player - audio, video */
@@ -62,4 +66,13 @@ libvlc_track_description_t * libvlc_get_track_description(
libvlc_media_player_t *p_mi,
const char *psz_variable );
+/**
+ * Internal equalizer structure.
+ */
+struct libvlc_equalizer_t
+{
+ float f_preamp;
+ float f_amp[EQZ_BANDS_MAX];
+};
+
#endif
diff --git a/modules/audio_filter/equalizer.c b/modules/audio_filter/equalizer.c
index 1f88a15..c152d2d 100644
--- a/modules/audio_filter/equalizer.c
+++ b/modules/audio_filter/equalizer.c
@@ -232,17 +232,6 @@ typedef struct
} eqz_config_t;
-/* The frequency tables */
-static const float f_vlc_frequency_table_10b[EQZ_BANDS_MAX] =
-{
- 60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000,
-};
-
-static const float f_iso_frequency_table_10b[EQZ_BANDS_MAX] =
-{
- 31.25, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000,
-};
-
/* Equalizer coefficient calculation function based on equ-xmms */
static void EqzCoeffs( int i_rate, float f_octave_percent,
bool b_use_vlc_freqs,
diff --git a/modules/audio_filter/equalizer_presets.h b/modules/audio_filter/equalizer_presets.h
index 0c0c812..f0830ad 100644
--- a/modules/audio_filter/equalizer_presets.h
+++ b/modules/audio_filter/equalizer_presets.h
@@ -21,6 +21,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
+#ifndef _EQUALIZER_PRESETS_H
+#define _EQUALIZER_PRESETS_H 1
+
/*****************************************************************************
* Equalizer presets
*****************************************************************************/
@@ -30,6 +33,17 @@
#define EQZ_BANDS_MAX 10
+/* The frequency tables */
+static const float f_vlc_frequency_table_10b[EQZ_BANDS_MAX] =
+{
+ 60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000,
+};
+
+static const float f_iso_frequency_table_10b[EQZ_BANDS_MAX] =
+{
+ 31.25, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000,
+};
+
#define NB_PRESETS 18
static const char *const preset_list[NB_PRESETS] = {
"flat", "classical", "club", "dance", "fullbass", "fullbasstreble",
@@ -132,3 +146,5 @@ static const eqz_preset_t eqz_preset_10b[NB_PRESETS] =
{ 8, 5.6, -1.11022e-15, -5.6, -4.8, -1.11022e-15, 8, 9.6, 9.6, 8.8 }
},
};
+
+#endif
diff --git a/src/audio_output/common.c b/src/audio_output/common.c
index c50883b..25f6ad0 100644
--- a/src/audio_output/common.c
+++ b/src/audio_output/common.c
@@ -88,6 +88,9 @@ audio_output_t *aout_New( vlc_object_t * p_parent )
var_Create (aout, "mute", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
var_AddCallback (aout, "mute", var_Copy, p_parent);
+ var_AddCallback (p_parent, "equalizer-preamp", var_Copy, aout );
+ var_AddCallback (p_parent, "equalizer-bands", var_Copy, aout );
+
/* Visualizations */
var_Create (aout, "visual", VLC_VAR_STRING | VLC_VAR_HASCHOICE);
text.psz_string = _("Visualizations");
@@ -197,6 +200,10 @@ void aout_Destroy (audio_output_t *aout)
var_DelCallback (aout, "mute", var_Copy, aout->p_parent);
var_SetFloat (aout, "volume", -1.f);
var_DelCallback (aout, "volume", var_Copy, aout->p_parent);
+
+ var_DelCallback (aout->p_parent, "equalizer-bands", var_Copy, aout);
+ var_DelCallback (aout->p_parent, "equalizer-preamp", var_Copy, aout);
+
vlc_object_release (aout);
}
--
1.7.9.5
More information about the vlc-devel
mailing list