[vlc-devel] [RFC PATCH 3/7] audio_filter: add ebur128 "audio meter" plugin

Steve Lhomme robux4 at ycbcr.xyz
Mon Aug 17 08:52:55 CEST 2020



On 2020-08-17 8:48, Steve Lhomme wrote:
> On 2020-08-14 15:18, Thomas Guillem wrote:
>> ---
>>   configure.ac                      |   5 +
>>   modules/audio_filter/Makefile.am  |   9 +-
>>   modules/audio_filter/libebur128.c | 290 ++++++++++++++++++++++++++++++
>>   3 files changed, 303 insertions(+), 1 deletion(-)
>>   create mode 100644 modules/audio_filter/libebur128.c
>>
>> diff --git a/configure.ac b/configure.ac
>> index 149c7c926b4..862546e49f3 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -3919,6 +3919,11 @@ dnl  soxr module
>>   dnl
>>   PKG_ENABLE_MODULES_VLC([SOXR], [], [soxr >= 0.1.2], [SoX Resampler 
>> library], [auto])
>> +dnl
>> +dnl  libebur128 module
>> +dnl
>> +PKG_ENABLE_MODULES_VLC([EBUR128], [], [libebur128 >= 1.2.4], [EBU R 
>> 128 standard for loudness normalisation], [auto])
>> +
>>   dnl
>>   dnl  OS/2 KAI plugin
>>   dnl
>> diff --git a/modules/audio_filter/Makefile.am 
>> b/modules/audio_filter/Makefile.am
>> index 279be02040f..028b188bfe2 100644
>> --- a/modules/audio_filter/Makefile.am
>> +++ b/modules/audio_filter/Makefile.am
>> @@ -125,14 +125,21 @@ libsoxr_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) 
>> $(SOXR_CFLAGS)
>>   libsoxr_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(audio_filterdir)'
>>   libsoxr_plugin_la_LIBADD = $(SOXR_LIBS) $(LIBM)
>> +libebur128_plugin_la_SOURCES = audio_filter/libebur128.c
>> +libebur128_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(EBUR128_CFLAGS)
>> +libebur128_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(audio_filterdir)'
>> +libebur128_plugin_la_LIBADD = $(EBUR128_LIBS)
>> +
>>   audio_filter_LTLIBRARIES += \
>>       $(LTLIBsamplerate) \
>>       $(LTLIBsoxr) \
>> +    $(LTLIBebur128) \
>>       libugly_resampler_plugin.la
>>   EXTRA_LTLIBRARIES += \
>>       libbandlimited_resampler_plugin.la \
>>       libsamplerate_plugin.la \
>> -    libsoxr_plugin.la
>> +    libsoxr_plugin.la \
>> +    libebur128_plugin.la
>>   libspeex_resampler_plugin_la_SOURCES = audio_filter/resampler/speex.c
>>   libspeex_resampler_plugin_la_CFLAGS = $(AM_CFLAGS) $(SPEEXDSP_CFLAGS)
>> diff --git a/modules/audio_filter/libebur128.c 
>> b/modules/audio_filter/libebur128.c
>> new file mode 100644
>> index 00000000000..bd5464dc6d1
>> --- /dev/null
>> +++ b/modules/audio_filter/libebur128.c
>> @@ -0,0 +1,290 @@
>> +/***************************************************************************** 
>>
>> + * libebur128.c : libebur128 filter
>> + 
>> ***************************************************************************** 
>>
>> + * Copyright © 2020 Videolabs
>> + *
>> + * 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.
>> + 
>> *****************************************************************************/ 
>>
>> +
>> +#ifdef HAVE_CONFIG_H
>> +# include "config.h"
>> +#endif
>> +
>> +#include <vlc_common.h>
>> +#include <vlc_aout.h>
>> +#include <vlc_filter.h>
>> +#include <vlc_modules.h>
>> +#include <vlc_plugin.h>
>> +
>> +#include <ebur128.h>
>> +
>> +#define UPDATE_INTERVAL VLC_TICK_FROM_MS(400)
>> +
>> +struct filter_sys
>> +{
>> +    ebur128_state *state;
>> +    vlc_tick_t last_update;
>> +    bool new_frames;
>> +};
>> +
>> +static ebur128_state *
>> +CreateEbuR128State(filter_t *filter)
>> +{
>> +    int mode = var_InheritBool(filter, "ebur128-fullmeter")
>> +             ? EBUR128_MODE_TRUE_PEAK|EBUR128_MODE_LRA : EBUR128_MODE_M;
>> +
>> +    ebur128_state *state =
>> +        ebur128_init(filter->fmt_in.audio.i_channels, 
>> filter->fmt_in.audio.i_rate, mode);
>> +    if (state == NULL)
>> +        return NULL;
>> +
>> +    /* TODO: improve */
>> +    unsigned channels_set = 2;
>> +    int error;
>> +    if (filter->fmt_in.audio.i_physical_channels == AOUT_CHANS_5_1
>> +     || filter->fmt_in.audio.i_physical_channels == AOUT_CHANS_7_1)
>> +    {
>> +        error = ebur128_set_channel(state, 2, EBUR128_LEFT_SURROUND);
>> +        if (error != EBUR128_SUCCESS)
>> +            goto error;
>> +        ebur128_set_channel(state, 3, EBUR128_RIGHT_SURROUND);
>> +        if (error != EBUR128_SUCCESS)
>> +            goto error;
>> +        ebur128_set_channel(state, 4, EBUR128_CENTER);
>> +        if (error != EBUR128_SUCCESS)
>> +            goto error;
>> +
>> +        channels_set += 3;
>> +    }
>> +
>> +    for (unsigned i = channels_set; i < 
>> filter->fmt_in.audio.i_channels; ++i)
>> +    {
>> +        error = ebur128_set_channel(state, i, EBUR128_UNUSED);
>> +        if (error != EBUR128_SUCCESS)
>> +            goto error;
>> +    }
>> +
>> +    return state;
>> +error:
>> +    ebur128_destroy(&state);
>> +    return NULL;
>> +}
>> +
>> +static int
>> +SendLoudnessMeter(filter_t *filter)
>> +{
>> +    struct filter_sys *sys = filter->p_sys;
>> +
>> +    int error;
>> +    struct vlc_audio_loudness_meter meter = { 0, 0, 0, 0, 0 };
>> +
>> +    error = ebur128_loudness_momentary(sys->state, 
>> &meter.loudness_momentary);
>> +    if (error != EBUR128_SUCCESS)
>> +        return error;
>> +
>> +    if ((sys->state->mode & EBUR128_MODE_S) == EBUR128_MODE_S)
>> +    {
>> +        error = ebur128_loudness_shortterm(sys->state, 
>> &meter.loudness_shortterm);
>> +        if (error != EBUR128_SUCCESS)
>> +            return error;
>> +    }
>> +    if ((sys->state->mode & EBUR128_MODE_I) == EBUR128_MODE_I)
>> +    {
>> +        error = ebur128_loudness_global(sys->state, 
>> &meter.loudness_integrated);
>> +        if (error != EBUR128_SUCCESS)
>> +            return error;
>> +
>> +    }
>> +    if ((sys->state->mode & EBUR128_MODE_LRA) == EBUR128_MODE_LRA)
>> +    {
>> +        error = ebur128_loudness_range(sys->state, 
>> &meter.loudness_range);
>> +        if (error != EBUR128_SUCCESS)
>> +            return error;
>> +    }
>> +    if ((sys->state->mode & EBUR128_MODE_TRUE_PEAK) == 
>> EBUR128_MODE_TRUE_PEAK)
>> +    {
>> +        for (unsigned i = 0; i < filter->fmt_in.audio.i_channels; ++i)
>> +        {
>> +            double truepeak;
>> +            error = ebur128_true_peak(sys->state, 0, &truepeak);
>> +            if (error != EBUR128_SUCCESS)
>> +                return error;
>> +            if (truepeak > meter.truepeak)
>> +                meter.truepeak = truepeak;
>> +        }
>> +    }
>> +
>> +    var_SetAddress(vlc_object_parent(VLC_OBJECT(filter)), 
>> "loudness-meter", &meter);
> 
> I'm not a big fan of this. I'd prefer timed data attached to the audio 
> blocks (or in a separate ES). This would provide more or less accurate 
> values with each audio block. It could be used in the vout to blend in 
> the UI. Here if there's a delay between the decoder and the playback the 
> display also has this delay.

Also I feel the visualization filters may be changed to something like 
this. They could generate SPUs that can be integrated in the UI (with 
many of them at once for example). The vu meter would then be a 
visualization filter which would rely on some timed data.


More information about the vlc-devel mailing list