[vlc-devel] [PATCH] Add new API to libvlc for persistent equalizer settings.

Mark Lee mark.lee at capricasoftware.co.uk
Wed Aug 29 21:26:47 CEST 2012


Sigh...

I need to do some more testing on this. I have found instances where the
equalizer is not restoring previously set values and I need to work out if
it's just my test application that is broken or actually the patch itself
that is broken.

Please disregard this patch for now pending further testing.

On 28 August 2012 20:29, Mark Lee <mark.lee at capricasoftware.co.uk> wrote:

> 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;
>  - 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        |  167
> ++++++++++++++++++++++++++++++
>  lib/audio.c                              |  149 ++++++++++++++++++++++++++
>  lib/libvlc.sym                           |   12 +++
>  lib/media_player.c                       |   33 ++++++
>  lib/media_player_internal.h              |   11 ++
>  modules/audio_filter/equalizer.c         |   24 +++--
>  modules/audio_filter/equalizer_presets.h |   16 +++
>  7 files changed, 401 insertions(+), 11 deletions(-)
>
> diff --git a/include/vlc/libvlc_media_player.h
> b/include/vlc/libvlc_media_player.h
> index aefef02..64727e8 100644
> --- a/include/vlc/libvlc_media_player.h
> +++ b/include/vlc/libvlc_media_player.h
> @@ -121,6 +121,13 @@ typedef enum libvlc_navigate_mode_t
>  } libvlc_navigate_mode_t;
>
>  /**
> + * Opaque equalizer handle.
> + *
> + * An equalizer can be applied to 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
> @@ -1626,6 +1633,166 @@ 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 u_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( unsigned
> u_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 band frequency.
> + *
> + * This value can be used, for example, to create a label for an
> equalizer band control
> + * in a user interface.
> + *
> + * \param u_index index of the band, counting from zero
> + * \return equalizer band frequency (Hz), or -1 if there is no such band
> + * \version LibVLC 2.1.0 or later
> + */
> +LIBVLC_API float libvlc_audio_equalizer_get_band_frequency( unsigned
> u_index );
> +
> +/**
> + * Create a new default equalizer, with all frequency values zeroed.
> + *
> + * The new equalizer can subsequently be applied to a media player by
> invoking
> + * libvlc_media_player_set_equalizer().
> + *
> + * The returned handle should be freed via
> libvlc_audio_equalizer_release() when
> + * it is no longer needed.
> + *
> + * \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 applied to a media player by
> invoking
> + * libvlc_media_player_set_equalizer().
> + *
> + * The returned handle should be freed via
> libvlc_audio_equalizer_release() when
> + * it is no longer needed.
> + *
> + * \param u_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(
> unsigned u_index );
> +
> +/**
> + * Release a previously created equalizer instance.
> + *
> + * The equalizer was previously created by using
> libvlc_audio_equalizer_new() or
> + * libvlc_audio_equalizer_new_from_preset().
> + *
> + * It is safe to invoke this method with a NULL p_equalizer parameter for
> no effect.
> + *
> + * \param p_equalizer opaque equalizer handle, or NULL
> + * \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 equalizer settings are subsequently applied to a media player
> by invoking
> + * libvlc_media_player_set_equalizer().
> + *
> + * \param p_equalizer opaque equalizer handle
> + * \param f_preamp preamp value (-20.0 to 20.0 Hz)
> + * \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 (Hz)
> + * \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 equalizer settings are subsequently applied to a media player
> by invoking
> + * libvlc_media_player_set_equalizer().
> + *
> + * \param p_equalizer opaque equalizer handle
> + * \param f_amp amplification value (-20.0 to 20.0 Hz)
> + * \param u_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, unsigned u_band );
> +
> +/**
> + * Get the amplification value for a particular equalizer frequency band.
> + *
> + * \param p_equalizer opaque equalizer handle
> + * \param u_band index, counting from zero, of the frequency band to get
> + * \return amplification value (Hz); 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, unsigned u_band );
> +
> +/**
> + * Apply new equalizer settings to a media player.
> + *
> + * The equalizer is first created by invoking
> libvlc_audio_equalizer_new() or
> + * libvlc_audio_equalizer_new_from_preset().
> + *
> + * It is possible to apply new equalizer settings to 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 disable the equalizer for a media player invoke this method passing
> NULL for the
> + * p_equalizer parameter.
> + *
> + * The media player does not keep a reference to the supplied equalizer
> so it is safe
> + * for an application to release the equalizer reference any time after
> this method
> + * returns.
> + *
> + * \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 );
> +
>  /** @} audio */
>
>  /** @} media_player */
> diff --git a/lib/audio.c b/lib/audio.c
> index 5a5ebd3..dfe9354 100644
> --- a/lib/audio.c
> +++ b/lib/audio.c
> @@ -449,3 +449,152 @@ 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( unsigned u_index )
> +{
> +    if ( u_index >= NB_PRESETS )
> +        return NULL;
> +
> +    return preset_list_text[ u_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( unsigned u_index )
> +{
> +    if ( u_index >= EQZ_BANDS_MAX )
> +        return -1.f;
> +
> +    return f_vlc_frequency_table_10b[ u_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 ( unlikely( p_equalizer == NULL ) )
> +        return NULL;
> +
> +    p_equalizer->f_preamp = 0.f;
> +
> +    for ( unsigned i = 0; i < EQZ_BANDS_MAX; i++ )
> +        p_equalizer->f_amp[ i ] = 0.f;
> +
> +    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( unsigned
> u_index )
> +{
> +    libvlc_equalizer_t *p_equalizer;
> +
> +    if ( u_index >= NB_PRESETS )
> +        return NULL;
> +
> +    p_equalizer = malloc( sizeof( *p_equalizer ) );
> +    if ( unlikely( p_equalizer == NULL ) )
> +        return NULL;
> +
> +    p_equalizer->f_preamp = eqz_preset_10b[ u_index ].f_preamp;
> +
> +    for ( unsigned i = 0; i < EQZ_BANDS_MAX; i++ )
> +        p_equalizer->f_amp[ i ] = eqz_preset_10b[ u_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 )
> +{
> +    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.0f )
> +        f_preamp = -20.0f;
> +    else if ( f_preamp > 20.0f )
> +        f_preamp = 20.0f;
> +
> +    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.f;
> +
> +    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, unsigned u_band )
> +{
> +    if ( !p_equalizer )
> +        return -1;
> +
> +    if ( u_band >= EQZ_BANDS_MAX )
> +        return -1;
> +
> +    if ( f_amp < -20.0f )
> +        f_amp = -20.0f;
> +    else if ( f_amp > 20.0f )
> +        f_amp = 20.0f;
> +
> +    p_equalizer->f_amp[ u_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, unsigned u_band )
> +{
> +    if ( !p_equalizer )
> +        return 0.f;
> +
> +    if ( u_band >= EQZ_BANDS_MAX )
> +        return 0.f;
> +
> +    return p_equalizer->f_amp[ u_band ];
> +}
> diff --git a/lib/libvlc.sym b/lib/libvlc.sym
> index 42dad5c..7c1874f 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_list_get
> @@ -150,6 +161,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..fd04222 100644
> --- a/lib/media_player.c
> +++ b/lib/media_player.c
> @@ -34,6 +34,7 @@
>  #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()
> @@ -482,6 +483,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 +1413,32 @@ 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_equalizer )
> +    {
> +        aout_EnableFilter( p_mi, "equalizer", false );
> +        return 0;
> +    }
> +
> +    var_SetFloat( p_mi, "equalizer-preamp", p_equalizer->f_preamp );
> +
> +    char *psz_bands = NULL;
> +    for ( int i = 0; i < EQZ_BANDS_MAX; i++ )
> +    {
> +        char *psz;
> +        if ( asprintf( &psz, "%s %.07f", psz_bands ? psz_bands : "",
> p_equalizer->f_amp[i] ) == -1 )
> +        {
> +            free( psz_bands );
> +            return -1;
> +        }
> +        free( psz_bands );
> +        psz_bands = psz;
> +    }
> +    var_SetString( p_mi, "equalizer-bands", psz_bands );
> +    free( psz_bands );
> +
> +    aout_EnableFilter( p_mi, "equalizer", true );
> +    return 0;
> +}
> diff --git a/lib/media_player_internal.h b/lib/media_player_internal.h
> index 185f183..27fbf1f 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
> @@ -62,4 +64,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 41a89eb..1a36eac 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,
> @@ -413,6 +402,13 @@ static int EqzInit( filter_t *p_filter, int i_rate )
>      var_AddCallback( p_aout, "equalizer-preamp", PreampCallback, p_sys );
>      var_AddCallback( p_aout, "equalizer-2pass", TwoPassCallback, p_sys );
>
> +    /* Preamp and bands go together, so we only need check for one or the
> other, not both */
> +    if ( var_Type( p_aout->p_parent, "equalizer-preamp" ) )
> +    {
> +        var_AddCallback( p_aout->p_parent, "equalizer-preamp",
> PreampCallback, p_sys );
> +        var_AddCallback( p_aout->p_parent, "equalizer-bands",
> BandsCallback, p_sys );
> +    }
> +
>      msg_Dbg( p_filter, "equalizer loaded for %d Hz with %d bands %d pass",
>                          i_rate, p_sys->i_band, p_sys->b_2eqz ? 2 : 1 );
>      for( i = 0; i < p_sys->i_band; i++ )
> @@ -498,6 +494,12 @@ static void EqzClean( filter_t *p_filter )
>      filter_sys_t *p_sys = p_filter->p_sys;
>      vlc_object_t *p_aout = p_filter->p_parent;
>
> +    if ( var_Type( p_aout->p_parent, "equalizer-preamp" ) )
> +    {
> +        var_DelCallback( p_aout->p_parent, "equalizer-preamp",
> PreampCallback, p_sys );
> +        var_DelCallback( p_aout->p_parent, "equalizer-bands",
> BandsCallback, p_sys );
> +    }
> +
>      var_DelCallback( p_aout, "equalizer-bands", BandsCallback, p_sys );
>      var_DelCallback( p_aout, "equalizer-preset", PresetCallback, p_sys );
>      var_DelCallback( p_aout, "equalizer-preamp", PreampCallback, p_sys );
> 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
> --
> 1.7.9.5
>
>


-- 
Mark Lee
mark1 'at' mark-lee.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20120829/b7de7639/attachment.html>


More information about the vlc-devel mailing list