[vlc-devel] [PATCH 2/6] equalizer: Add support for extra sets of ISO bands
Rémi Denis-Courmont
remi at remlab.net
Sat Nov 28 15:36:21 CET 2015
On Saturday 28 November 2015 00:31:02 Ronald Wright wrote:
> Note: This patch cannot be applied without patch 1, and patches 2 through 6
> must be applied all together.
>
> Let me know if the string for BANDS_LONGTEXT is still too long.
> ---
> include/vlc_eqz_util.h | 92 +++++
> modules/audio_filter/equalizer.c | 134 +++---
> modules/audio_filter/equalizer_presets.h | 672
> +++++++++++++++++++++++++++++-- src/misc/eqz_util.c |
> 297 ++++++++++++++
> 4 files changed, 1116 insertions(+), 79 deletions(-)
> create mode 100644 include/vlc_eqz_util.h
> create mode 100644 src/misc/eqz_util.c
>
> diff --git a/include/vlc_eqz_util.h b/include/vlc_eqz_util.h
> new file mode 100644
> index 0000000..25bc421
> --- /dev/null
> +++ b/include/vlc_eqz_util.h
> @@ -0,0 +1,92 @@
> +/**************************************************************************
> *** + * vlc_eqz_util.h: Equalizer utility functions
> +
> ***************************************************************************
> ** + * Copyright (C) 2015 Ronald Wright
> + * $Id$
> + *
> + * Author: Ronald Wright <logiconcepts819 at gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License as published by
> + * the Free Software Foundation; either version 2.1 of the License, or + *
> (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser 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. +
> ***************************************************************************
> **/ +
> +#ifndef VLC_EQZ_UTIL_H
> +#define VLC_EQZ_UTIL_H
> +
> +/**
> + * \file
> + * This file is the interface definition of several useful equalizer
> utility + * functions (implementation in src/misc/eqz_util.c)
> + */
> +
> +/**************************************************************************
> *** + * Documentation
> +
> ***************************************************************************
> **/ +
> +/**************************************************************************
> *** + * Type definitions
> +
> ***************************************************************************
> **/ +
> +/**
> + * The preset interpolation data type. This is a pointer to a private
> structure + * defined in misc/eqz_util.c.
> + */
> +typedef struct _vlc_band_parse_t * vlc_band_parse_t;
Non-C-conforming identifier. Also no pointer in typedef please.
> +
> +/**************************************************************************
> *** + * Interpolation routines
> +
> ***************************************************************************
> **/ +
> +/**
> + * Start a new band parser.
> + *
> + * \param p_obj The object that holds VLC object data
> + * \param p_parser_ctx The object that shall hold band parse data
> + * \param psz_bands The bands string (e.g. "2 0 -2 -4 -2 0 2 4 2 0")
> + * \param i_type The current equalizer type
> + * \param pf_amp An optional memory location to store interpolated values
> + * \return VLC_SUCCESS for success or VLC_ENOMEM for memory failure
\retval
> + *
> + * \note If pf_bands is NULL, then memory is automatically allocated in the
> + * preset parser data context according to the given equalizer type.
> If + * the provided bands string provides a valid number of bands
> (i.e. 10, + * 15, or 31), then the preset values are interpolated
> according to the + * current equalizer type. Otherwise, each value is
> mapped to the + * corresponding band of the current equalizer type,
> starting at the + * lowest band, until there are no more spaces or
> values left. + */
> +VLC_API int vlc_eqz_util_band_parser_init( vlc_object_t * p_obj,
> + vlc_band_parse_t * p_parse_ctx,
> + const char * psz_bands, int
> i_type, + float * pf_amp );
> +
> +/**
> + * Find the amplification factors from the given band parse context.
> + *
> + * \param interp_ctx The object that holds band parse data
> + * \return A pointer to the amplification array in the context, which
> + * corresponds to either its own memory if a non-NULL value of
> pf_amp + * was provided in vlc_eqz_util_band_parser_init, or pf_amp
> otherwise + */
> +VLC_API const float *
> +vlc_eqz_util_get_amp_array( const vlc_band_parse_t parse_ctx );
> +
> +/**
> + * Destroy the band parse context.
> + *
> + * \param interp_ctx The object that holds band parse data
> + */
> +VLC_API void vlc_eqz_util_band_parser_destroy( vlc_band_parse_t parse_ctx
> ); +
> +#endif
> diff --git a/modules/audio_filter/equalizer.c
> b/modules/audio_filter/equalizer.c index 98a4a7e..c73dda1 100644
> --- a/modules/audio_filter/equalizer.c
> +++ b/modules/audio_filter/equalizer.c
This probably belongs in a separate patch
> diff --git a/src/misc/eqz_util.c b/src/misc/eqz_util.c
> new file mode 100644
> index 0000000..caf0171
> --- /dev/null
> +++ b/src/misc/eqz_util.c
> @@ -0,0 +1,297 @@
> +/**************************************************************************
> *** + * vlc_eqz_util.h: Equalizer utility functions
> +
> ***************************************************************************
> ** + * Copyright (C) 2015 Ronald Wright
> + * $Id$
> + *
> + * Author: Ronald Wright <logiconcepts819 at gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License as published by
> + * the Free Software Foundation; either version 2.1 of the License, or + *
> (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser 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
> +
> ***************************************************************************
> **/ +
> +#ifdef HAVE_CONFIG_H
> +# include "config.h"
> +#endif
> +
> +#include <math.h>
> +#include <vlc_common.h>
> +#include <vlc_charset.h>
> +#include <vlc_interpolation.h>
> +#include <vlc_eqz_util.h>
> +
> +#define EQZ_INCLUDE_MATH_ROUTINES 1
> +#include "../../modules/audio_filter/equalizer_presets.h"
Eeek.
> +
> +/**************************************************************************
> *** + * Documentation : Read vlc_interpolation.h
> +
> ***************************************************************************
> **/ +
> +/**************************************************************************
> *** + * Private types.
> +
> ***************************************************************************
> **/ +
> +struct _vlc_band_parse_t
> +{
> + float * pf_orig_amp;
> + int i_orig_bands;
> + vlc_interpolant_t itp;
> + float * pf_amp;
> + int i_type;
Likely missing flexible array here.
> +};
> +
> +/**************************************************************************
> *** + * Implementation of routines.
> +
> ***************************************************************************
> **/ +
> +/* Determine the most valid equalizer identifier from the number of bands
> and + * a string with a possibly invalid identifier */
> +static char GetValidIdentifier( vlc_object_t *p_obj, int i_cur_type,
> + const char * psz_identifier, int i_bands )
> +{
> + char eqz_identifier;
> + switch( i_bands )
> + {
> + case EQZ_ISO10_BANDS_MAX:
> + /* fall-through */
> + case EQZ_ISO15_BANDS_MAX:
> + /* fall-through */
> + case EQZ_ISO31_BANDS_MAX:
> + {
> + size_t i_id_len = psz_identifier ? strlen( psz_identifier ) :
> 0;
> + if( i_id_len != 1 ||
> + ( psz_identifier[0] != EQZ_VLC_IDENTIFIER &&
> + psz_identifier[0] != EQZ_ISO_IDENTIFIER ) )
> + {
> + eqz_identifier = EqzGetDefaultIdentifier( i_bands );
> + if( i_id_len == 0 )
> + {
> + /* No identifier specified in string */
> + if( i_bands == EQZ_ISO10_BANDS_MAX )
> + {
> + msg_Warn( p_obj, "equalizer identifier not
> specified " + "for 10 bands; assuming VLC bands"
> ); + }
> + }
> + else
> + {
> + /* Found invalid identifier */
> + msg_Warn( p_obj, "invalid equalizer identifier '%s'; "
> + "assuming default equalizer type for %d bands
> ('%c')", + psz_identifier, i_bands, eqz_identifier
> ); + }
> + }
> + else if( i_bands != EQZ_ISO10_BANDS_MAX &&
> + psz_identifier[0] == EQZ_VLC_IDENTIFIER )
> + {
> + /* Found VLC equalizer type for 15 and 31 bands, but we
> only + * provide ISO bands in these cases */
> + eqz_identifier = EQZ_ISO_IDENTIFIER;
> + msg_Warn( p_obj, "equalizer identifier '%s' not defined for
> " + "%d bands; assuming ISO bands", psz_identifier,
> i_bands ); + }
> + else
> + {
> + /* Found VLC or ISO identifier for 10 bands and ISO
> identifier + * for 15 and 31 bands */
> + eqz_identifier = psz_identifier[0];
> + }
> + break;
> + }
> + default:
> + {
> + /* Default is to assume current mode */
> + int i_cur_bands = EqzGetNumBandsByType( i_cur_type );
> + int i_smallest_bands = __MIN( i_cur_bands, i_bands );
> + eqz_identifier = EqzGetIdentifier( i_cur_type );
> + if( i_smallest_bands == 1 )
> + {
> + msg_Warn( p_obj, "found only one band (which is not 10, 15,
> " + "or 31, as it ought to be); assuming it corresponds
> to " + "the first band of the currently active equalizer
> type " + "(%d-band %s equalizer)", i_cur_bands,
> + EqzGetStringIdentifier( eqz_identifier ) );
> + }
> + else
> + {
> + msg_Warn( p_obj, "found unexpected number of bands (%d,
> which " + "is not 10, 15, or 31, as it ought to be);
> assuming the " + "%s%d bands correspond to the %s%d
> bands of the currently " + "active equalizer type
> (%d-band %s equalizer)", i_bands, + i_cur_bands <
> i_bands ? "first " : "", i_smallest_bands, + i_cur_bands
> > i_bands ? "first " : "", i_smallest_bands, +
> i_cur_bands, EqzGetStringIdentifier( eqz_identifier ) ); + }
> + break;
> + }
> + }
> + return eqz_identifier;
> +}
> +
> +/* Try setting up an interpolant */
> +static int SetUpInterpolant( int i_bands, int i_type, float * pf_amp,
> + vlc_interpolant_t * itp )
> +{
> + int i_ret_val = VLC_ENOMEM;
> + float * pf_freq = malloc( i_bands * sizeof( *pf_freq ) );
> + if( likely( pf_freq != NULL ) )
> + {
> + for( int k = 0; k < i_bands; k++ )
> + pf_freq[k] = EqzGetTrueFrequency( i_type, k );
> + i_ret_val = vlc_create_interpolant( itp, pf_freq, pf_amp, i_bands
> ); + free( pf_freq );
> + }
> + return i_ret_val;
> +}
> +
> +int vlc_eqz_util_band_parser_init( vlc_object_t * p_obj,
> + vlc_band_parse_t * p_parse_ctx,
> + const char * psz_bands, int i_type,
> + float * pf_amp )
> +{
> + vlc_band_parse_t parse_ctx;
> + vlc_interpolant_t itp = NULL;
> + float * pf_orig_amp;
> + int i = 0, i_toks = 0;
> +
> + /* Duplicate memory of bands string value */
> + char *p = strdup( psz_bands ), *q = NULL, *saved;
> + if( unlikely( !p ) )
> + return VLC_ENOMEM;
> +
> + /* Allocate memory for storing the context data */
> + int i_ret_val = VLC_ENOMEM;
> + int i_size = EQZ_BANDS_MAX;
> + if( !pf_amp )
> + i_size += EqzGetNumBandsByType( i_type );
> + parse_ctx = malloc( sizeof( *parse_ctx ) + i_size * sizeof( *pf_amp )
> ); + if( likely( parse_ctx != NULL ) )
> + {
> + pf_orig_amp = ( float * ) ( parse_ctx + 1 );
> + if( !pf_amp )
> + pf_amp = pf_orig_amp + EQZ_BANDS_MAX;
> +
> + for( char *tok = strtok_r( p, " ", &saved ); tok != NULL;
> + tok = strtok_r( NULL, " ", &saved ) )
> + {
> + if( i < EQZ_BANDS_MAX )
> + {
> + char *r = tok;
> + float f = us_strtof( tok, &r );
> + if( r == tok || *r != '\0' || isnan( f ) )
> + pf_orig_amp[i++] = 0.f;
> + else
> + pf_orig_amp[i++] = f;
> + }
> +
> + /* Even if we exceed EQZ_BANDS_MAX or encounter malformed
> tokens, + * keep counting the number of tokens */
> + i_toks++;
> + q = tok;
> + }
> +
> + /* Check whether we have a potential identifier at the end of the
> + * string. One way to check is if the last token is numeric. If
> not, + * then we consider it as a potential identifier. */
> + if( q ) /* q is non-NULL if we have at least one token */
> + {
> + char *r = q;
> + float f = us_strtof( q, &r );
> + if( r == q || *r != '\0' || isnan( f ) )
> + {
> + /* In this case, the last token could not be converted into
> a + * float, so we treat it as a potential identifier by
> excluding + * it from all counts */
> + if( i <= EQZ_BANDS_MAX )
> + i--; /* potential identifier found within bounds */
> + i_toks--;
> + }
> + else
> + q = NULL; /* don't treat any tokens as potential
> identifiers */ + }
> +
> + i_ret_val = VLC_SUCCESS;
> + if( i > 0 )
> + {
> + /* Should there be a mismatch in the number or type of bands,
> + * interpolate */
> + char id = GetValidIdentifier( p_obj, i_type, q, i_toks );
> + if( i != EqzGetNumBandsByType( i_type ) ||
> + id != EqzGetIdentifier( i_type ) )
> + {
> + int i_bands_type = EqzGetTypeByNumBands( i_toks, id );
> + if( i_bands_type != EQZ_UNKNOWN_TYPE )
> + /* Try creating the interpolant */
> + i_ret_val = SetUpInterpolant( i, i_bands_type,
> pf_orig_amp, + &itp );
> + }
> + }
> + }
> +
> + /* Check status of i_ret_val. If it is not equal to VLC_SUCCESS, then
> + * clean up. Otherwise, set up structure */
> + if( i_ret_val == VLC_SUCCESS )
> + {
> + parse_ctx->itp = itp;
> + parse_ctx->pf_orig_amp = pf_orig_amp;
> + parse_ctx->i_orig_bands = i;
> + parse_ctx->pf_amp = pf_amp;
> + parse_ctx->i_type = i_type;
> + *p_parse_ctx = parse_ctx;
> + }
> + else
> + {
> + free( parse_ctx );
> + }
> +
> + free( p );
> + return i_ret_val;
> +}
> +
> +const float * vlc_eqz_util_get_amp_array( const vlc_band_parse_t parse_ctx
> ) +{
> + int i_band = EqzGetNumBandsByType( parse_ctx->i_type );
> + if( parse_ctx->itp )
> + {
> + /* Construct the interpolated set of bands */
> + for( int k = 0; k < i_band; k++ )
> + {
> + float f_freq = EqzGetTrueFrequency( parse_ctx->i_type, k );
> + parse_ctx->pf_amp[k] = vlc_interpolate( parse_ctx->itp, f_freq
> ); + }
> + }
> + else
> + {
> + /* Read bands as they are */
> + int k;
> + for( k = 0; k < parse_ctx->i_orig_bands; k++ )
> + parse_ctx->pf_amp[k] = parse_ctx->pf_orig_amp[k];
> + while( k < i_band )
> + parse_ctx->pf_amp[k++] = 0.f;
> + }
> + return parse_ctx->pf_amp;
> +}
> +
> +void vlc_eqz_util_band_parser_destroy( vlc_band_parse_t parse_ctx )
> +{
> + if( likely( parse_ctx ) )
> + {
> + free( parse_ctx->itp );
> + free( parse_ctx );
> + }
> +}
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list