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 |
|
|
|