I decided to separate out the peak measurement loop to avoid bloating the signature, and since it's only conditionally used.
Unified · Split
| @@ -609,11 +609,48 @@ static int gate_update(struct integrator *integ, double power, · 608 unmodified lines | ||
| 609 | 609 | return gate_hist_pos; |
| 610 | 610 | } |
| 611 | 611 | |
| 612 | +void ff_ebur128_filter_channels_c(const EBUR128DSPContext *dsp, | |
| 613 | + const double *restrict samples, | |
| 614 | + double *restrict cache_400, | |
| 615 | + double *restrict cache_3000, | |
| 616 | + double *restrict sum_400, | |
| 617 | + double *restrict sum_3000, | |
| 618 | + const int nb_channels) | |
| 619 | +{ | |
| 620 | + const EBUR128Biquad pre = dsp->pre; | |
| 621 | + const EBUR128Biquad rlb = dsp->rlb; | |
| 622 | + | |
| 623 | + for (int ch = 0; ch < nb_channels; ch++) { | |
| 624 | + /* Y[i] = X[i]*b0 + X[i-1]*b1 + X[i-2]*b2 - Y[i-1]*a1 - Y[i-2]*a2 */ | |
| 625 | +#define FILTER(DST, SRC, FILT) do { \ | |
| 626 | + const double tmp = DST[0] = FILT.b0 * SRC + DST[1]; \ | |
| 627 | + DST[1] = FILT.b1 * SRC + DST[2] - FILT.a1 * tmp; \ | |
| 628 | + DST[2] = FILT.b2 * SRC - FILT.a2 * tmp; \ | |
| 629 | +} while (0) | |
| 630 | + | |
| 631 | + const double x = samples[ch]; | |
| 632 | + double *restrict y = &dsp->y[3 * ch]; | |
| 633 | + double *restrict z = &dsp->z[3 * ch]; | |
| 634 | + | |
| 635 | + // TODO: merge both filters in one? | |
| 636 | + FILTER(y, x, pre); // apply pre-filter | |
| 637 | + FILTER(z, *y, rlb); // apply RLB-filter | |
| 638 | + | |
| 639 | + /* add the new value, and limit the sum to the cache size (400ms or 3s) | |
| 640 | + * by removing the oldest one */ | |
| 641 | + const double bin = *z * *z; | |
| 642 | + sum_400 [ch] += bin - cache_400[ch]; | |
| 643 | + sum_3000[ch] += bin - cache_3000[ch]; | |
| 644 | + cache_400[ch] = cache_3000[ch] = bin; | |
| 645 | + } | |
| 646 | +} | |
| 647 | + | |
| 612 | 648 | static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) |
| 613 | 649 | { |
| 614 | 650 | int i, ch, idx_insample, ret; |
| 615 | 651 | AVFilterContext *ctx = inlink->dst; |
| 616 | 652 | EBUR128Context *ebur128 = ctx->priv; |
| 653 | + const EBUR128DSPContext *dsp = &ebur128->dsp; | |
| 617 | 654 | const int nb_channels = ebur128->nb_channels; |
| 618 | 655 | const int nb_samples = insamples->nb_samples; |
| 619 | 656 | const double *samples = (double *)insamples->data[0]; |
| @@ -639,14 +676,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) · 19 unmodified lines | ||
| 639 | 676 | } |
| 640 | 677 | #endif |
| 641 | 678 | |
| 642 | − const EBUR128Biquad pre = ebur128->dsp.pre; | |
| 643 | − const EBUR128Biquad rlb = ebur128->dsp.rlb; | |
| 644 | − | |
| 645 | 679 | for (idx_insample = ebur128->idx_insample; idx_insample < nb_samples; idx_insample++) { |
| 646 | 680 | const int bin_id_400 = ebur128->i400.cache_pos; |
| 647 | 681 | const int bin_id_3000 = ebur128->i3000.cache_pos; |
| 648 | − double *restrict cache_400 = &ebur128->i400.cache[bin_id_400 * nb_channels]; | |
| 649 | − double *restrict cache_3000 = &ebur128->i3000.cache[bin_id_3000 * nb_channels]; | |
| 650 | 682 | |
| 651 | 683 | #define MOVE_TO_NEXT_CACHED_ENTRY(time) do { \ |
| 652 | 684 | ebur128->i##time.cache_pos++; \ |
| @@ -660,35 +692,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) · 7 unmodified lines | ||
| 660 | 692 | MOVE_TO_NEXT_CACHED_ENTRY(400); |
| 661 | 693 | MOVE_TO_NEXT_CACHED_ENTRY(3000); |
| 662 | 694 | |
| 663 | − for (ch = 0; ch < nb_channels; ch++) { | |
| 664 | − if (ebur128->peak_mode & PEAK_MODE_SAMPLES_PEAKS) | |
| 665 | − ebur128->sample_peaks[ch] = FFMAX(ebur128->sample_peaks[ch], fabs(samples[idx_insample * nb_channels + ch])); | |
| 666 | − | |
| 667 | − if (!ebur128->ch_weighting[ch]) | |
| 668 | − continue; | |
| 669 | − | |
| 670 | − /* Y[i] = X[i]*b0 + X[i-1]*b1 + X[i-2]*b2 - Y[i-1]*a1 - Y[i-2]*a2 */ | |
| 671 | −#define FILTER(DST, SRC, FILT) do { \ | |
| 672 | − const double tmp = DST[0] = FILT.b0 * SRC + DST[1]; \ | |
| 673 | − DST[1] = FILT.b1 * SRC + DST[2] - FILT.a1 * tmp; \ | |
| 674 | − DST[2] = FILT.b2 * SRC - FILT.a2 * tmp; \ | |
| 675 | −} while (0) | |
| 676 | − | |
| 677 | − const double x = samples[idx_insample * nb_channels + ch]; | |
| 678 | − double *restrict y = &ebur128->dsp.y[3 * ch]; | |
| 679 | − double *restrict z = &ebur128->dsp.z[3 * ch]; | |
| 680 | − | |
| 681 | − // TODO: merge both filters in one? | |
| 682 | − FILTER(y, x, pre); // apply pre-filter | |
| 683 | − FILTER(z, *y, rlb); // apply RLB-filter | |
| 684 | − | |
| 685 | − /* add the new value, and limit the sum to the cache size (400ms or 3s) | |
| 686 | − * by removing the oldest one */ | |
| 687 | − const double bin = *z * *z; | |
| 688 | − ebur128->i400.sum [ch] += bin - cache_400[ch]; | |
| 689 | − ebur128->i3000.sum[ch] += bin - cache_3000[ch]; | |
| 690 | − cache_400[ch] = cache_3000[ch] = bin; | |
| 691 | − } | |
| 695 | + ff_ebur128_filter_channels_c(dsp, &samples[idx_insample * nb_channels], | |
| 696 | + &ebur128->i400.cache[bin_id_400 * nb_channels], | |
| 697 | + &ebur128->i3000.cache[bin_id_3000 * nb_channels], | |
| 698 | + ebur128->i400.sum, ebur128->i3000.sum, | |
| 699 | + nb_channels); | |
| 692 | 700 | |
| 693 | 701 | #define FIND_PEAK(global, sp, ptype) do { \ |
| 694 | 702 | int ch; \ |
| @@ -701,6 +709,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) · 6 unmodified lines | ||
| 701 | 709 | } \ |
| 702 | 710 | } while (0) |
| 703 | 711 | |
| 712 | + if (ebur128->peak_mode & PEAK_MODE_SAMPLES_PEAKS) { | |
| 713 | + for (ch = 0; ch < nb_channels; ch++) { | |
| 714 | + const double sample = samples[idx_insample * nb_channels + ch]; | |
| 715 | + ebur128->sample_peaks[ch] = FFMAX(ebur128->sample_peaks[ch], fabs(sample)); | |
| 716 | + } | |
| 717 | + } | |
| 718 | + | |
| 704 | 719 | FIND_PEAK(ebur128->sample_peak, ebur128->sample_peaks, SAMPLES); |
| 705 | 720 | FIND_PEAK(ebur128->true_peak, ebur128->true_peaks, TRUE); |
| 706 | 721 | |
| @@ -37,4 +37,7 @@ typedef struct EBUR128DSPContext { · 36 unmodified lines | ||
| 37 | 37 | double *z; /* after RLB-filter */ |
| 38 | 38 | } EBUR128DSPContext; |
| 39 | 39 | |
| 40 | +void ff_ebur128_filter_channels_c(const EBUR128DSPContext *, const double *, | |
| 41 | + double *, double *, double *, double *, int); | |
| 42 | + | |
| 40 | 43 | #endif /* AVFILTER_F_EBUR128_H */ |