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

Alexey Sokolov alexey at asokolov.org
Tue Aug 28 04:20:23 CEST 2012


28.08.2012 04:37, Mark Lee пишет:
> 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                              |  151 +++++++++++++++++++++++++++
>  lib/libvlc.sym                           |   12 +++
>  lib/media_player.c                       |   35 +++++++
>  lib/media_player_internal.h              |   11 ++
>  modules/audio_filter/equalizer.c         |   24 +++--
>  modules/audio_filter/equalizer_presets.h |   16 +++
>  7 files changed, 405 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..034d255 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.
> @@ -449,3 +451,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;
Please set an error message via libvlc_printerr( "..." ); when an error
is detected.
> +
> +    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;
same here
> +
> +    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;
and here
> +
> +    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;
here
> +
> +    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;
here, etc.
> +
> +    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..4e3e980 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,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..631483d 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


-- 
Best regards,
Alexey "DarthGandalf" Sokolov


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 900 bytes
Desc: OpenPGP digital signature
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20120828/bb243946/attachment.sig>


More information about the vlc-devel mailing list