1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-08-04 22:03:09 +02:00

avfilter/f_ebur128: split off C implementation to separate function

I decided to separate out the peak measurement loop to avoid bloating
the signature, and since it's only conditionally used.
This commit is contained in:
Niklas Haas
2025-06-12 21:03:34 +02:00
parent c7d2b0a7a1
commit deab15e76a
2 changed files with 52 additions and 34 deletions

View File

@ -609,11 +609,48 @@ static int gate_update(struct integrator *integ, double power,
return gate_hist_pos; return gate_hist_pos;
} }
void ff_ebur128_filter_channels_c(const EBUR128DSPContext *dsp,
const double *restrict samples,
double *restrict cache_400,
double *restrict cache_3000,
double *restrict sum_400,
double *restrict sum_3000,
const int nb_channels)
{
const EBUR128Biquad pre = dsp->pre;
const EBUR128Biquad rlb = dsp->rlb;
for (int ch = 0; ch < nb_channels; ch++) {
/* 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, FILT) do { \
const double tmp = DST[0] = FILT.b0 * SRC + DST[1]; \
DST[1] = FILT.b1 * SRC + DST[2] - FILT.a1 * tmp; \
DST[2] = FILT.b2 * SRC - FILT.a2 * tmp; \
} while (0)
const double x = samples[ch];
double *restrict y = &dsp->y[3 * ch];
double *restrict z = &dsp->z[3 * ch];
// TODO: merge both filters in one?
FILTER(y, x, pre); // apply pre-filter
FILTER(z, *y, rlb); // apply RLB-filter
/* add the new value, and limit the sum to the cache size (400ms or 3s)
* by removing the oldest one */
const double bin = *z * *z;
sum_400 [ch] += bin - cache_400[ch];
sum_3000[ch] += bin - cache_3000[ch];
cache_400[ch] = cache_3000[ch] = bin;
}
}
static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
{ {
int i, ch, idx_insample, ret; int i, ch, idx_insample, ret;
AVFilterContext *ctx = inlink->dst; AVFilterContext *ctx = inlink->dst;
EBUR128Context *ebur128 = ctx->priv; EBUR128Context *ebur128 = ctx->priv;
const EBUR128DSPContext *dsp = &ebur128->dsp;
const int nb_channels = ebur128->nb_channels; const int nb_channels = ebur128->nb_channels;
const int nb_samples = insamples->nb_samples; const int nb_samples = insamples->nb_samples;
const double *samples = (double *)insamples->data[0]; const double *samples = (double *)insamples->data[0];
@ -639,14 +676,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
} }
#endif #endif
const EBUR128Biquad pre = ebur128->dsp.pre;
const EBUR128Biquad rlb = ebur128->dsp.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;
double *restrict cache_400 = &ebur128->i400.cache[bin_id_400 * nb_channels];
double *restrict cache_3000 = &ebur128->i3000.cache[bin_id_3000 * nb_channels];
#define MOVE_TO_NEXT_CACHED_ENTRY(time) do { \ #define MOVE_TO_NEXT_CACHED_ENTRY(time) do { \
ebur128->i##time.cache_pos++; \ ebur128->i##time.cache_pos++; \
@ -660,35 +692,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
MOVE_TO_NEXT_CACHED_ENTRY(400); MOVE_TO_NEXT_CACHED_ENTRY(400);
MOVE_TO_NEXT_CACHED_ENTRY(3000); MOVE_TO_NEXT_CACHED_ENTRY(3000);
for (ch = 0; ch < nb_channels; ch++) { ff_ebur128_filter_channels_c(dsp, &samples[idx_insample * nb_channels],
if (ebur128->peak_mode & PEAK_MODE_SAMPLES_PEAKS) &ebur128->i400.cache[bin_id_400 * nb_channels],
ebur128->sample_peaks[ch] = FFMAX(ebur128->sample_peaks[ch], fabs(samples[idx_insample * nb_channels + ch])); &ebur128->i3000.cache[bin_id_3000 * nb_channels],
ebur128->i400.sum, ebur128->i3000.sum,
if (!ebur128->ch_weighting[ch]) nb_channels);
continue;
/* 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, FILT) do { \
const double tmp = DST[0] = FILT.b0 * SRC + DST[1]; \
DST[1] = FILT.b1 * SRC + DST[2] - FILT.a1 * tmp; \
DST[2] = FILT.b2 * SRC - FILT.a2 * tmp; \
} while (0)
const double x = samples[idx_insample * nb_channels + ch];
double *restrict y = &ebur128->dsp.y[3 * ch];
double *restrict z = &ebur128->dsp.z[3 * ch];
// TODO: merge both filters in one?
FILTER(y, x, pre); // apply pre-filter
FILTER(z, *y, rlb); // apply RLB-filter
/* add the new value, and limit the sum to the cache size (400ms or 3s)
* by removing the oldest one */
const double bin = *z * *z;
ebur128->i400.sum [ch] += bin - cache_400[ch];
ebur128->i3000.sum[ch] += bin - cache_3000[ch];
cache_400[ch] = cache_3000[ch] = bin;
}
#define FIND_PEAK(global, sp, ptype) do { \ #define FIND_PEAK(global, sp, ptype) do { \
int ch; \ int ch; \
@ -701,6 +709,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
} \ } \
} while (0) } while (0)
if (ebur128->peak_mode & PEAK_MODE_SAMPLES_PEAKS) {
for (ch = 0; ch < nb_channels; ch++) {
const double sample = samples[idx_insample * nb_channels + ch];
ebur128->sample_peaks[ch] = FFMAX(ebur128->sample_peaks[ch], fabs(sample));
}
}
FIND_PEAK(ebur128->sample_peak, ebur128->sample_peaks, SAMPLES); FIND_PEAK(ebur128->sample_peak, ebur128->sample_peaks, SAMPLES);
FIND_PEAK(ebur128->true_peak, ebur128->true_peaks, TRUE); FIND_PEAK(ebur128->true_peak, ebur128->true_peaks, TRUE);

View File

@ -37,4 +37,7 @@ typedef struct EBUR128DSPContext {
double *z; /* after RLB-filter */ double *z; /* after RLB-filter */
} EBUR128DSPContext; } EBUR128DSPContext;
void ff_ebur128_filter_channels_c(const EBUR128DSPContext *, const double *,
double *, double *, double *, double *, int);
#endif /* AVFILTER_F_EBUR128_H */ #endif /* AVFILTER_F_EBUR128_H */