avfilter/af_aiir: calculate group delay too

This commit is contained in:
Paul B Mahol 2019-07-13 15:43:17 +02:00
parent 18c808ffbe
commit 80dacbedba
2 changed files with 31 additions and 4 deletions
doc
libavfilter

@ -1397,7 +1397,7 @@ How much to use filtered signal in output. Default is 1.
Range is between 0 and 1. Range is between 0 and 1.
@item response @item response
Show IR frequency response, magnitude and phase in additional video stream. Show IR frequency response, magnitude(magenta), phase(green) and group delay(yellow) in additional video stream.
By default it is disabled. By default it is disabled.
@item channel @item channel

@ -721,8 +721,9 @@ static void draw_line(AVFrame *out, int x0, int y0, int x1, int y1, uint32_t col
static void draw_response(AVFilterContext *ctx, AVFrame *out) static void draw_response(AVFilterContext *ctx, AVFrame *out)
{ {
AudioIIRContext *s = ctx->priv; AudioIIRContext *s = ctx->priv;
float *mag, *phase, min = FLT_MAX, max = FLT_MIN; float *mag, *phase, *delay, min = FLT_MAX, max = FLT_MIN;
int prev_ymag = -1, prev_yphase = -1; float min_delay = FLT_MAX, max_delay = FLT_MIN;
int prev_ymag = -1, prev_yphase = -1, prev_ydelay = -1;
char text[32]; char text[32];
int ch, i, x; int ch, i, x;
@ -730,7 +731,8 @@ static void draw_response(AVFilterContext *ctx, AVFrame *out)
phase = av_malloc_array(s->w, sizeof(*phase)); phase = av_malloc_array(s->w, sizeof(*phase));
mag = av_malloc_array(s->w, sizeof(*mag)); mag = av_malloc_array(s->w, sizeof(*mag));
if (!mag || !phase) delay = av_malloc_array(s->w, sizeof(*delay));
if (!mag || !phase || !delay)
goto end; goto end;
ch = av_clip(s->ir_channel, 0, s->channels - 1); ch = av_clip(s->ir_channel, 0, s->channels - 1);
@ -795,23 +797,39 @@ static void draw_response(AVFilterContext *ctx, AVFrame *out)
max = fmaxf(max, mag[i]); max = fmaxf(max, mag[i]);
} }
for (i = 0; i < s->w - 1; i++) {
float dw = M_PI / (s->w - 1);
delay[i] = -(phase[i + 1] - phase[i]) / dw;
min_delay = fminf(min_delay, delay[i]);
max_delay = fmaxf(max_delay, delay[i]);
}
delay[i] = delay[i - 1];
for (i = 0; i < s->w; i++) { for (i = 0; i < s->w; i++) {
int ymag = mag[i] / max * (s->h - 1); int ymag = mag[i] / max * (s->h - 1);
int ydelay = (delay[i] - min_delay) / (max_delay - min_delay) * (s->h - 1);
int yphase = (0.5 * (1. + phase[i] / M_PI)) * (s->h - 1); int yphase = (0.5 * (1. + phase[i] / M_PI)) * (s->h - 1);
ymag = s->h - 1 - av_clip(ymag, 0, s->h - 1); ymag = s->h - 1 - av_clip(ymag, 0, s->h - 1);
yphase = s->h - 1 - av_clip(yphase, 0, s->h - 1); yphase = s->h - 1 - av_clip(yphase, 0, s->h - 1);
ydelay = s->h - 1 - av_clip(ydelay, 0, s->h - 1);
if (prev_ymag < 0) if (prev_ymag < 0)
prev_ymag = ymag; prev_ymag = ymag;
if (prev_yphase < 0) if (prev_yphase < 0)
prev_yphase = yphase; prev_yphase = yphase;
if (prev_ydelay < 0)
prev_ydelay = ydelay;
draw_line(out, i, ymag, FFMAX(i - 1, 0), prev_ymag, 0xFFFF00FF); draw_line(out, i, ymag, FFMAX(i - 1, 0), prev_ymag, 0xFFFF00FF);
draw_line(out, i, yphase, FFMAX(i - 1, 0), prev_yphase, 0xFF00FF00); draw_line(out, i, yphase, FFMAX(i - 1, 0), prev_yphase, 0xFF00FF00);
draw_line(out, i, ydelay, FFMAX(i - 1, 0), prev_ydelay, 0xFF00FFFF);
prev_ymag = ymag; prev_ymag = ymag;
prev_yphase = yphase; prev_yphase = yphase;
prev_ydelay = ydelay;
} }
if (s->w > 400 && s->h > 100) { if (s->w > 400 && s->h > 100) {
@ -822,9 +840,18 @@ static void draw_response(AVFilterContext *ctx, AVFrame *out)
drawtext(out, 2, 12, "Min Magnitude:", 0xDDDDDDDD); drawtext(out, 2, 12, "Min Magnitude:", 0xDDDDDDDD);
snprintf(text, sizeof(text), "%.2f", min); snprintf(text, sizeof(text), "%.2f", min);
drawtext(out, 15 * 8 + 2, 12, text, 0xDDDDDDDD); drawtext(out, 15 * 8 + 2, 12, text, 0xDDDDDDDD);
drawtext(out, 2, 22, "Max Delay:", 0xDDDDDDDD);
snprintf(text, sizeof(text), "%.2f", max_delay);
drawtext(out, 11 * 8 + 2, 22, text, 0xDDDDDDDD);
drawtext(out, 2, 32, "Min Delay:", 0xDDDDDDDD);
snprintf(text, sizeof(text), "%.2f", min_delay);
drawtext(out, 11 * 8 + 2, 32, text, 0xDDDDDDDD);
} }
end: end:
av_free(delay);
av_free(phase); av_free(phase);
av_free(mag); av_free(mag);
} }