| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (c) 2011 Jan Kokemüller | ||
| 3 | * | ||
| 4 | * This file is part of FFmpeg. | ||
| 5 | * | ||
| 6 | * FFmpeg is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU Lesser General Public | ||
| 8 | * License as published by the Free Software Foundation; either | ||
| 9 | * version 2.1 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * Lesser General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU Lesser General Public | ||
| 17 | * License along with FFmpeg; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 19 | * | ||
| 20 | * This file is based on libebur128 which is available at | ||
| 21 | * https://github.com/jiixyj/libebur128/ | ||
| 22 | * | ||
| 23 | * Libebur128 has the following copyright: | ||
| 24 | * | ||
| 25 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 26 | * of this software and associated documentation files (the "Software"), to deal | ||
| 27 | * in the Software without restriction, including without limitation the rights | ||
| 28 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 29 | * copies of the Software, and to permit persons to whom the Software is | ||
| 30 | * furnished to do so, subject to the following conditions: | ||
| 31 | * | ||
| 32 | * The above copyright notice and this permission notice shall be included in | ||
| 33 | * all copies or substantial portions of the Software. | ||
| 34 | * | ||
| 35 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 36 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 37 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 38 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 39 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 40 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 41 | * THE SOFTWARE. | ||
| 42 | */ | ||
| 43 | |||
| 44 | #include "ebur128.h" | ||
| 45 | |||
| 46 | #include <float.h> | ||
| 47 | #include <limits.h> | ||
| 48 | #include <math.h> /* You may have to define _USE_MATH_DEFINES if you use MSVC */ | ||
| 49 | |||
| 50 | #include "libavutil/error.h" | ||
| 51 | #include "libavutil/macros.h" | ||
| 52 | #include "libavutil/mem.h" | ||
| 53 | #include "libavutil/mem_internal.h" | ||
| 54 | #include "libavutil/thread.h" | ||
| 55 | |||
| 56 | #define CHECK_ERROR(condition, errorcode, goto_point) \ | ||
| 57 | if ((condition)) { \ | ||
| 58 | errcode = (errorcode); \ | ||
| 59 | goto goto_point; \ | ||
| 60 | } | ||
| 61 | |||
| 62 | #define ALMOST_ZERO 0.000001 | ||
| 63 | |||
| 64 | #define RELATIVE_GATE (-10.0) | ||
| 65 | #define RELATIVE_GATE_FACTOR pow(10.0, RELATIVE_GATE / 10.0) | ||
| 66 | #define MINUS_20DB pow(10.0, -20.0 / 10.0) | ||
| 67 | |||
| 68 | struct FFEBUR128StateInternal { | ||
| 69 | /** Filtered audio data (used as ring buffer). */ | ||
| 70 | double *audio_data; | ||
| 71 | /** Size of audio_data array. */ | ||
| 72 | size_t audio_data_frames; | ||
| 73 | /** Current index for audio_data. */ | ||
| 74 | size_t audio_data_index; | ||
| 75 | /** How many frames are needed for a gating block. Will correspond to 400ms | ||
| 76 | * of audio at initialization, and 100ms after the first block (75% overlap | ||
| 77 | * as specified in the 2011 revision of BS1770). */ | ||
| 78 | unsigned long needed_frames; | ||
| 79 | /** The channel map. Has as many elements as there are channels. */ | ||
| 80 | int *channel_map; | ||
| 81 | /** How many samples fit in 100ms (rounded). */ | ||
| 82 | unsigned long samples_in_100ms; | ||
| 83 | /** BS.1770 filter coefficients (nominator). */ | ||
| 84 | double b[5]; | ||
| 85 | /** BS.1770 filter coefficients (denominator). */ | ||
| 86 | double a[5]; | ||
| 87 | /** BS.1770 filter state. */ | ||
| 88 | double v[5][5]; | ||
| 89 | /** Histograms, used to calculate LRA. */ | ||
| 90 | unsigned long *block_energy_histogram; | ||
| 91 | unsigned long *short_term_block_energy_histogram; | ||
| 92 | /** Keeps track of when a new short term block is needed. */ | ||
| 93 | size_t short_term_frame_counter; | ||
| 94 | /** Maximum sample peak, one per channel */ | ||
| 95 | double *sample_peak; | ||
| 96 | /** The maximum window duration in ms. */ | ||
| 97 | unsigned long window; | ||
| 98 | /** Data pointer array for interleaved data */ | ||
| 99 | void **data_ptrs; | ||
| 100 | }; | ||
| 101 | |||
| 102 | static AVOnce histogram_init = AV_ONCE_INIT; | ||
| 103 | static DECLARE_ALIGNED(32, double, histogram_energies)[1000]; | ||
| 104 | static DECLARE_ALIGNED(32, double, histogram_energy_boundaries)[1001]; | ||
| 105 | |||
| 106 | ✗ | static void ebur128_init_filter(FFEBUR128State * st) | |
| 107 | { | ||
| 108 | int i, j; | ||
| 109 | |||
| 110 | ✗ | double f0 = 1681.974450955533; | |
| 111 | ✗ | double G = 3.999843853973347; | |
| 112 | ✗ | double Q = 0.7071752369554196; | |
| 113 | |||
| 114 | ✗ | double K = tan(M_PI * f0 / (double) st->samplerate); | |
| 115 | ✗ | double Vh = pow(10.0, G / 20.0); | |
| 116 | ✗ | double Vb = pow(Vh, 0.4996667741545416); | |
| 117 | |||
| 118 | ✗ | double pb[3] = { 0.0, 0.0, 0.0 }; | |
| 119 | ✗ | double pa[3] = { 1.0, 0.0, 0.0 }; | |
| 120 | ✗ | double rb[3] = { 1.0, -2.0, 1.0 }; | |
| 121 | ✗ | double ra[3] = { 1.0, 0.0, 0.0 }; | |
| 122 | |||
| 123 | ✗ | double a0 = 1.0 + K / Q + K * K; | |
| 124 | ✗ | pb[0] = (Vh + Vb * K / Q + K * K) / a0; | |
| 125 | ✗ | pb[1] = 2.0 * (K * K - Vh) / a0; | |
| 126 | ✗ | pb[2] = (Vh - Vb * K / Q + K * K) / a0; | |
| 127 | ✗ | pa[1] = 2.0 * (K * K - 1.0) / a0; | |
| 128 | ✗ | pa[2] = (1.0 - K / Q + K * K) / a0; | |
| 129 | |||
| 130 | ✗ | f0 = 38.13547087602444; | |
| 131 | ✗ | Q = 0.5003270373238773; | |
| 132 | ✗ | K = tan(M_PI * f0 / (double) st->samplerate); | |
| 133 | |||
| 134 | ✗ | ra[1] = 2.0 * (K * K - 1.0) / (1.0 + K / Q + K * K); | |
| 135 | ✗ | ra[2] = (1.0 - K / Q + K * K) / (1.0 + K / Q + K * K); | |
| 136 | |||
| 137 | ✗ | st->d->b[0] = pb[0] * rb[0]; | |
| 138 | ✗ | st->d->b[1] = pb[0] * rb[1] + pb[1] * rb[0]; | |
| 139 | ✗ | st->d->b[2] = pb[0] * rb[2] + pb[1] * rb[1] + pb[2] * rb[0]; | |
| 140 | ✗ | st->d->b[3] = pb[1] * rb[2] + pb[2] * rb[1]; | |
| 141 | ✗ | st->d->b[4] = pb[2] * rb[2]; | |
| 142 | |||
| 143 | ✗ | st->d->a[0] = pa[0] * ra[0]; | |
| 144 | ✗ | st->d->a[1] = pa[0] * ra[1] + pa[1] * ra[0]; | |
| 145 | ✗ | st->d->a[2] = pa[0] * ra[2] + pa[1] * ra[1] + pa[2] * ra[0]; | |
| 146 | ✗ | st->d->a[3] = pa[1] * ra[2] + pa[2] * ra[1]; | |
| 147 | ✗ | st->d->a[4] = pa[2] * ra[2]; | |
| 148 | |||
| 149 | ✗ | for (i = 0; i < 5; ++i) { | |
| 150 | ✗ | for (j = 0; j < 5; ++j) { | |
| 151 | ✗ | st->d->v[i][j] = 0.0; | |
| 152 | } | ||
| 153 | } | ||
| 154 | ✗ | } | |
| 155 | |||
| 156 | ✗ | static int ebur128_init_channel_map(FFEBUR128State * st) | |
| 157 | { | ||
| 158 | size_t i; | ||
| 159 | ✗ | st->d->channel_map = | |
| 160 | ✗ | (int *) av_malloc_array(st->channels, sizeof(*st->d->channel_map)); | |
| 161 | ✗ | if (!st->d->channel_map) | |
| 162 | ✗ | return AVERROR(ENOMEM); | |
| 163 | ✗ | if (st->channels == 4) { | |
| 164 | ✗ | st->d->channel_map[0] = FF_EBUR128_LEFT; | |
| 165 | ✗ | st->d->channel_map[1] = FF_EBUR128_RIGHT; | |
| 166 | ✗ | st->d->channel_map[2] = FF_EBUR128_LEFT_SURROUND; | |
| 167 | ✗ | st->d->channel_map[3] = FF_EBUR128_RIGHT_SURROUND; | |
| 168 | ✗ | } else if (st->channels == 5) { | |
| 169 | ✗ | st->d->channel_map[0] = FF_EBUR128_LEFT; | |
| 170 | ✗ | st->d->channel_map[1] = FF_EBUR128_RIGHT; | |
| 171 | ✗ | st->d->channel_map[2] = FF_EBUR128_CENTER; | |
| 172 | ✗ | st->d->channel_map[3] = FF_EBUR128_LEFT_SURROUND; | |
| 173 | ✗ | st->d->channel_map[4] = FF_EBUR128_RIGHT_SURROUND; | |
| 174 | } else { | ||
| 175 | ✗ | for (i = 0; i < st->channels; ++i) { | |
| 176 | ✗ | switch (i) { | |
| 177 | ✗ | case 0: | |
| 178 | ✗ | st->d->channel_map[i] = FF_EBUR128_LEFT; | |
| 179 | ✗ | break; | |
| 180 | ✗ | case 1: | |
| 181 | ✗ | st->d->channel_map[i] = FF_EBUR128_RIGHT; | |
| 182 | ✗ | break; | |
| 183 | ✗ | case 2: | |
| 184 | ✗ | st->d->channel_map[i] = FF_EBUR128_CENTER; | |
| 185 | ✗ | break; | |
| 186 | ✗ | case 3: | |
| 187 | ✗ | st->d->channel_map[i] = FF_EBUR128_UNUSED; | |
| 188 | ✗ | break; | |
| 189 | ✗ | case 4: | |
| 190 | ✗ | st->d->channel_map[i] = FF_EBUR128_LEFT_SURROUND; | |
| 191 | ✗ | break; | |
| 192 | ✗ | case 5: | |
| 193 | ✗ | st->d->channel_map[i] = FF_EBUR128_RIGHT_SURROUND; | |
| 194 | ✗ | break; | |
| 195 | ✗ | default: | |
| 196 | ✗ | st->d->channel_map[i] = FF_EBUR128_UNUSED; | |
| 197 | ✗ | break; | |
| 198 | } | ||
| 199 | } | ||
| 200 | } | ||
| 201 | ✗ | return 0; | |
| 202 | } | ||
| 203 | |||
| 204 | ✗ | static inline void init_histogram(void) | |
| 205 | { | ||
| 206 | int i; | ||
| 207 | /* initialize static constants */ | ||
| 208 | ✗ | histogram_energy_boundaries[0] = pow(10.0, (-70.0 + 0.691) / 10.0); | |
| 209 | ✗ | for (i = 0; i < 1000; ++i) { | |
| 210 | ✗ | histogram_energies[i] = | |
| 211 | ✗ | pow(10.0, ((double) i / 10.0 - 69.95 + 0.691) / 10.0); | |
| 212 | } | ||
| 213 | ✗ | for (i = 1; i < 1001; ++i) { | |
| 214 | ✗ | histogram_energy_boundaries[i] = | |
| 215 | ✗ | pow(10.0, ((double) i / 10.0 - 70.0 + 0.691) / 10.0); | |
| 216 | } | ||
| 217 | ✗ | } | |
| 218 | |||
| 219 | ✗ | FFEBUR128State *ff_ebur128_init(unsigned int channels, | |
| 220 | unsigned long samplerate, | ||
| 221 | unsigned long window, int mode) | ||
| 222 | { | ||
| 223 | int errcode; | ||
| 224 | FFEBUR128State *st; | ||
| 225 | |||
| 226 | ✗ | st = (FFEBUR128State *) av_malloc(sizeof(*st)); | |
| 227 | ✗ | CHECK_ERROR(!st, 0, exit) | |
| 228 | ✗ | st->d = (struct FFEBUR128StateInternal *) | |
| 229 | ✗ | av_malloc(sizeof(*st->d)); | |
| 230 | ✗ | CHECK_ERROR(!st->d, 0, free_state) | |
| 231 | ✗ | st->channels = channels; | |
| 232 | ✗ | errcode = ebur128_init_channel_map(st); | |
| 233 | ✗ | CHECK_ERROR(errcode, 0, free_internal) | |
| 234 | |||
| 235 | ✗ | st->d->sample_peak = | |
| 236 | ✗ | (double *) av_calloc(channels, sizeof(*st->d->sample_peak)); | |
| 237 | ✗ | CHECK_ERROR(!st->d->sample_peak, 0, free_channel_map) | |
| 238 | |||
| 239 | ✗ | st->samplerate = samplerate; | |
| 240 | ✗ | st->d->samples_in_100ms = (st->samplerate + 5) / 10; | |
| 241 | ✗ | st->mode = mode; | |
| 242 | ✗ | if ((mode & FF_EBUR128_MODE_S) == FF_EBUR128_MODE_S) { | |
| 243 | ✗ | st->d->window = FFMAX(window, 3000); | |
| 244 | ✗ | } else if ((mode & FF_EBUR128_MODE_M) == FF_EBUR128_MODE_M) { | |
| 245 | ✗ | st->d->window = FFMAX(window, 400); | |
| 246 | } else { | ||
| 247 | ✗ | goto free_sample_peak; | |
| 248 | } | ||
| 249 | ✗ | st->d->audio_data_frames = st->samplerate * st->d->window / 1000; | |
| 250 | ✗ | if (st->d->audio_data_frames % st->d->samples_in_100ms) { | |
| 251 | /* round up to multiple of samples_in_100ms */ | ||
| 252 | ✗ | st->d->audio_data_frames = st->d->audio_data_frames | |
| 253 | ✗ | + st->d->samples_in_100ms | |
| 254 | ✗ | - (st->d->audio_data_frames % st->d->samples_in_100ms); | |
| 255 | } | ||
| 256 | ✗ | st->d->audio_data = | |
| 257 | ✗ | (double *) av_calloc(st->d->audio_data_frames, | |
| 258 | ✗ | st->channels * sizeof(*st->d->audio_data)); | |
| 259 | ✗ | CHECK_ERROR(!st->d->audio_data, 0, free_sample_peak) | |
| 260 | |||
| 261 | ✗ | ebur128_init_filter(st); | |
| 262 | |||
| 263 | ✗ | st->d->block_energy_histogram = | |
| 264 | ✗ | av_mallocz(1000 * sizeof(*st->d->block_energy_histogram)); | |
| 265 | ✗ | CHECK_ERROR(!st->d->block_energy_histogram, 0, free_audio_data) | |
| 266 | ✗ | st->d->short_term_block_energy_histogram = | |
| 267 | ✗ | av_mallocz(1000 * sizeof(*st->d->short_term_block_energy_histogram)); | |
| 268 | ✗ | CHECK_ERROR(!st->d->short_term_block_energy_histogram, 0, | |
| 269 | free_block_energy_histogram) | ||
| 270 | ✗ | st->d->short_term_frame_counter = 0; | |
| 271 | |||
| 272 | /* the first block needs 400ms of audio data */ | ||
| 273 | ✗ | st->d->needed_frames = st->d->samples_in_100ms * 4; | |
| 274 | /* start at the beginning of the buffer */ | ||
| 275 | ✗ | st->d->audio_data_index = 0; | |
| 276 | |||
| 277 | ✗ | if (ff_thread_once(&histogram_init, &init_histogram) != 0) | |
| 278 | ✗ | goto free_short_term_block_energy_histogram; | |
| 279 | |||
| 280 | ✗ | st->d->data_ptrs = av_malloc_array(channels, sizeof(*st->d->data_ptrs)); | |
| 281 | ✗ | CHECK_ERROR(!st->d->data_ptrs, 0, | |
| 282 | free_short_term_block_energy_histogram); | ||
| 283 | |||
| 284 | ✗ | return st; | |
| 285 | |||
| 286 | ✗ | free_short_term_block_energy_histogram: | |
| 287 | ✗ | av_free(st->d->short_term_block_energy_histogram); | |
| 288 | ✗ | free_block_energy_histogram: | |
| 289 | ✗ | av_free(st->d->block_energy_histogram); | |
| 290 | ✗ | free_audio_data: | |
| 291 | ✗ | av_free(st->d->audio_data); | |
| 292 | ✗ | free_sample_peak: | |
| 293 | ✗ | av_free(st->d->sample_peak); | |
| 294 | ✗ | free_channel_map: | |
| 295 | ✗ | av_free(st->d->channel_map); | |
| 296 | ✗ | free_internal: | |
| 297 | ✗ | av_free(st->d); | |
| 298 | ✗ | free_state: | |
| 299 | ✗ | av_free(st); | |
| 300 | ✗ | exit: | |
| 301 | ✗ | return NULL; | |
| 302 | } | ||
| 303 | |||
| 304 | ✗ | void ff_ebur128_destroy(FFEBUR128State ** st) | |
| 305 | { | ||
| 306 | ✗ | av_free((*st)->d->block_energy_histogram); | |
| 307 | ✗ | av_free((*st)->d->short_term_block_energy_histogram); | |
| 308 | ✗ | av_free((*st)->d->audio_data); | |
| 309 | ✗ | av_free((*st)->d->channel_map); | |
| 310 | ✗ | av_free((*st)->d->sample_peak); | |
| 311 | ✗ | av_free((*st)->d->data_ptrs); | |
| 312 | ✗ | av_free((*st)->d); | |
| 313 | ✗ | av_free(*st); | |
| 314 | ✗ | *st = NULL; | |
| 315 | ✗ | } | |
| 316 | |||
| 317 | #define EBUR128_FILTER(type, scaling_factor) \ | ||
| 318 | static void ebur128_filter_##type(FFEBUR128State* st, const type** srcs, \ | ||
| 319 | size_t src_index, size_t frames, \ | ||
| 320 | int stride) { \ | ||
| 321 | double* audio_data = st->d->audio_data + st->d->audio_data_index; \ | ||
| 322 | size_t i, c; \ | ||
| 323 | \ | ||
| 324 | if ((st->mode & FF_EBUR128_MODE_SAMPLE_PEAK) == FF_EBUR128_MODE_SAMPLE_PEAK) { \ | ||
| 325 | for (c = 0; c < st->channels; ++c) { \ | ||
| 326 | double max = 0.0; \ | ||
| 327 | for (i = 0; i < frames; ++i) { \ | ||
| 328 | type v = srcs[c][src_index + i * stride]; \ | ||
| 329 | if (v > max) { \ | ||
| 330 | max = v; \ | ||
| 331 | } else if (-v > max) { \ | ||
| 332 | max = -1.0 * v; \ | ||
| 333 | } \ | ||
| 334 | } \ | ||
| 335 | max /= scaling_factor; \ | ||
| 336 | if (max > st->d->sample_peak[c]) st->d->sample_peak[c] = max; \ | ||
| 337 | } \ | ||
| 338 | } \ | ||
| 339 | for (c = 0; c < st->channels; ++c) { \ | ||
| 340 | int ci = st->d->channel_map[c] - 1; \ | ||
| 341 | if (ci < 0) continue; \ | ||
| 342 | else if (ci == FF_EBUR128_DUAL_MONO - 1) ci = 0; /*dual mono */ \ | ||
| 343 | for (i = 0; i < frames; ++i) { \ | ||
| 344 | st->d->v[ci][0] = (double) (srcs[c][src_index + i * stride] / scaling_factor) \ | ||
| 345 | - st->d->a[1] * st->d->v[ci][1] \ | ||
| 346 | - st->d->a[2] * st->d->v[ci][2] \ | ||
| 347 | - st->d->a[3] * st->d->v[ci][3] \ | ||
| 348 | - st->d->a[4] * st->d->v[ci][4]; \ | ||
| 349 | audio_data[i * st->channels + c] = \ | ||
| 350 | st->d->b[0] * st->d->v[ci][0] \ | ||
| 351 | + st->d->b[1] * st->d->v[ci][1] \ | ||
| 352 | + st->d->b[2] * st->d->v[ci][2] \ | ||
| 353 | + st->d->b[3] * st->d->v[ci][3] \ | ||
| 354 | + st->d->b[4] * st->d->v[ci][4]; \ | ||
| 355 | st->d->v[ci][4] = st->d->v[ci][3]; \ | ||
| 356 | st->d->v[ci][3] = st->d->v[ci][2]; \ | ||
| 357 | st->d->v[ci][2] = st->d->v[ci][1]; \ | ||
| 358 | st->d->v[ci][1] = st->d->v[ci][0]; \ | ||
| 359 | } \ | ||
| 360 | st->d->v[ci][4] = fabs(st->d->v[ci][4]) < DBL_MIN ? 0.0 : st->d->v[ci][4]; \ | ||
| 361 | st->d->v[ci][3] = fabs(st->d->v[ci][3]) < DBL_MIN ? 0.0 : st->d->v[ci][3]; \ | ||
| 362 | st->d->v[ci][2] = fabs(st->d->v[ci][2]) < DBL_MIN ? 0.0 : st->d->v[ci][2]; \ | ||
| 363 | st->d->v[ci][1] = fabs(st->d->v[ci][1]) < DBL_MIN ? 0.0 : st->d->v[ci][1]; \ | ||
| 364 | } \ | ||
| 365 | } | ||
| 366 | ✗ | EBUR128_FILTER(double, 1.0) | |
| 367 | |||
| 368 | ✗ | static double ebur128_energy_to_loudness(double energy) | |
| 369 | { | ||
| 370 | ✗ | return 10 * log10(energy) - 0.691; | |
| 371 | } | ||
| 372 | |||
| 373 | ✗ | static size_t find_histogram_index(double energy) | |
| 374 | { | ||
| 375 | ✗ | size_t index_min = 0; | |
| 376 | ✗ | size_t index_max = 1000; | |
| 377 | size_t index_mid; | ||
| 378 | |||
| 379 | do { | ||
| 380 | ✗ | index_mid = (index_min + index_max) / 2; | |
| 381 | ✗ | if (energy >= histogram_energy_boundaries[index_mid]) { | |
| 382 | ✗ | index_min = index_mid; | |
| 383 | } else { | ||
| 384 | ✗ | index_max = index_mid; | |
| 385 | } | ||
| 386 | ✗ | } while (index_max - index_min != 1); | |
| 387 | |||
| 388 | ✗ | return index_min; | |
| 389 | } | ||
| 390 | |||
| 391 | ✗ | static void ebur128_calc_gating_block(FFEBUR128State * st, | |
| 392 | size_t frames_per_block, | ||
| 393 | double *optional_output) | ||
| 394 | { | ||
| 395 | size_t i, c; | ||
| 396 | ✗ | double sum = 0.0; | |
| 397 | double channel_sum; | ||
| 398 | ✗ | for (c = 0; c < st->channels; ++c) { | |
| 399 | ✗ | if (st->d->channel_map[c] == FF_EBUR128_UNUSED) | |
| 400 | ✗ | continue; | |
| 401 | ✗ | channel_sum = 0.0; | |
| 402 | ✗ | if (st->d->audio_data_index < frames_per_block * st->channels) { | |
| 403 | ✗ | for (i = 0; i < st->d->audio_data_index / st->channels; ++i) { | |
| 404 | ✗ | channel_sum += st->d->audio_data[i * st->channels + c] * | |
| 405 | ✗ | st->d->audio_data[i * st->channels + c]; | |
| 406 | } | ||
| 407 | ✗ | for (i = st->d->audio_data_frames - | |
| 408 | (frames_per_block - | ||
| 409 | ✗ | st->d->audio_data_index / st->channels); | |
| 410 | ✗ | i < st->d->audio_data_frames; ++i) { | |
| 411 | ✗ | channel_sum += st->d->audio_data[i * st->channels + c] * | |
| 412 | ✗ | st->d->audio_data[i * st->channels + c]; | |
| 413 | } | ||
| 414 | } else { | ||
| 415 | ✗ | for (i = | |
| 416 | ✗ | st->d->audio_data_index / st->channels - frames_per_block; | |
| 417 | ✗ | i < st->d->audio_data_index / st->channels; ++i) { | |
| 418 | ✗ | channel_sum += | |
| 419 | ✗ | st->d->audio_data[i * st->channels + | |
| 420 | ✗ | c] * st->d->audio_data[i * | |
| 421 | ✗ | st->channels + | |
| 422 | c]; | ||
| 423 | } | ||
| 424 | } | ||
| 425 | ✗ | if (st->d->channel_map[c] == FF_EBUR128_Mp110 || | |
| 426 | ✗ | st->d->channel_map[c] == FF_EBUR128_Mm110 || | |
| 427 | ✗ | st->d->channel_map[c] == FF_EBUR128_Mp060 || | |
| 428 | ✗ | st->d->channel_map[c] == FF_EBUR128_Mm060 || | |
| 429 | ✗ | st->d->channel_map[c] == FF_EBUR128_Mp090 || | |
| 430 | ✗ | st->d->channel_map[c] == FF_EBUR128_Mm090) { | |
| 431 | ✗ | channel_sum *= 1.41; | |
| 432 | ✗ | } else if (st->d->channel_map[c] == FF_EBUR128_DUAL_MONO) { | |
| 433 | ✗ | channel_sum *= 2.0; | |
| 434 | } | ||
| 435 | ✗ | sum += channel_sum; | |
| 436 | } | ||
| 437 | ✗ | sum /= (double) frames_per_block; | |
| 438 | ✗ | if (optional_output) { | |
| 439 | ✗ | *optional_output = sum; | |
| 440 | ✗ | } else if (sum >= histogram_energy_boundaries[0]) { | |
| 441 | ✗ | ++st->d->block_energy_histogram[find_histogram_index(sum)]; | |
| 442 | } | ||
| 443 | ✗ | } | |
| 444 | |||
| 445 | ✗ | int ff_ebur128_set_channel(FFEBUR128State * st, | |
| 446 | unsigned int channel_number, int value) | ||
| 447 | { | ||
| 448 | ✗ | if (channel_number >= st->channels) { | |
| 449 | ✗ | return 1; | |
| 450 | } | ||
| 451 | ✗ | if (value == FF_EBUR128_DUAL_MONO && | |
| 452 | ✗ | (st->channels != 1 || channel_number != 0)) { | |
| 453 | ✗ | return 1; | |
| 454 | } | ||
| 455 | ✗ | st->d->channel_map[channel_number] = value; | |
| 456 | ✗ | return 0; | |
| 457 | } | ||
| 458 | |||
| 459 | static int ebur128_energy_shortterm(FFEBUR128State * st, double *out); | ||
| 460 | #define EBUR128_ADD_FRAMES_PLANAR(type) \ | ||
| 461 | static void ebur128_add_frames_planar_##type(FFEBUR128State* st, const type** srcs, \ | ||
| 462 | size_t frames, int stride) { \ | ||
| 463 | size_t src_index = 0; \ | ||
| 464 | while (frames > 0) { \ | ||
| 465 | if (frames >= st->d->needed_frames) { \ | ||
| 466 | ebur128_filter_##type(st, srcs, src_index, st->d->needed_frames, stride); \ | ||
| 467 | src_index += st->d->needed_frames * stride; \ | ||
| 468 | frames -= st->d->needed_frames; \ | ||
| 469 | st->d->audio_data_index += st->d->needed_frames * st->channels; \ | ||
| 470 | /* calculate the new gating block */ \ | ||
| 471 | if ((st->mode & FF_EBUR128_MODE_I) == FF_EBUR128_MODE_I) { \ | ||
| 472 | ebur128_calc_gating_block(st, st->d->samples_in_100ms * 4, NULL); \ | ||
| 473 | } \ | ||
| 474 | if ((st->mode & FF_EBUR128_MODE_LRA) == FF_EBUR128_MODE_LRA) { \ | ||
| 475 | st->d->short_term_frame_counter += st->d->needed_frames; \ | ||
| 476 | if (st->d->short_term_frame_counter == st->d->samples_in_100ms * 30) { \ | ||
| 477 | double st_energy; \ | ||
| 478 | ebur128_energy_shortterm(st, &st_energy); \ | ||
| 479 | if (st_energy >= histogram_energy_boundaries[0]) { \ | ||
| 480 | ++st->d->short_term_block_energy_histogram[ \ | ||
| 481 | find_histogram_index(st_energy)]; \ | ||
| 482 | } \ | ||
| 483 | st->d->short_term_frame_counter = st->d->samples_in_100ms * 20; \ | ||
| 484 | } \ | ||
| 485 | } \ | ||
| 486 | /* 100ms are needed for all blocks besides the first one */ \ | ||
| 487 | st->d->needed_frames = st->d->samples_in_100ms; \ | ||
| 488 | /* reset audio_data_index when buffer full */ \ | ||
| 489 | if (st->d->audio_data_index == st->d->audio_data_frames * st->channels) { \ | ||
| 490 | st->d->audio_data_index = 0; \ | ||
| 491 | } \ | ||
| 492 | } else { \ | ||
| 493 | ebur128_filter_##type(st, srcs, src_index, frames, stride); \ | ||
| 494 | st->d->audio_data_index += frames * st->channels; \ | ||
| 495 | if ((st->mode & FF_EBUR128_MODE_LRA) == FF_EBUR128_MODE_LRA) { \ | ||
| 496 | st->d->short_term_frame_counter += frames; \ | ||
| 497 | } \ | ||
| 498 | st->d->needed_frames -= frames; \ | ||
| 499 | frames = 0; \ | ||
| 500 | } \ | ||
| 501 | } \ | ||
| 502 | } | ||
| 503 | ✗ | EBUR128_ADD_FRAMES_PLANAR(double) | |
| 504 | #define FF_EBUR128_ADD_FRAMES(type) \ | ||
| 505 | void ff_ebur128_add_frames_##type(FFEBUR128State* st, const type* src, \ | ||
| 506 | size_t frames) { \ | ||
| 507 | int i; \ | ||
| 508 | const type **buf = (const type**)st->d->data_ptrs; \ | ||
| 509 | for (i = 0; i < st->channels; i++) \ | ||
| 510 | buf[i] = src + i; \ | ||
| 511 | ebur128_add_frames_planar_##type(st, buf, frames, st->channels); \ | ||
| 512 | } | ||
| 513 | ✗ | FF_EBUR128_ADD_FRAMES(double) | |
| 514 | |||
| 515 | ✗ | static int ebur128_calc_relative_threshold(FFEBUR128State **sts, size_t size, | |
| 516 | double *relative_threshold) | ||
| 517 | { | ||
| 518 | size_t i, j; | ||
| 519 | ✗ | int above_thresh_counter = 0; | |
| 520 | ✗ | *relative_threshold = 0.0; | |
| 521 | |||
| 522 | ✗ | for (i = 0; i < size; i++) { | |
| 523 | ✗ | unsigned long *block_energy_histogram = sts[i]->d->block_energy_histogram; | |
| 524 | ✗ | for (j = 0; j < 1000; ++j) { | |
| 525 | ✗ | *relative_threshold += block_energy_histogram[j] * histogram_energies[j]; | |
| 526 | ✗ | above_thresh_counter += block_energy_histogram[j]; | |
| 527 | } | ||
| 528 | } | ||
| 529 | |||
| 530 | ✗ | if (above_thresh_counter != 0) { | |
| 531 | ✗ | *relative_threshold /= (double)above_thresh_counter; | |
| 532 | ✗ | *relative_threshold *= RELATIVE_GATE_FACTOR; | |
| 533 | } | ||
| 534 | |||
| 535 | ✗ | return above_thresh_counter; | |
| 536 | } | ||
| 537 | |||
| 538 | ✗ | static int ebur128_gated_loudness(FFEBUR128State ** sts, size_t size, | |
| 539 | double *out) | ||
| 540 | { | ||
| 541 | ✗ | double gated_loudness = 0.0; | |
| 542 | double relative_threshold; | ||
| 543 | size_t above_thresh_counter; | ||
| 544 | size_t i, j, start_index; | ||
| 545 | |||
| 546 | ✗ | for (i = 0; i < size; i++) | |
| 547 | ✗ | if ((sts[i]->mode & FF_EBUR128_MODE_I) != FF_EBUR128_MODE_I) | |
| 548 | ✗ | return AVERROR(EINVAL); | |
| 549 | |||
| 550 | ✗ | if (!ebur128_calc_relative_threshold(sts, size, &relative_threshold)) { | |
| 551 | ✗ | *out = -HUGE_VAL; | |
| 552 | ✗ | return 0; | |
| 553 | } | ||
| 554 | |||
| 555 | ✗ | above_thresh_counter = 0; | |
| 556 | ✗ | if (relative_threshold < histogram_energy_boundaries[0]) { | |
| 557 | ✗ | start_index = 0; | |
| 558 | } else { | ||
| 559 | ✗ | start_index = find_histogram_index(relative_threshold); | |
| 560 | ✗ | if (relative_threshold > histogram_energies[start_index]) { | |
| 561 | ✗ | ++start_index; | |
| 562 | } | ||
| 563 | } | ||
| 564 | ✗ | for (i = 0; i < size; i++) { | |
| 565 | ✗ | for (j = start_index; j < 1000; ++j) { | |
| 566 | ✗ | gated_loudness += sts[i]->d->block_energy_histogram[j] * | |
| 567 | ✗ | histogram_energies[j]; | |
| 568 | ✗ | above_thresh_counter += sts[i]->d->block_energy_histogram[j]; | |
| 569 | } | ||
| 570 | } | ||
| 571 | ✗ | if (!above_thresh_counter) { | |
| 572 | ✗ | *out = -HUGE_VAL; | |
| 573 | ✗ | return 0; | |
| 574 | } | ||
| 575 | ✗ | gated_loudness /= (double) above_thresh_counter; | |
| 576 | ✗ | *out = ebur128_energy_to_loudness(gated_loudness); | |
| 577 | ✗ | return 0; | |
| 578 | } | ||
| 579 | |||
| 580 | ✗ | int ff_ebur128_relative_threshold(FFEBUR128State * st, double *out) | |
| 581 | { | ||
| 582 | double relative_threshold; | ||
| 583 | |||
| 584 | ✗ | if ((st->mode & FF_EBUR128_MODE_I) != FF_EBUR128_MODE_I) | |
| 585 | ✗ | return AVERROR(EINVAL); | |
| 586 | |||
| 587 | ✗ | if (!ebur128_calc_relative_threshold(&st, 1, &relative_threshold)) { | |
| 588 | ✗ | *out = -70.0; | |
| 589 | ✗ | return 0; | |
| 590 | } | ||
| 591 | |||
| 592 | ✗ | *out = ebur128_energy_to_loudness(relative_threshold); | |
| 593 | ✗ | return 0; | |
| 594 | } | ||
| 595 | |||
| 596 | ✗ | int ff_ebur128_loudness_global(FFEBUR128State * st, double *out) | |
| 597 | { | ||
| 598 | ✗ | return ebur128_gated_loudness(&st, 1, out); | |
| 599 | } | ||
| 600 | |||
| 601 | ✗ | static int ebur128_energy_in_interval(FFEBUR128State * st, | |
| 602 | size_t interval_frames, double *out) | ||
| 603 | { | ||
| 604 | ✗ | if (interval_frames > st->d->audio_data_frames) { | |
| 605 | ✗ | return AVERROR(EINVAL); | |
| 606 | } | ||
| 607 | ✗ | ebur128_calc_gating_block(st, interval_frames, out); | |
| 608 | ✗ | return 0; | |
| 609 | } | ||
| 610 | |||
| 611 | ✗ | static int ebur128_energy_shortterm(FFEBUR128State * st, double *out) | |
| 612 | { | ||
| 613 | ✗ | return ebur128_energy_in_interval(st, st->d->samples_in_100ms * 30, | |
| 614 | out); | ||
| 615 | } | ||
| 616 | |||
| 617 | ✗ | int ff_ebur128_loudness_shortterm(FFEBUR128State * st, double *out) | |
| 618 | { | ||
| 619 | double energy; | ||
| 620 | ✗ | int error = ebur128_energy_shortterm(st, &energy); | |
| 621 | ✗ | if (error) { | |
| 622 | ✗ | return error; | |
| 623 | ✗ | } else if (energy <= 0.0) { | |
| 624 | ✗ | *out = -HUGE_VAL; | |
| 625 | ✗ | return 0; | |
| 626 | } | ||
| 627 | ✗ | *out = ebur128_energy_to_loudness(energy); | |
| 628 | ✗ | return 0; | |
| 629 | } | ||
| 630 | |||
| 631 | /* EBU - TECH 3342 */ | ||
| 632 | ✗ | int ff_ebur128_loudness_range_multiple(FFEBUR128State ** sts, size_t size, | |
| 633 | double *out) | ||
| 634 | { | ||
| 635 | size_t i, j; | ||
| 636 | size_t stl_size; | ||
| 637 | double stl_power, stl_integrated; | ||
| 638 | /* High and low percentile energy */ | ||
| 639 | double h_en, l_en; | ||
| 640 | ✗ | unsigned long hist[1000] = { 0 }; | |
| 641 | size_t percentile_low, percentile_high; | ||
| 642 | size_t index; | ||
| 643 | |||
| 644 | ✗ | for (i = 0; i < size; ++i) { | |
| 645 | ✗ | if (sts[i]) { | |
| 646 | ✗ | if ((sts[i]->mode & FF_EBUR128_MODE_LRA) != | |
| 647 | FF_EBUR128_MODE_LRA) { | ||
| 648 | ✗ | return AVERROR(EINVAL); | |
| 649 | } | ||
| 650 | } | ||
| 651 | } | ||
| 652 | |||
| 653 | ✗ | stl_size = 0; | |
| 654 | ✗ | stl_power = 0.0; | |
| 655 | ✗ | for (i = 0; i < size; ++i) { | |
| 656 | ✗ | if (!sts[i]) | |
| 657 | ✗ | continue; | |
| 658 | ✗ | for (j = 0; j < 1000; ++j) { | |
| 659 | ✗ | hist[j] += sts[i]->d->short_term_block_energy_histogram[j]; | |
| 660 | ✗ | stl_size += sts[i]->d->short_term_block_energy_histogram[j]; | |
| 661 | ✗ | stl_power += sts[i]->d->short_term_block_energy_histogram[j] | |
| 662 | ✗ | * histogram_energies[j]; | |
| 663 | } | ||
| 664 | } | ||
| 665 | ✗ | if (!stl_size) { | |
| 666 | ✗ | *out = 0.0; | |
| 667 | ✗ | return 0; | |
| 668 | } | ||
| 669 | |||
| 670 | ✗ | stl_power /= stl_size; | |
| 671 | ✗ | stl_integrated = MINUS_20DB * stl_power; | |
| 672 | |||
| 673 | ✗ | if (stl_integrated < histogram_energy_boundaries[0]) { | |
| 674 | ✗ | index = 0; | |
| 675 | } else { | ||
| 676 | ✗ | index = find_histogram_index(stl_integrated); | |
| 677 | ✗ | if (stl_integrated > histogram_energies[index]) { | |
| 678 | ✗ | ++index; | |
| 679 | } | ||
| 680 | } | ||
| 681 | ✗ | stl_size = 0; | |
| 682 | ✗ | for (j = index; j < 1000; ++j) { | |
| 683 | ✗ | stl_size += hist[j]; | |
| 684 | } | ||
| 685 | ✗ | if (!stl_size) { | |
| 686 | ✗ | *out = 0.0; | |
| 687 | ✗ | return 0; | |
| 688 | } | ||
| 689 | |||
| 690 | ✗ | percentile_low = (size_t) ((stl_size - 1) * 0.1 + 0.5); | |
| 691 | ✗ | percentile_high = (size_t) ((stl_size - 1) * 0.95 + 0.5); | |
| 692 | |||
| 693 | ✗ | stl_size = 0; | |
| 694 | ✗ | j = index; | |
| 695 | ✗ | while (stl_size <= percentile_low) { | |
| 696 | ✗ | stl_size += hist[j++]; | |
| 697 | } | ||
| 698 | ✗ | l_en = histogram_energies[j - 1]; | |
| 699 | ✗ | while (stl_size <= percentile_high) { | |
| 700 | ✗ | stl_size += hist[j++]; | |
| 701 | } | ||
| 702 | ✗ | h_en = histogram_energies[j - 1]; | |
| 703 | ✗ | *out = | |
| 704 | ✗ | ebur128_energy_to_loudness(h_en) - | |
| 705 | ✗ | ebur128_energy_to_loudness(l_en); | |
| 706 | ✗ | return 0; | |
| 707 | } | ||
| 708 | |||
| 709 | ✗ | int ff_ebur128_loudness_range(FFEBUR128State * st, double *out) | |
| 710 | { | ||
| 711 | ✗ | return ff_ebur128_loudness_range_multiple(&st, 1, out); | |
| 712 | } | ||
| 713 | |||
| 714 | ✗ | int ff_ebur128_sample_peak(FFEBUR128State * st, | |
| 715 | unsigned int channel_number, double *out) | ||
| 716 | { | ||
| 717 | ✗ | if ((st->mode & FF_EBUR128_MODE_SAMPLE_PEAK) != | |
| 718 | FF_EBUR128_MODE_SAMPLE_PEAK) { | ||
| 719 | ✗ | return AVERROR(EINVAL); | |
| 720 | ✗ | } else if (channel_number >= st->channels) { | |
| 721 | ✗ | return AVERROR(EINVAL); | |
| 722 | } | ||
| 723 | ✗ | *out = st->d->sample_peak[channel_number]; | |
| 724 | ✗ | return 0; | |
| 725 | } | ||
| 726 |