avfilter/af_surround: allow non-power of 2 win_size

This commit is contained in:
Paul B Mahol 2022-11-16 23:41:31 +01:00
parent 404c2955b1
commit a640b2874a

View File

@ -113,7 +113,6 @@ typedef struct AudioSurroundContext {
float *lfe_mag;
float *mag_total;
int buf_size;
int rdft_size;
int hop_size;
AVTXContext **rdft, **irdft;
@ -286,7 +285,7 @@ static int config_input(AVFilterLink *inlink)
float scale = 1.f;
ret = av_tx_init(&s->rdft[ch], &s->tx_fn, AV_TX_FLOAT_RDFT,
0, s->buf_size, &scale, 0);
0, s->win_size, &scale, 0);
if (ret < 0)
return ret;
}
@ -296,20 +295,20 @@ static int config_input(AVFilterLink *inlink)
set_input_levels(ctx);
s->window = ff_get_audio_buffer(inlink, s->buf_size * 2);
s->window = ff_get_audio_buffer(inlink, s->win_size * 2);
if (!s->window)
return AVERROR(ENOMEM);
s->input_in = ff_get_audio_buffer(inlink, s->buf_size * 2);
s->input_in = ff_get_audio_buffer(inlink, s->win_size * 2);
if (!s->input_in)
return AVERROR(ENOMEM);
s->input = ff_get_audio_buffer(inlink, s->buf_size + 2);
s->input = ff_get_audio_buffer(inlink, s->win_size + 2);
if (!s->input)
return AVERROR(ENOMEM);
s->lowcut = 1.f * s->lowcutf / (inlink->sample_rate * 0.5) * (s->buf_size / 2);
s->highcut = 1.f * s->highcutf / (inlink->sample_rate * 0.5) * (s->buf_size / 2);
s->lowcut = 1.f * s->lowcutf / (inlink->sample_rate * 0.5) * (s->win_size / 2);
s->highcut = 1.f * s->highcutf / (inlink->sample_rate * 0.5) * (s->win_size / 2);
return 0;
}
@ -329,7 +328,7 @@ static int config_output(AVFilterLink *outlink)
float iscale = 1.f;
ret = av_tx_init(&s->irdft[ch], &s->itx_fn, AV_TX_FLOAT_RDFT,
1, s->buf_size, &iscale, 0);
1, s->win_size, &iscale, 0);
if (ret < 0)
return ret;
}
@ -340,13 +339,13 @@ static int config_output(AVFilterLink *outlink)
set_output_levels(ctx);
s->output_out = ff_get_audio_buffer(outlink, s->buf_size + 2);
s->output = ff_get_audio_buffer(outlink, s->buf_size + 2);
s->overlap_buffer = ff_get_audio_buffer(outlink, s->buf_size * 2);
s->output_out = ff_get_audio_buffer(outlink, s->win_size + 2);
s->output = ff_get_audio_buffer(outlink, s->win_size + 2);
s->overlap_buffer = ff_get_audio_buffer(outlink, s->win_size * 2);
if (!s->overlap_buffer || !s->output || !s->output_out)
return AVERROR(ENOMEM);
s->rdft_size = s->buf_size / 2 + 1;
s->rdft_size = s->win_size / 2 + 1;
s->x_pos = av_calloc(s->rdft_size, sizeof(*s->x_pos));
s->y_pos = av_calloc(s->rdft_size, sizeof(*s->y_pos));
@ -1222,19 +1221,17 @@ fail:
return AVERROR(EINVAL);
}
s->buf_size = 1 << av_log2(s->win_size);
s->window_func_lut = av_calloc(s->buf_size, sizeof(*s->window_func_lut));
s->window_func_lut = av_calloc(s->win_size, sizeof(*s->window_func_lut));
if (!s->window_func_lut)
return AVERROR(ENOMEM);
generate_window_func(s->window_func_lut, s->buf_size, s->win_func, &overlap);
generate_window_func(s->window_func_lut, s->win_size, s->win_func, &overlap);
if (s->overlap == 1)
s->overlap = overlap;
for (i = 0; i < s->buf_size; i++)
s->window_func_lut[i] = sqrtf(s->window_func_lut[i] / s->buf_size);
s->hop_size = FFMAX(1, s->buf_size * (1. - s->overlap));
for (i = 0; i < s->win_size; i++)
s->window_func_lut[i] = sqrtf(s->window_func_lut[i] / s->win_size);
s->hop_size = FFMAX(1, s->win_size * (1. - s->overlap));
allchannels_spread(ctx);
@ -1246,14 +1243,14 @@ static int fft_channel(AVFilterContext *ctx, AVFrame *in, int ch)
AudioSurroundContext *s = ctx->priv;
float *src = (float *)s->input_in->extended_data[ch];
float *win = (float *)s->window->extended_data[ch];
const int offset = s->buf_size - s->hop_size;
const int offset = s->win_size - s->hop_size;
const float level_in = s->input_levels[ch];
memmove(src, &src[s->hop_size], offset * sizeof(float));
memcpy(&src[offset], in->extended_data[ch], in->nb_samples * sizeof(float));
memset(&src[offset + in->nb_samples], 0, (s->hop_size - in->nb_samples) * sizeof(float));
for (int n = 0; n < s->buf_size; n++)
for (int n = 0; n < s->win_size; n++)
win[n] = src[n] * s->window_func_lut[n] * level_in;
s->tx_fn(s->rdft[ch], (float *)s->input->extended_data[ch], win, sizeof(float));
@ -1285,11 +1282,11 @@ static int ifft_channel(AVFilterContext *ctx, AVFrame *out, int ch)
memmove(s->overlap_buffer->extended_data[ch],
s->overlap_buffer->extended_data[ch] + s->hop_size * sizeof(float),
s->buf_size * sizeof(float));
memset(s->overlap_buffer->extended_data[ch] + s->buf_size * sizeof(float),
s->win_size * sizeof(float));
memset(s->overlap_buffer->extended_data[ch] + s->win_size * sizeof(float),
0, s->hop_size * sizeof(float));
for (int n = 0; n < s->buf_size; n++)
for (int n = 0; n < s->win_size; n++)
ptr[n] += dst[n] * s->window_func_lut[n] * level_out;
ptr = (float *)s->overlap_buffer->extended_data[ch];
@ -1418,7 +1415,7 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar
if (ret < 0)
return ret;
s->hop_size = FFMAX(1, s->buf_size * (1. - s->overlap));
s->hop_size = FFMAX(1, s->win_size * (1. - s->overlap));
allchannels_spread(ctx);
set_input_levels(ctx);