You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-04 22:03:09 +02:00
avfilter/f_ebur128: use structs for biquad weights
Simplifies the code a bit. In particular, the copy to the stack is marginally faster.
This commit is contained in:
@ -75,6 +75,11 @@ struct integrator {
|
|||||||
|
|
||||||
struct rect { int x, y, w, h; };
|
struct rect { int x, y, w, h; };
|
||||||
|
|
||||||
|
struct biquad {
|
||||||
|
double b0, b1, b2;
|
||||||
|
double a1, a2;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct EBUR128Context {
|
typedef struct EBUR128Context {
|
||||||
const AVClass *class; ///< AVClass context for log and options purpose
|
const AVClass *class; ///< AVClass context for log and options purpose
|
||||||
|
|
||||||
@ -117,10 +122,8 @@ typedef struct EBUR128Context {
|
|||||||
* The mult by 3 in the following is for X[i], X[i-1] and X[i-2] */
|
* The mult by 3 in the following is for X[i], X[i-1] and X[i-2] */
|
||||||
double *y; ///< 3 pre-filter samples cache for each channel
|
double *y; ///< 3 pre-filter samples cache for each channel
|
||||||
double *z; ///< 3 RLB-filter samples cache for each channel
|
double *z; ///< 3 RLB-filter samples cache for each channel
|
||||||
double pre_b[3]; ///< pre-filter numerator coefficients
|
struct biquad pre;
|
||||||
double pre_a[3]; ///< pre-filter denominator coefficients
|
struct biquad rlb;
|
||||||
double rlb_b[3]; ///< rlb-filter numerator coefficients
|
|
||||||
double rlb_a[3]; ///< rlb-filter denominator coefficients
|
|
||||||
|
|
||||||
struct integrator i400; ///< 400ms integrator, used for Momentary loudness (M), and Integrated loudness (I)
|
struct integrator i400; ///< 400ms integrator, used for Momentary loudness (M), and Integrated loudness (I)
|
||||||
struct integrator i3000; ///< 3s integrator, used for Short term loudness (S), and Loudness Range (LRA)
|
struct integrator i3000; ///< 3s integrator, used for Short term loudness (S), and Loudness Range (LRA)
|
||||||
@ -405,21 +408,21 @@ static int config_audio_input(AVFilterLink *inlink)
|
|||||||
|
|
||||||
double a0 = 1.0 + K / Q + K * K;
|
double a0 = 1.0 + K / Q + K * K;
|
||||||
|
|
||||||
ebur128->pre_b[0] = (Vh + Vb * K / Q + K * K) / a0;
|
ebur128->pre.b0 = (Vh + Vb * K / Q + K * K) / a0;
|
||||||
ebur128->pre_b[1] = 2.0 * (K * K - Vh) / a0;
|
ebur128->pre.b1 = 2.0 * (K * K - Vh) / a0;
|
||||||
ebur128->pre_b[2] = (Vh - Vb * K / Q + K * K) / a0;
|
ebur128->pre.b2 = (Vh - Vb * K / Q + K * K) / a0;
|
||||||
ebur128->pre_a[1] = 2.0 * (K * K - 1.0) / a0;
|
ebur128->pre.a1 = 2.0 * (K * K - 1.0) / a0;
|
||||||
ebur128->pre_a[2] = (1.0 - K / Q + K * K) / a0;
|
ebur128->pre.a2 = (1.0 - K / Q + K * K) / a0;
|
||||||
|
|
||||||
f0 = 38.13547087602444;
|
f0 = 38.13547087602444;
|
||||||
Q = 0.5003270373238773;
|
Q = 0.5003270373238773;
|
||||||
K = tan(M_PI * f0 / (double)inlink->sample_rate);
|
K = tan(M_PI * f0 / (double)inlink->sample_rate);
|
||||||
|
|
||||||
ebur128->rlb_b[0] = 1.0;
|
ebur128->rlb.b0 = 1.0;
|
||||||
ebur128->rlb_b[1] = -2.0;
|
ebur128->rlb.b1 = -2.0;
|
||||||
ebur128->rlb_b[2] = 1.0;
|
ebur128->rlb.b2 = 1.0;
|
||||||
ebur128->rlb_a[1] = 2.0 * (K * K - 1.0) / (1.0 + K / Q + K * K);
|
ebur128->rlb.a1 = 2.0 * (K * K - 1.0) / (1.0 + K / Q + K * K);
|
||||||
ebur128->rlb_a[2] = (1.0 - K / Q + K * K) / (1.0 + K / Q + K * K);
|
ebur128->rlb.a2 = (1.0 - K / Q + K * K) / (1.0 + K / Q + K * K);
|
||||||
|
|
||||||
/* Force 100ms framing in case of metadata injection: the frames must have
|
/* Force 100ms framing in case of metadata injection: the frames must have
|
||||||
* a granularity of the window overlap to be accurately exploited.
|
* a granularity of the window overlap to be accurately exploited.
|
||||||
@ -654,6 +657,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const struct biquad pre = ebur128->pre;
|
||||||
|
const struct biquad rlb = ebur128->rlb;
|
||||||
|
|
||||||
for (idx_insample = ebur128->idx_insample; idx_insample < nb_samples; idx_insample++) {
|
for (idx_insample = ebur128->idx_insample; idx_insample < nb_samples; idx_insample++) {
|
||||||
const int bin_id_400 = ebur128->i400.cache_pos;
|
const int bin_id_400 = ebur128->i400.cache_pos;
|
||||||
const int bin_id_3000 = ebur128->i3000.cache_pos;
|
const int bin_id_3000 = ebur128->i3000.cache_pos;
|
||||||
@ -678,10 +684,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Y[i] = X[i]*b0 + X[i-1]*b1 + X[i-2]*b2 - Y[i-1]*a1 - Y[i-2]*a2 */
|
/* Y[i] = X[i]*b0 + X[i-1]*b1 + X[i-2]*b2 - Y[i-1]*a1 - Y[i-2]*a2 */
|
||||||
#define FILTER(DST, SRC, NUM, DEN) do { \
|
#define FILTER(DST, SRC, FILT) do { \
|
||||||
const double tmp = DST[0] = NUM[0] * SRC + DST[1]; \
|
const double tmp = DST[0] = FILT.b0 * SRC + DST[1]; \
|
||||||
DST[1] = NUM[1] * SRC + DST[2] - DEN[1] * tmp; \
|
DST[1] = FILT.b1 * SRC + DST[2] - FILT.a1 * tmp; \
|
||||||
DST[2] = NUM[2] * SRC - DEN[2] * tmp; \
|
DST[2] = FILT.b2 * SRC - FILT.a2 * tmp; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
const double x = samples[idx_insample * nb_channels + ch];
|
const double x = samples[idx_insample * nb_channels + ch];
|
||||||
@ -689,14 +695,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
|
|||||||
double *restrict z = &ebur128->z[3 * ch];
|
double *restrict z = &ebur128->z[3 * ch];
|
||||||
|
|
||||||
// TODO: merge both filters in one?
|
// TODO: merge both filters in one?
|
||||||
FILTER(y, x, ebur128->pre_b, ebur128->pre_a); // apply pre-filter
|
FILTER(y, x, pre); // apply pre-filter
|
||||||
FILTER(z, *y, ebur128->rlb_b, ebur128->rlb_a); // apply RLB-filter
|
FILTER(z, *y, rlb); // apply RLB-filter
|
||||||
|
|
||||||
/* add the new value, and limit the sum to the cache size (400ms or 3s)
|
/* add the new value, and limit the sum to the cache size (400ms or 3s)
|
||||||
* by removing the oldest one */
|
* by removing the oldest one */
|
||||||
double bin = *z * *z;
|
const double bin = *z * *z;
|
||||||
ebur128->i400.sum [ch] = ebur128->i400.sum [ch] + bin - ebur128->i400.cache [ch][bin_id_400];
|
ebur128->i400.sum [ch] += bin - ebur128->i400.cache [ch][bin_id_400];
|
||||||
ebur128->i3000.sum[ch] = ebur128->i3000.sum[ch] + bin - ebur128->i3000.cache[ch][bin_id_3000];
|
ebur128->i3000.sum[ch] += bin - ebur128->i3000.cache[ch][bin_id_3000];
|
||||||
|
|
||||||
/* override old cache entry with the new value */
|
/* override old cache entry with the new value */
|
||||||
ebur128->i400.cache [ch][bin_id_400 ] = bin;
|
ebur128->i400.cache [ch][bin_id_400 ] = bin;
|
||||||
|
Reference in New Issue
Block a user