725 lines · 28.5 KB · C
RawDownload
/* * Copyright (c) 2011 Jan Kokemüller * * This file is part of FFmpeg. * * FFmpeg 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. * * FFmpeg 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 FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * This file is based on libebur128 which is available at * https://github.com/jiixyj/libebur128/ * * Libebur128 has the following copyright: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE.*/ #include "ebur128.h" #include <float.h>#include <limits.h>#include <math.h>               /* You may have to define _USE_MATH_DEFINES if you use MSVC */ #include "libavutil/error.h"#include "libavutil/macros.h"#include "libavutil/mem.h"#include "libavutil/mem_internal.h"#include "libavutil/thread.h" #define CHECK_ERROR(condition, errorcode, goto_point)                          \    if ((condition)) {                                                         \        errcode = (errorcode);                                                 \        goto goto_point;                                                       \    } #define ALMOST_ZERO 0.000001 #define RELATIVE_GATE         (-10.0)#define RELATIVE_GATE_FACTOR  pow(10.0, RELATIVE_GATE / 10.0)#define MINUS_20DB            pow(10.0, -20.0 / 10.0) struct FFEBUR128StateInternal {    /** Filtered audio data (used as ring buffer). */    double *audio_data;    /** Size of audio_data array. */    size_t audio_data_frames;    /** Current index for audio_data. */    size_t audio_data_index;    /** How many frames are needed for a gating block. Will correspond to 400ms     *  of audio at initialization, and 100ms after the first block (75% overlap     *  as specified in the 2011 revision of BS1770). */    unsigned long needed_frames;    /** The channel map. Has as many elements as there are channels. */    int *channel_map;    /** How many samples fit in 100ms (rounded). */    unsigned long samples_in_100ms;    /** BS.1770 filter coefficients (nominator). */    double b[5];    /** BS.1770 filter coefficients (denominator). */    double a[5];    /** BS.1770 filter state. */    double v[5][5];    /** Histograms, used to calculate LRA. */    unsigned long *block_energy_histogram;    unsigned long *short_term_block_energy_histogram;    /** Keeps track of when a new short term block is needed. */    size_t short_term_frame_counter;    /** Maximum sample peak, one per channel */    double *sample_peak;    /** The maximum window duration in ms. */    unsigned long window;    /** Data pointer array for interleaved data */    void **data_ptrs;}; static AVOnce histogram_init = AV_ONCE_INIT;static DECLARE_ALIGNED(32, double, histogram_energies)[1000];static DECLARE_ALIGNED(32, double, histogram_energy_boundaries)[1001]; static void ebur128_init_filter(FFEBUR128State * st){    int i, j;     double f0 = 1681.974450955533;    double G = 3.999843853973347;    double Q = 0.7071752369554196;     double K = tan(M_PI * f0 / (double) st->samplerate);    double Vh = pow(10.0, G / 20.0);    double Vb = pow(Vh, 0.4996667741545416);     double pb[3] = { 0.0, 0.0, 0.0 };    double pa[3] = { 1.0, 0.0, 0.0 };    double rb[3] = { 1.0, -2.0, 1.0 };    double ra[3] = { 1.0, 0.0, 0.0 };     double a0 = 1.0 + K / Q + K * K;    pb[0] = (Vh + Vb * K / Q + K * K) / a0;    pb[1] = 2.0 * (K * K - Vh) / a0;    pb[2] = (Vh - Vb * K / Q + K * K) / a0;    pa[1] = 2.0 * (K * K - 1.0) / a0;    pa[2] = (1.0 - K / Q + K * K) / a0;     f0 = 38.13547087602444;    Q = 0.5003270373238773;    K = tan(M_PI * f0 / (double) st->samplerate);     ra[1] = 2.0 * (K * K - 1.0) / (1.0 + K / Q + K * K);    ra[2] = (1.0 - K / Q + K * K) / (1.0 + K / Q + K * K);     st->d->b[0] = pb[0] * rb[0];    st->d->b[1] = pb[0] * rb[1] + pb[1] * rb[0];    st->d->b[2] = pb[0] * rb[2] + pb[1] * rb[1] + pb[2] * rb[0];    st->d->b[3] = pb[1] * rb[2] + pb[2] * rb[1];    st->d->b[4] = pb[2] * rb[2];     st->d->a[0] = pa[0] * ra[0];    st->d->a[1] = pa[0] * ra[1] + pa[1] * ra[0];    st->d->a[2] = pa[0] * ra[2] + pa[1] * ra[1] + pa[2] * ra[0];    st->d->a[3] = pa[1] * ra[2] + pa[2] * ra[1];    st->d->a[4] = pa[2] * ra[2];     for (i = 0; i < 5; ++i) {        for (j = 0; j < 5; ++j) {            st->d->v[i][j] = 0.0;        }    }} static int ebur128_init_channel_map(FFEBUR128State * st){    size_t i;    st->d->channel_map =        (int *) av_malloc_array(st->channels, sizeof(*st->d->channel_map));    if (!st->d->channel_map)        return AVERROR(ENOMEM);    if (st->channels == 4) {        st->d->channel_map[0] = FF_EBUR128_LEFT;        st->d->channel_map[1] = FF_EBUR128_RIGHT;        st->d->channel_map[2] = FF_EBUR128_LEFT_SURROUND;        st->d->channel_map[3] = FF_EBUR128_RIGHT_SURROUND;    } else if (st->channels == 5) {        st->d->channel_map[0] = FF_EBUR128_LEFT;        st->d->channel_map[1] = FF_EBUR128_RIGHT;        st->d->channel_map[2] = FF_EBUR128_CENTER;        st->d->channel_map[3] = FF_EBUR128_LEFT_SURROUND;        st->d->channel_map[4] = FF_EBUR128_RIGHT_SURROUND;    } else {        for (i = 0; i < st->channels; ++i) {            switch (i) {            case 0:                st->d->channel_map[i] = FF_EBUR128_LEFT;                break;            case 1:                st->d->channel_map[i] = FF_EBUR128_RIGHT;                break;            case 2:                st->d->channel_map[i] = FF_EBUR128_CENTER;                break;            case 3:                st->d->channel_map[i] = FF_EBUR128_UNUSED;                break;            case 4:                st->d->channel_map[i] = FF_EBUR128_LEFT_SURROUND;                break;            case 5:                st->d->channel_map[i] = FF_EBUR128_RIGHT_SURROUND;                break;            default:                st->d->channel_map[i] = FF_EBUR128_UNUSED;                break;            }        }    }    return 0;} static inline void init_histogram(void){    int i;    /* initialize static constants */    histogram_energy_boundaries[0] = pow(10.0, (-70.0 + 0.691) / 10.0);    for (i = 0; i < 1000; ++i) {        histogram_energies[i] =            pow(10.0, ((double) i / 10.0 - 69.95 + 0.691) / 10.0);    }    for (i = 1; i < 1001; ++i) {        histogram_energy_boundaries[i] =            pow(10.0, ((double) i / 10.0 - 70.0 + 0.691) / 10.0);    }} FFEBUR128State *ff_ebur128_init(unsigned int channels,                                unsigned long samplerate,                                unsigned long window, int mode){    int errcode;    FFEBUR128State *st;     st = (FFEBUR128State *) av_malloc(sizeof(*st));    CHECK_ERROR(!st, 0, exit)    st->d = (struct FFEBUR128StateInternal *)        av_malloc(sizeof(*st->d));    CHECK_ERROR(!st->d, 0, free_state)    st->channels = channels;    errcode = ebur128_init_channel_map(st);    CHECK_ERROR(errcode, 0, free_internal)     st->d->sample_peak =        (double *) av_calloc(channels, sizeof(*st->d->sample_peak));    CHECK_ERROR(!st->d->sample_peak, 0, free_channel_map)     st->samplerate = samplerate;    st->d->samples_in_100ms = (st->samplerate + 5) / 10;    st->mode = mode;    if ((mode & FF_EBUR128_MODE_S) == FF_EBUR128_MODE_S) {        st->d->window = FFMAX(window, 3000);    } else if ((mode & FF_EBUR128_MODE_M) == FF_EBUR128_MODE_M) {        st->d->window = FFMAX(window, 400);    } else {        goto free_sample_peak;    }    st->d->audio_data_frames = st->samplerate * st->d->window / 1000;    if (st->d->audio_data_frames % st->d->samples_in_100ms) {        /* round up to multiple of samples_in_100ms */        st->d->audio_data_frames = st->d->audio_data_frames            + st->d->samples_in_100ms            - (st->d->audio_data_frames % st->d->samples_in_100ms);    }    st->d->audio_data =        (double *) av_calloc(st->d->audio_data_frames,                             st->channels * sizeof(*st->d->audio_data));    CHECK_ERROR(!st->d->audio_data, 0, free_sample_peak)     ebur128_init_filter(st);     st->d->block_energy_histogram =        av_mallocz(1000 * sizeof(*st->d->block_energy_histogram));    CHECK_ERROR(!st->d->block_energy_histogram, 0, free_audio_data)    st->d->short_term_block_energy_histogram =        av_mallocz(1000 * sizeof(*st->d->short_term_block_energy_histogram));    CHECK_ERROR(!st->d->short_term_block_energy_histogram, 0,                free_block_energy_histogram)    st->d->short_term_frame_counter = 0;     /* the first block needs 400ms of audio data */    st->d->needed_frames = st->d->samples_in_100ms * 4;    /* start at the beginning of the buffer */    st->d->audio_data_index = 0;     if (ff_thread_once(&histogram_init, &init_histogram) != 0)        goto free_short_term_block_energy_histogram;     st->d->data_ptrs = av_malloc_array(channels, sizeof(*st->d->data_ptrs));    CHECK_ERROR(!st->d->data_ptrs, 0,                free_short_term_block_energy_histogram);     return st; free_short_term_block_energy_histogram:    av_free(st->d->short_term_block_energy_histogram);free_block_energy_histogram:    av_free(st->d->block_energy_histogram);free_audio_data:    av_free(st->d->audio_data);free_sample_peak:    av_free(st->d->sample_peak);free_channel_map:    av_free(st->d->channel_map);free_internal:    av_free(st->d);free_state:    av_free(st);exit:    return NULL;} void ff_ebur128_destroy(FFEBUR128State ** st){    av_free((*st)->d->block_energy_histogram);    av_free((*st)->d->short_term_block_energy_histogram);    av_free((*st)->d->audio_data);    av_free((*st)->d->channel_map);    av_free((*st)->d->sample_peak);    av_free((*st)->d->data_ptrs);    av_free((*st)->d);    av_free(*st);    *st = NULL;} #define EBUR128_FILTER(type, scaling_factor)                                       \static void ebur128_filter_##type(FFEBUR128State* st, const type** srcs,           \                                  size_t src_index, size_t frames,                 \                                  int stride) {                                    \    double* audio_data = st->d->audio_data + st->d->audio_data_index;              \    size_t i, c;                                                                   \                                                                                   \    if ((st->mode & FF_EBUR128_MODE_SAMPLE_PEAK) == FF_EBUR128_MODE_SAMPLE_PEAK) { \        for (c = 0; c < st->channels; ++c) {                                       \            double max = 0.0;                                                      \            for (i = 0; i < frames; ++i) {                                         \                type v = srcs[c][src_index + i * stride];                          \                if (v > max) {                                                     \                    max =        v;                                                \                } else if (-v > max) {                                             \                    max = -1.0 * v;                                                \                }                                                                  \            }                                                                      \            max /= scaling_factor;                                                 \            if (max > st->d->sample_peak[c]) st->d->sample_peak[c] = max;          \        }                                                                          \    }                                                                              \    for (c = 0; c < st->channels; ++c) {                                           \        int ci = st->d->channel_map[c] - 1;                                        \        if (ci < 0) continue;                                                      \        else if (ci == FF_EBUR128_DUAL_MONO - 1) ci = 0; /*dual mono */            \        for (i = 0; i < frames; ++i) {                                             \            st->d->v[ci][0] = (double) (srcs[c][src_index + i * stride] / scaling_factor) \                         - st->d->a[1] * st->d->v[ci][1]                           \                         - st->d->a[2] * st->d->v[ci][2]                           \                         - st->d->a[3] * st->d->v[ci][3]                           \                         - st->d->a[4] * st->d->v[ci][4];                          \            audio_data[i * st->channels + c] =                                     \                           st->d->b[0] * st->d->v[ci][0]                           \                         + st->d->b[1] * st->d->v[ci][1]                           \                         + st->d->b[2] * st->d->v[ci][2]                           \                         + st->d->b[3] * st->d->v[ci][3]                           \                         + st->d->b[4] * st->d->v[ci][4];                          \            st->d->v[ci][4] = st->d->v[ci][3];                                     \            st->d->v[ci][3] = st->d->v[ci][2];                                     \            st->d->v[ci][2] = st->d->v[ci][1];                                     \            st->d->v[ci][1] = st->d->v[ci][0];                                     \        }                                                                          \        st->d->v[ci][4] = fabs(st->d->v[ci][4]) < DBL_MIN ? 0.0 : st->d->v[ci][4]; \        st->d->v[ci][3] = fabs(st->d->v[ci][3]) < DBL_MIN ? 0.0 : st->d->v[ci][3]; \        st->d->v[ci][2] = fabs(st->d->v[ci][2]) < DBL_MIN ? 0.0 : st->d->v[ci][2]; \        st->d->v[ci][1] = fabs(st->d->v[ci][1]) < DBL_MIN ? 0.0 : st->d->v[ci][1]; \    }                                                                              \}EBUR128_FILTER(double, 1.0) static double ebur128_energy_to_loudness(double energy){    return 10 * log10(energy) - 0.691;} static size_t find_histogram_index(double energy){    size_t index_min = 0;    size_t index_max = 1000;    size_t index_mid;     do {        index_mid = (index_min + index_max) / 2;        if (energy >= histogram_energy_boundaries[index_mid]) {            index_min = index_mid;        } else {            index_max = index_mid;        }    } while (index_max - index_min != 1);     return index_min;} static void ebur128_calc_gating_block(FFEBUR128State * st,                                      size_t frames_per_block,                                      double *optional_output){    size_t i, c;    double sum = 0.0;    double channel_sum;    for (c = 0; c < st->channels; ++c) {        if (st->d->channel_map[c] == FF_EBUR128_UNUSED)            continue;        channel_sum = 0.0;        if (st->d->audio_data_index < frames_per_block * st->channels) {            for (i = 0; i < st->d->audio_data_index / st->channels; ++i) {                channel_sum += st->d->audio_data[i * st->channels + c] *                    st->d->audio_data[i * st->channels + c];            }            for (i = st->d->audio_data_frames -                 (frames_per_block -                  st->d->audio_data_index / st->channels);                 i < st->d->audio_data_frames; ++i) {                channel_sum += st->d->audio_data[i * st->channels + c] *                    st->d->audio_data[i * st->channels + c];            }        } else {            for (i =                 st->d->audio_data_index / st->channels - frames_per_block;                 i < st->d->audio_data_index / st->channels; ++i) {                channel_sum +=                    st->d->audio_data[i * st->channels +                                      c] * st->d->audio_data[i *                                                             st->channels +                                                             c];            }        }        if (st->d->channel_map[c] == FF_EBUR128_Mp110 ||            st->d->channel_map[c] == FF_EBUR128_Mm110 ||            st->d->channel_map[c] == FF_EBUR128_Mp060 ||            st->d->channel_map[c] == FF_EBUR128_Mm060 ||            st->d->channel_map[c] == FF_EBUR128_Mp090 ||            st->d->channel_map[c] == FF_EBUR128_Mm090) {            channel_sum *= 1.41;        } else if (st->d->channel_map[c] == FF_EBUR128_DUAL_MONO) {            channel_sum *= 2.0;        }        sum += channel_sum;    }    sum /= (double) frames_per_block;    if (optional_output) {        *optional_output = sum;    } else if (sum >= histogram_energy_boundaries[0]) {        ++st->d->block_energy_histogram[find_histogram_index(sum)];    }} int ff_ebur128_set_channel(FFEBUR128State * st,                           unsigned int channel_number, int value){    if (channel_number >= st->channels) {        return 1;    }    if (value == FF_EBUR128_DUAL_MONO &&        (st->channels != 1 || channel_number != 0)) {        return 1;    }    st->d->channel_map[channel_number] = value;    return 0;} static int ebur128_energy_shortterm(FFEBUR128State * st, double *out);#define EBUR128_ADD_FRAMES_PLANAR(type)                                                \static void ebur128_add_frames_planar_##type(FFEBUR128State* st, const type** srcs,    \                                 size_t frames, int stride) {                          \    size_t src_index = 0;                                                              \    while (frames > 0) {                                                               \        if (frames >= st->d->needed_frames) {                                          \            ebur128_filter_##type(st, srcs, src_index, st->d->needed_frames, stride);  \            src_index += st->d->needed_frames * stride;                                \            frames -= st->d->needed_frames;                                            \            st->d->audio_data_index += st->d->needed_frames * st->channels;            \            /* calculate the new gating block */                                       \            if ((st->mode & FF_EBUR128_MODE_I) == FF_EBUR128_MODE_I) {                 \                ebur128_calc_gating_block(st, st->d->samples_in_100ms * 4, NULL);      \            }                                                                          \            if ((st->mode & FF_EBUR128_MODE_LRA) == FF_EBUR128_MODE_LRA) {             \                st->d->short_term_frame_counter += st->d->needed_frames;               \                if (st->d->short_term_frame_counter == st->d->samples_in_100ms * 30) { \                    double st_energy;                                                  \                    ebur128_energy_shortterm(st, &st_energy);                          \                    if (st_energy >= histogram_energy_boundaries[0]) {                 \                        ++st->d->short_term_block_energy_histogram[                    \                                                    find_histogram_index(st_energy)];  \                    }                                                                  \                    st->d->short_term_frame_counter = st->d->samples_in_100ms * 20;    \                }                                                                      \            }                                                                          \            /* 100ms are needed for all blocks besides the first one */                \            st->d->needed_frames = st->d->samples_in_100ms;                            \            /* reset audio_data_index when buffer full */                              \            if (st->d->audio_data_index == st->d->audio_data_frames * st->channels) {  \                st->d->audio_data_index = 0;                                           \            }                                                                          \        } else {                                                                       \            ebur128_filter_##type(st, srcs, src_index, frames, stride);                \            st->d->audio_data_index += frames * st->channels;                          \            if ((st->mode & FF_EBUR128_MODE_LRA) == FF_EBUR128_MODE_LRA) {             \                st->d->short_term_frame_counter += frames;                             \            }                                                                          \            st->d->needed_frames -= frames;                                            \            frames = 0;                                                                \        }                                                                              \

Lines 1–500 of 725.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t