Unified · Split
| @@ -27,13 +27,18 @@ · 26 unmodified lines | |||
| 27 | #include "filters.h" | 27 | #include "filters.h" |
| 28 | #include "internal.h" | 28 | #include "internal.h" |
| 29 | 29 | ||
| 30 | typedef struct ChanStats { | ||
| 31 | double u; | ||
| 32 | double v; | ||
| 33 | double uv; | ||
| 34 | } ChanStats; | ||
| 35 | |||
| 30 | typedef struct AudioSDRContext { | 36 | typedef struct AudioSDRContext { |
| 31 | int channels; | 37 | int channels; |
| 32 | uint64_t nb_samples; | 38 | uint64_t nb_samples; |
| 33 | double max; | 39 | double max; |
| 34 | double *sum_u; | 40 | |
| 35 | double *sum_v; | 41 | ChanStats *chs; |
| 36 | double *sum_uv; | ||
| 37 | 42 | ||
| 38 | AVFrame *cache[2]; | 43 | AVFrame *cache[2]; |
| 39 | 44 | ||
| @@ -52,6 +57,7 @@ static int sdr_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)\ · 12 unmodified lines | |||
| 52 | const int nb_samples = u->nb_samples; \ | 57 | const int nb_samples = u->nb_samples; \ |
| 53 | \ | 58 | \ |
| 54 | for (int ch = start; ch < end; ch++) { \ | 59 | for (int ch = start; ch < end; ch++) { \ |
| 60 | ChanStats *chs = &s->chs[ch]; \ | ||
| 55 | const type *const us = (type *)u->extended_data[ch]; \ | 61 | const type *const us = (type *)u->extended_data[ch]; \ |
| 56 | const type *const vs = (type *)v->extended_data[ch]; \ | 62 | const type *const vs = (type *)v->extended_data[ch]; \ |
| 57 | double sum_uv = 0.; \ | 63 | double sum_uv = 0.; \ |
| @@ -62,8 +68,8 @@ static int sdr_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)\ · 4 unmodified lines | |||
| 62 | sum_uv += (us[n] - vs[n]) * (us[n] - vs[n]); \ | 68 | sum_uv += (us[n] - vs[n]) * (us[n] - vs[n]); \ |
| 63 | } \ | 69 | } \ |
| 64 | \ | 70 | \ |
| 65 | s->sum_uv[ch] += sum_uv; \ | 71 | chs->uv += sum_uv; \ |
| 66 | s->sum_u[ch] += sum_u; \ | 72 | chs->u += sum_u; \ |
| 67 | } \ | 73 | } \ |
| 68 | \ | 74 | \ |
| 69 | return 0; \ | 75 | return 0; \ |
| @@ -84,6 +90,7 @@ static int sisdr_##name(AVFilterContext *ctx, void *arg,int jobnr,int nb_jobs)\ · 14 unmodified lines | |||
| 84 | const int nb_samples = u->nb_samples; \ | 90 | const int nb_samples = u->nb_samples; \ |
| 85 | \ | 91 | \ |
| 86 | for (int ch = start; ch < end; ch++) { \ | 92 | for (int ch = start; ch < end; ch++) { \ |
| 93 | ChanStats *chs = &s->chs[ch]; \ | ||
| 87 | const type *const us = (type *)u->extended_data[ch]; \ | 94 | const type *const us = (type *)u->extended_data[ch]; \ |
| 88 | const type *const vs = (type *)v->extended_data[ch]; \ | 95 | const type *const vs = (type *)v->extended_data[ch]; \ |
| 89 | double sum_uv = 0.; \ | 96 | double sum_uv = 0.; \ |
| @@ -96,9 +103,9 @@ static int sisdr_##name(AVFilterContext *ctx, void *arg,int jobnr,int nb_jobs)\ · 6 unmodified lines | |||
| 96 | sum_uv += us[n] * vs[n]; \ | 103 | sum_uv += us[n] * vs[n]; \ |
| 97 | } \ | 104 | } \ |
| 98 | \ | 105 | \ |
| 99 | s->sum_uv[ch] += sum_uv; \ | 106 | chs->uv += sum_uv; \ |
| 100 | s->sum_u[ch] += sum_u; \ | 107 | chs->u += sum_u; \ |
| 101 | s->sum_v[ch] += sum_v; \ | 108 | chs->v += sum_v; \ |
| 102 | } \ | 109 | } \ |
| 103 | \ | 110 | \ |
| 104 | return 0; \ | 111 | return 0; \ |
| @@ -119,6 +126,7 @@ static int psnr_##name(AVFilterContext *ctx, void *arg, int jobnr,int nb_jobs)\ · 14 unmodified lines | |||
| 119 | const int nb_samples = u->nb_samples; \ | 126 | const int nb_samples = u->nb_samples; \ |
| 120 | \ | 127 | \ |
| 121 | for (int ch = start; ch < end; ch++) { \ | 128 | for (int ch = start; ch < end; ch++) { \ |
| 129 | ChanStats *chs = &s->chs[ch]; \ | ||
| 122 | const type *const us = (type *)u->extended_data[ch]; \ | 130 | const type *const us = (type *)u->extended_data[ch]; \ |
| 123 | const type *const vs = (type *)v->extended_data[ch]; \ | 131 | const type *const vs = (type *)v->extended_data[ch]; \ |
| 124 | double sum_uv = 0.; \ | 132 | double sum_uv = 0.; \ |
| @@ -126,7 +134,7 @@ static int psnr_##name(AVFilterContext *ctx, void *arg, int jobnr,int nb_jobs)\ · 1 unmodified line | |||
| 126 | for (int n = 0; n < nb_samples; n++) \ | 134 | for (int n = 0; n < nb_samples; n++) \ |
| 127 | sum_uv += (us[n] - vs[n]) * (us[n] - vs[n]); \ | 135 | sum_uv += (us[n] - vs[n]) * (us[n] - vs[n]); \ |
| 128 | \ | 136 | \ |
| 129 | s->sum_uv[ch] += sum_uv; \ | 137 | chs->uv += sum_uv; \ |
| 130 | } \ | 138 | } \ |
| 131 | \ | 139 | \ |
| 132 | return 0; \ | 140 | return 0; \ |
| @@ -204,10 +212,8 @@ static int config_output(AVFilterLink *outlink) · 71 unmodified lines | |||
| 204 | s->filter = inlink->format == AV_SAMPLE_FMT_FLTP ? psnr_fltp : psnr_dblp; | 212 | s->filter = inlink->format == AV_SAMPLE_FMT_FLTP ? psnr_fltp : psnr_dblp; |
| 205 | s->max = inlink->format == AV_SAMPLE_FMT_FLTP ? FLT_MAX : DBL_MAX; | 213 | s->max = inlink->format == AV_SAMPLE_FMT_FLTP ? FLT_MAX : DBL_MAX; |
| 206 | 214 | ||
| 207 | s->sum_u = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->sum_u)); | 215 | s->chs = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->chs)); |
| 208 | s->sum_v = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->sum_v)); | 216 | if (!s->chs) |
| 209 | s->sum_uv = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->sum_uv)); | ||
| 210 | if (!s->sum_u || !s->sum_uv || !s->sum_v) | ||
| 211 | return AVERROR(ENOMEM); | 217 | return AVERROR(ENOMEM); |
| 212 | 218 | ||
| 213 | return 0; | 219 | return 0; |
| @@ -219,17 +225,17 @@ static av_cold void uninit(AVFilterContext *ctx) · 5 unmodified lines | |||
| 219 | 225 | ||
| 220 | if (!strcmp(ctx->filter->name, "asdr")) { | 226 | if (!strcmp(ctx->filter->name, "asdr")) { |
| 221 | for (int ch = 0; ch < s->channels; ch++) | 227 | for (int ch = 0; ch < s->channels; ch++) |
| 222 | av_log(ctx, AV_LOG_INFO, "SDR ch%d: %g dB\n", ch, 20. * log10(s->sum_u[ch] / s->sum_uv[ch])); | 228 | av_log(ctx, AV_LOG_INFO, "SDR ch%d: %g dB\n", ch, 20. * log10(s->chs[ch].u / s->chs[ch].uv)); |
| 223 | } else if (!strcmp(ctx->filter->name, "asisdr")) { | 229 | } else if (!strcmp(ctx->filter->name, "asisdr")) { |
| 224 | for (int ch = 0; ch < s->channels; ch++) { | 230 | for (int ch = 0; ch < s->channels; ch++) { |
| 225 | double scale = s->sum_uv[ch] / s->sum_v[ch]; | 231 | double scale = s->chs[ch].uv / s->chs[ch].v; |
| 226 | double sisdr = s->sum_u[ch] / (s->sum_u[ch] + scale*scale*s->sum_v[ch] - 2.0*scale*s->sum_uv[ch]); | 232 | double sisdr = s->chs[ch].u / fmax(0., s->chs[ch].u + scale*scale*s->chs[ch].v - 2.0*scale*s->chs[ch].uv); |
| 227 | 233 | ||
| 228 | av_log(ctx, AV_LOG_INFO, "SI-SDR ch%d: %g dB\n", ch, 10. * log10(sisdr)); | 234 | av_log(ctx, AV_LOG_INFO, "SI-SDR ch%d: %g dB\n", ch, 10. * log10(sisdr)); |
| 229 | } | 235 | } |
| 230 | } else { | 236 | } else { |
| 231 | for (int ch = 0; ch < s->channels; ch++) { | 237 | for (int ch = 0; ch < s->channels; ch++) { |
| 232 | double psnr = s->sum_uv[ch] > 0.0 ? 2.0 * log(s->max) - log(s->nb_samples / s->sum_uv[ch]) : INFINITY; | 238 | double psnr = s->chs[ch].uv > 0.0 ? 2.0 * log(s->max) - log(s->nb_samples / s->chs[ch].uv) : INFINITY; |
| 233 | 239 | ||
| 234 | av_log(ctx, AV_LOG_INFO, "PSNR ch%d: %g dB\n", ch, psnr); | 240 | av_log(ctx, AV_LOG_INFO, "PSNR ch%d: %g dB\n", ch, psnr); |
| 235 | } | 241 | } |
| @@ -238,9 +244,7 @@ static av_cold void uninit(AVFilterContext *ctx) · 2 unmodified lines | |||
| 238 | av_frame_free(&s->cache[0]); | 244 | av_frame_free(&s->cache[0]); |
| 239 | av_frame_free(&s->cache[1]); | 245 | av_frame_free(&s->cache[1]); |
| 240 | 246 | ||
| 241 | av_freep(&s->sum_u); | 247 | av_freep(&s->chs); |
| 242 | av_freep(&s->sum_v); | ||
| 243 | av_freep(&s->sum_uv); | ||
| 244 | } | 248 | } |
| 245 | 249 | ||
| 246 | static const AVFilterPad inputs[] = { | 250 | static const AVFilterPad inputs[] = { |