[vlc-devel] [PATCH v3 02/10] Add utilities for parsing equalizer band strings

Ronald Wright logiconcepts819 at gmail.com
Sun Nov 29 23:09:34 CET 2015


Note:  This patch cannot be applied until after patch 1 is applied.
---
 include/vlc_eqz_util.h |  92 +++++++++++++++
 po/POTFILES.in         |   2 +
 src/Makefile.am        |   6 +-
 src/libvlccore.sym     |  21 ++--
 src/misc/eqz_util.c    | 295 +++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 407 insertions(+), 9 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..b347cae
--- /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
+ * \brief 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;
+
+/*****************************************************************************
+ * Interpolation routines
+ *****************************************************************************/
+
+/**
+ * Start a new band parser.
+ *
+ * \param p_obj The object that holds VLC object data
+ * \param pp_parse_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
+ * \retval VLC_SUCCESS Success
+ * \retval VLC_ENOMEM  Memory failure
+ *
+ * \note If pf_amp 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 ** pp_parse_ctx,
+                                           const char * psz_bands, int i_type,
+                                           float * pf_amp );
+
+/**
+ * Find the amplification factors from the given band parse context.
+ *
+ * \param p_parse_ctx The object that holds band parse data
+ * \return A pointer to the amplification array in the context
+ */
+VLC_API const float *
+vlc_eqz_util_get_amp_array( const vlc_band_parse_t * p_parse_ctx );
+
+/**
+ * Destroy the band parse context.
+ *
+ * \param p_parse_ctx The object that holds band parse data
+ */
+VLC_API void
+vlc_eqz_util_band_parser_destroy( vlc_band_parse_t * p_parse_ctx );
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index db9e4ca..3a2dec2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -16,6 +16,7 @@ include/vlc_configuration.h
 include/vlc_demux.h
 include/vlc/deprecated.h
 include/vlc_epg.h
+include/vlc_eqz_util.h
 include/vlc_es.h
 include/vlc_es_out.h
 include/vlc_events.h
@@ -106,6 +107,7 @@ src/libvlc.h
 src/libvlc-module.c
 src/misc/block.c
 src/misc/cpu.c
+src/misc/eqz_util.c
 src/misc/error.c
 src/misc/es_format.c
 src/misc/events.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 0d534ba..b60257d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -42,6 +42,7 @@ pluginsinclude_HEADERS = \
 	../include/vlc_dialog.h \
 	../include/vlc_demux.h \
 	../include/vlc_epg.h \
+	../include/vlc_eqz_util.h \
 	../include/vlc_es.h \
 	../include/vlc_es_out.h \
 	../include/vlc_events.h \
@@ -435,6 +436,7 @@ SOURCES_libvlc_common = \
 	misc/fifo.c \
 	misc/fourcc.c \
 	misc/fourcc_list.h \
+	misc/eqz_util.c \
 	misc/es_format.c \
 	misc/interpolation.c \
 	misc/picture.c \
@@ -538,7 +540,7 @@ check_PROGRAMS = \
 	test_xmlent \
 	test_headers
 
-TESTS = $(check_PROGRAMS) check_symbols
+TESTS = $(check_PROGRAMS)
 
 test_block_SOURCES = test/block_test.c
 test_block_LDADD = $(LDADD) $(LIBS_libvlccore)
@@ -594,7 +596,7 @@ stamp-revision:
 # Unit/regression test
 ###############################################################################
 
-dist_check_SCRIPTS = check_headers check_symbols
+dist_check_SCRIPTS = check_headers
 
 check-local:
 	for h in `echo $(pkginclude_HEADERS) | sed -e s,\.\./include/,,g`; \
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index f03e451..134f031 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -66,6 +66,7 @@ config_ResetAll
 config_SaveConfigFile
 config_StringEscape
 config_StringUnescape
+convert_xml_special_chars
 date_Change
 date_Decrement
 date_Get
@@ -87,6 +88,8 @@ decoder_SynchroNewPicture
 decoder_SynchroRelease
 decoder_SynchroReset
 decoder_SynchroTrash
+decode_URI
+decode_URI_duplicate
 demux_Delete
 demux_PacketizerDestroy
 demux_PacketizerNew
@@ -103,12 +106,15 @@ dialog_Question
 dialog_Register
 dialog_Unregister
 dialog_VFatal
+encode_URI_component
 EndMD5
+EnsureUTF8
 es_format_Clean
 es_format_Copy
 es_format_Init
 es_format_InitFromVideo
 es_format_IsSimilar
+filename_sanitize
 filter_Blend
 filter_chain_AppendFilter
 filter_chain_AppendFromString
@@ -228,6 +234,7 @@ input_Stop
 input_vaControl
 input_Close
 intf_Create
+IsUTF8
 libvlc_InternalAddIntf
 libvlc_InternalPlay
 libvlc_InternalCleanup
@@ -241,10 +248,7 @@ libvlc_ArtRequest
 vlc_UrlParse
 vlc_UrlClean
 vlc_path2uri
-vlc_uri2path
-vlc_uri_decode
-vlc_uri_decode_duplicate
-vlc_uri_encode
+make_path
 mdate
 module_config_free
 module_config_get
@@ -285,6 +289,7 @@ net_SetCSCov
 net_vaPrintf
 net_Write
 NTPtime64
+path_sanitize
 picture_BlendSubpicture
 picture_CopyPixels
 picture_Hold
@@ -358,6 +363,7 @@ playlist_VolumeSet
 playlist_VolumeUp
 playlist_MuteSet
 playlist_MuteGet
+resolve_xml_special_chars
 sdp_AddAttribute
 sdp_AddMedia
 secstotimestr
@@ -411,6 +417,7 @@ stream_ReadDir
 stream_FilterDefaultReadDir
 str_format_meta
 str_format_time
+str_duration
 subpicture_Delete
 subpicture_New
 subpicture_NewFromPicture
@@ -523,6 +530,9 @@ vlc_interpolant_create
 vlc_interpolant_destroy
 vlc_GetCPUCount
 vlc_CPU
+vlc_eqz_util_band_parser_destroy
+vlc_eqz_util_band_parser_init
+vlc_eqz_util_get_amp_array
 vlc_error
 vlc_event_attach
 vlc_event_detach
@@ -626,7 +636,6 @@ vlc_timer_create
 vlc_timer_destroy
 vlc_timer_getoverrun
 vlc_timer_schedule
-vlc_towc
 vlc_ureduce
 vlc_epg_Init
 vlc_epg_Clean
@@ -689,8 +698,6 @@ xml_Delete
 xml_ReaderCreate
 xml_ReaderDelete
 xml_ReaderReset
-vlc_xml_decode
-vlc_xml_encode
 vlc_keycode2str
 vlc_str2keycode
 fingerprinter_Create
diff --git a/src/misc/eqz_util.c b/src/misc/eqz_util.c
new file mode 100644
index 0000000..838f8d6
--- /dev/null
+++ b/src/misc/eqz_util.c
@@ -0,0 +1,295 @@
+/*****************************************************************************
+ * 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>
+
+#include "../../modules/audio_filter/equalizer_presets.h"
+
+/*****************************************************************************
+ * Documentation : Read vlc_interpolation.h
+ *****************************************************************************/
+
+/*****************************************************************************
+ *  Private types.
+ *****************************************************************************/
+
+struct vlc_band_parse_t
+{
+    int i_orig_bands;
+    vlc_interpolant_t * p_itp;
+    float * pf_amp;
+    int i_type;
+    float f_orig_amp[];
+};
+
+/*****************************************************************************
+ * 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_interpolant_create( 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 ** pp_parse_ctx,
+                                   const char * psz_bands, int i_type,
+                                   float * pf_amp )
+{
+    vlc_band_parse_t * p_parse_ctx;
+    vlc_interpolant_t * p_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 );
+    p_parse_ctx = malloc( sizeof( *p_parse_ctx ) + i_size * sizeof( *pf_amp ) );
+    if( likely( p_parse_ctx != NULL ) )
+    {
+        pf_orig_amp = p_parse_ctx->f_orig_amp;
+        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,
+                                                  &p_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 )
+    {
+        p_parse_ctx->p_itp = p_itp;
+        p_parse_ctx->i_orig_bands = i;
+        p_parse_ctx->pf_amp = pf_amp;
+        p_parse_ctx->i_type = i_type;
+        *pp_parse_ctx = p_parse_ctx;
+    }
+    else
+    {
+        free( p_parse_ctx );
+    }
+
+    free( p );
+    return i_ret_val;
+}
+
+const float * vlc_eqz_util_get_amp_array( const vlc_band_parse_t * p_parse_ctx )
+{
+    int i_band = EqzGetNumBandsByType( p_parse_ctx->i_type );
+    if( p_parse_ctx->p_itp )
+    {
+        /* Construct the interpolated set of bands */
+        for( int k = 0; k < i_band; k++ )
+        {
+            float f_freq = EqzGetTrueFrequency( p_parse_ctx->i_type, k );
+            p_parse_ctx->pf_amp[k] = vlc_interpolate( p_parse_ctx->p_itp, f_freq );
+        }
+    }
+    else
+    {
+        /* Read bands as they are */
+        int k;
+        for( k = 0; k < p_parse_ctx->i_orig_bands; k++ )
+            p_parse_ctx->pf_amp[k] = p_parse_ctx->f_orig_amp[k];
+        while( k < i_band )
+            p_parse_ctx->pf_amp[k++] = 0.f;
+    }
+    return p_parse_ctx->pf_amp;
+}
+
+void vlc_eqz_util_band_parser_destroy( vlc_band_parse_t * p_parse_ctx )
+{
+    if( likely( p_parse_ctx ) )
+    {
+        free( p_parse_ctx->p_itp );
+        free( p_parse_ctx );
+    }
+}
-- 
1.9.1



More information about the vlc-devel mailing list