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 | return gate_hist_pos; | 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 | static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) | 648 | static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) |
| 613 | { | 649 | { |
| 614 | int i, ch, idx_insample, ret; | 650 | int i, ch, idx_insample, ret; |
| 615 | AVFilterContext *ctx = inlink->dst; | 651 | AVFilterContext *ctx = inlink->dst; |
| 616 | EBUR128Context *ebur128 = ctx->priv; | 652 | EBUR128Context *ebur128 = ctx->priv; |
| 653 | const EBUR128DSPContext *dsp = &ebur128->dsp; | ||
| 617 | const int nb_channels = ebur128->nb_channels; | 654 | const int nb_channels = ebur128->nb_channels; |
| 618 | const int nb_samples = insamples->nb_samples; | 655 | const int nb_samples = insamples->nb_samples; |
| 619 | const double *samples = (double *)insamples->data[0]; | 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 | #endif | 677 | #endif |
| 641 | 678 | ||
| 642 | const EBUR128Biquad pre = ebur128->dsp.pre; | ||
| 643 | const EBUR128Biquad rlb = ebur128->dsp.rlb; | ||
| 644 | |||
| 645 | for (idx_insample = ebur128->idx_insample; idx_insample < nb_samples; idx_insample++) { | 679 | for (idx_insample = ebur128->idx_insample; idx_insample < nb_samples; idx_insample++) { |
| 646 | const int bin_id_400 = ebur128->i400.cache_pos; | 680 | const int bin_id_400 = ebur128->i400.cache_pos; |
| 647 | const int bin_id_3000 = ebur128->i3000.cache_pos; | 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 | #define MOVE_TO_NEXT_CACHED_ENTRY(time) do { \ | 683 | #define MOVE_TO_NEXT_CACHED_ENTRY(time) do { \ |
| 652 | ebur128->i##time.cache_pos++; \ | 684 | ebur128->i##time.cache_pos++; \ |
| @@ -660,35 +692,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) · 7 unmodified lines | |||
| 660 | MOVE_TO_NEXT_CACHED_ENTRY(400); | 692 | MOVE_TO_NEXT_CACHED_ENTRY(400); |
| 661 | MOVE_TO_NEXT_CACHED_ENTRY(3000); | 693 | MOVE_TO_NEXT_CACHED_ENTRY(3000); |
| 662 | 694 | ||
| 663 | for (ch = 0; ch < nb_channels; ch++) { | 695 | ff_ebur128_filter_channels_c(dsp, &samples[idx_insample * nb_channels], |
| 664 | if (ebur128->peak_mode & PEAK_MODE_SAMPLES_PEAKS) | 696 | &ebur128->i400.cache[bin_id_400 * nb_channels], |
| 665 | ebur128->sample_peaks[ch] = FFMAX(ebur128->sample_peaks[ch], fabs(samples[idx_insample * nb_channels + ch])); | 697 | &ebur128->i3000.cache[bin_id_3000 * nb_channels], |
| 666 | 698 | ebur128->i400.sum, ebur128->i3000.sum, | |
| 667 | if (!ebur128->ch_weighting[ch]) | 699 | nb_channels); |
| 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 | } | ||
| 692 | 700 | ||
| 693 | #define FIND_PEAK(global, sp, ptype) do { \ | 701 | #define FIND_PEAK(global, sp, ptype) do { \ |
| 694 | int ch; \ | 702 | int ch; \ |
| @@ -701,6 +709,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) · 6 unmodified lines | |||
| 701 | } \ | 709 | } \ |
| 702 | } while (0) | 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 | FIND_PEAK(ebur128->sample_peak, ebur128->sample_peaks, SAMPLES); | 719 | FIND_PEAK(ebur128->sample_peak, ebur128->sample_peaks, SAMPLES); |
| 705 | FIND_PEAK(ebur128->true_peak, ebur128->true_peaks, TRUE); | 720 | FIND_PEAK(ebur128->true_peak, ebur128->true_peaks, TRUE); |
| 706 | 721 | ||
| @@ -37,4 +37,7 @@ typedef struct EBUR128DSPContext { · 36 unmodified lines | |||
| 37 | double *z; /* after RLB-filter */ | 37 | double *z; /* after RLB-filter */ |
| 38 | } EBUR128DSPContext; | 38 | } EBUR128DSPContext; |
| 39 | 39 | ||
| 40 | void ff_ebur128_filter_channels_c(const EBUR128DSPContext *, const double *, | ||
| 41 | double *, double *, double *, double *, int); | ||
| 42 | |||
| 40 | #endif /* AVFILTER_F_EBUR128_H */ | 43 | #endif /* AVFILTER_F_EBUR128_H */ |