avfilter/af_afir: switch to lavu/tx
This commit is contained in:
parent
8ca06a8148
commit
d388dc20b9
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
|
#include "libavutil/tx.h"
|
||||||
#include "libavutil/avstring.h"
|
#include "libavutil/avstring.h"
|
||||||
#include "libavutil/channel_layout.h"
|
#include "libavutil/channel_layout.h"
|
||||||
#include "libavutil/common.h"
|
#include "libavutil/common.h"
|
||||||
@ -32,7 +33,6 @@
|
|||||||
#include "libavutil/intreadwrite.h"
|
#include "libavutil/intreadwrite.h"
|
||||||
#include "libavutil/opt.h"
|
#include "libavutil/opt.h"
|
||||||
#include "libavutil/xga_font_data.h"
|
#include "libavutil/xga_font_data.h"
|
||||||
#include "libavcodec/avfft.h"
|
|
||||||
|
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "avfilter.h"
|
#include "avfilter.h"
|
||||||
@ -58,7 +58,7 @@ static void fcmul_add_c(float *sum, const float *t, const float *c, ptrdiff_t le
|
|||||||
sum[2 * n] += t[2 * n] * c[2 * n];
|
sum[2 * n] += t[2 * n] * c[2 * n];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void direct(const float *in, const FFTComplex *ir, int len, float *out)
|
static void direct(const float *in, const AVComplexFloat *ir, int len, float *out)
|
||||||
{
|
{
|
||||||
for (int n = 0; n < len; n++)
|
for (int n = 0; n < len; n++)
|
||||||
for (int m = 0; m <= n; m++)
|
for (int m = 0; m <= n; m++)
|
||||||
@ -79,7 +79,7 @@ static int fir_quantum(AVFilterContext *ctx, AVFrame *out, int ch, int offset)
|
|||||||
{
|
{
|
||||||
AudioFIRContext *s = ctx->priv;
|
AudioFIRContext *s = ctx->priv;
|
||||||
const float *in = (const float *)s->in->extended_data[ch] + offset;
|
const float *in = (const float *)s->in->extended_data[ch] + offset;
|
||||||
float *block, *buf, *ptr = (float *)out->extended_data[ch] + offset;
|
float *blockin, *blockout, *buf, *ptr = (float *)out->extended_data[ch] + offset;
|
||||||
const int nb_samples = FFMIN(s->min_part_size, out->nb_samples - offset);
|
const int nb_samples = FFMIN(s->min_part_size, out->nb_samples - offset);
|
||||||
int n, i, j;
|
int n, i, j;
|
||||||
|
|
||||||
@ -87,7 +87,8 @@ static int fir_quantum(AVFilterContext *ctx, AVFrame *out, int ch, int offset)
|
|||||||
AudioFIRSegment *seg = &s->seg[segment];
|
AudioFIRSegment *seg = &s->seg[segment];
|
||||||
float *src = (float *)seg->input->extended_data[ch];
|
float *src = (float *)seg->input->extended_data[ch];
|
||||||
float *dst = (float *)seg->output->extended_data[ch];
|
float *dst = (float *)seg->output->extended_data[ch];
|
||||||
float *sum = (float *)seg->sum->extended_data[ch];
|
float *sumin = (float *)seg->sumin->extended_data[ch];
|
||||||
|
float *sumout = (float *)seg->sumout->extended_data[ch];
|
||||||
|
|
||||||
if (s->min_part_size >= 8) {
|
if (s->min_part_size >= 8) {
|
||||||
s->fdsp->vector_fmul_scalar(src + seg->input_offset, in, s->dry_gain, FFALIGN(nb_samples, 4));
|
s->fdsp->vector_fmul_scalar(src + seg->input_offset, in, s->dry_gain, FFALIGN(nb_samples, 4));
|
||||||
@ -115,7 +116,7 @@ static int fir_quantum(AVFilterContext *ctx, AVFrame *out, int ch, int offset)
|
|||||||
|
|
||||||
for (i = 0; i < seg->nb_partitions; i++) {
|
for (i = 0; i < seg->nb_partitions; i++) {
|
||||||
const int coffset = j * seg->coeff_size;
|
const int coffset = j * seg->coeff_size;
|
||||||
const FFTComplex *coeff = (const FFTComplex *)seg->coeff->extended_data[ch * !s->one2many] + coffset;
|
const AVComplexFloat *coeff = (const AVComplexFloat *)seg->coeff->extended_data[ch * !s->one2many] + coffset;
|
||||||
|
|
||||||
direct(src, coeff, nb_samples, dst);
|
direct(src, coeff, nb_samples, dst);
|
||||||
|
|
||||||
@ -134,40 +135,38 @@ static int fir_quantum(AVFilterContext *ctx, AVFrame *out, int ch, int offset)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(sum, 0, sizeof(*sum) * seg->fft_length);
|
memset(sumin, 0, sizeof(*sumin) * seg->fft_length);
|
||||||
block = (float *)seg->block->extended_data[ch] + seg->part_index[ch] * seg->block_size;
|
blockin = (float *)seg->blockin->extended_data[ch] + seg->part_index[ch] * seg->block_size;
|
||||||
memset(block + seg->part_size, 0, sizeof(*block) * (seg->fft_length - seg->part_size));
|
blockout = (float *)seg->blockout->extended_data[ch] + seg->part_index[ch] * seg->block_size;
|
||||||
|
memset(blockin + seg->part_size, 0, sizeof(*blockin) * (seg->fft_length - seg->part_size));
|
||||||
|
|
||||||
memcpy(block, src, sizeof(*src) * seg->part_size);
|
memcpy(blockin, src, sizeof(*src) * seg->part_size);
|
||||||
|
|
||||||
av_rdft_calc(seg->rdft[ch], block);
|
seg->tx_fn(seg->tx[ch], blockout, blockin, sizeof(float));
|
||||||
block[2 * seg->part_size] = block[1];
|
|
||||||
block[1] = 0;
|
|
||||||
|
|
||||||
j = seg->part_index[ch];
|
j = seg->part_index[ch];
|
||||||
|
|
||||||
for (i = 0; i < seg->nb_partitions; i++) {
|
for (i = 0; i < seg->nb_partitions; i++) {
|
||||||
const int coffset = j * seg->coeff_size;
|
const int coffset = j * seg->coeff_size;
|
||||||
const float *block = (const float *)seg->block->extended_data[ch] + i * seg->block_size;
|
const float *blockout = (const float *)seg->blockout->extended_data[ch] + i * seg->block_size;
|
||||||
const FFTComplex *coeff = (const FFTComplex *)seg->coeff->extended_data[ch * !s->one2many] + coffset;
|
const AVComplexFloat *coeff = (const AVComplexFloat *)seg->coeff->extended_data[ch * !s->one2many] + coffset;
|
||||||
|
|
||||||
s->afirdsp.fcmul_add(sum, block, (const float *)coeff, seg->part_size);
|
s->afirdsp.fcmul_add(sumin, blockout, (const float *)coeff, seg->part_size);
|
||||||
|
|
||||||
if (j == 0)
|
if (j == 0)
|
||||||
j = seg->nb_partitions;
|
j = seg->nb_partitions;
|
||||||
j--;
|
j--;
|
||||||
}
|
}
|
||||||
|
|
||||||
sum[1] = sum[2 * seg->part_size];
|
seg->itx_fn(seg->itx[ch], sumout, sumin, sizeof(float));
|
||||||
av_rdft_calc(seg->irdft[ch], sum);
|
|
||||||
|
|
||||||
buf = (float *)seg->buffer->extended_data[ch];
|
buf = (float *)seg->buffer->extended_data[ch];
|
||||||
fir_fadd(s, buf, sum, seg->part_size);
|
fir_fadd(s, buf, sumout, seg->part_size);
|
||||||
|
|
||||||
memcpy(dst, buf, seg->part_size * sizeof(*dst));
|
memcpy(dst, buf, seg->part_size * sizeof(*dst));
|
||||||
|
|
||||||
buf = (float *)seg->buffer->extended_data[ch];
|
buf = (float *)seg->buffer->extended_data[ch];
|
||||||
memcpy(buf, sum + seg->part_size, seg->part_size * sizeof(*buf));
|
memcpy(buf, sumout + seg->part_size, seg->part_size * sizeof(*buf));
|
||||||
|
|
||||||
seg->part_index[ch] = (seg->part_index[ch] + 1) % seg->nb_partitions;
|
seg->part_index[ch] = (seg->part_index[ch] + 1) % seg->nb_partitions;
|
||||||
|
|
||||||
@ -381,9 +380,9 @@ static int init_segment(AVFilterContext *ctx, AudioFIRSegment *seg,
|
|||||||
{
|
{
|
||||||
AudioFIRContext *s = ctx->priv;
|
AudioFIRContext *s = ctx->priv;
|
||||||
|
|
||||||
seg->rdft = av_calloc(ctx->inputs[0]->channels, sizeof(*seg->rdft));
|
seg->tx = av_calloc(ctx->inputs[0]->channels, sizeof(*seg->tx));
|
||||||
seg->irdft = av_calloc(ctx->inputs[0]->channels, sizeof(*seg->irdft));
|
seg->itx = av_calloc(ctx->inputs[0]->channels, sizeof(*seg->itx));
|
||||||
if (!seg->rdft || !seg->irdft)
|
if (!seg->tx || !seg->itx)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
seg->fft_length = part_size * 2 + 1;
|
seg->fft_length = part_size * 2 + 1;
|
||||||
@ -400,19 +399,22 @@ static int init_segment(AVFilterContext *ctx, AudioFIRSegment *seg,
|
|||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
for (int ch = 0; ch < ctx->inputs[0]->channels && part_size >= 8; ch++) {
|
for (int ch = 0; ch < ctx->inputs[0]->channels && part_size >= 8; ch++) {
|
||||||
seg->rdft[ch] = av_rdft_init(av_log2(2 * part_size), DFT_R2C);
|
float scale = 1.f, iscale = 1.f / part_size;
|
||||||
seg->irdft[ch] = av_rdft_init(av_log2(2 * part_size), IDFT_C2R);
|
av_tx_init(&seg->tx[ch], &seg->tx_fn, AV_TX_FLOAT_RDFT, 0, 2 * part_size, &scale, 0);
|
||||||
if (!seg->rdft[ch] || !seg->irdft[ch])
|
av_tx_init(&seg->itx[ch], &seg->itx_fn, AV_TX_FLOAT_RDFT, 1, 2 * part_size, &iscale, 0);
|
||||||
|
if (!seg->tx[ch] || !seg->itx[ch])
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
seg->sum = ff_get_audio_buffer(ctx->inputs[0], seg->fft_length);
|
seg->sumin = ff_get_audio_buffer(ctx->inputs[0], seg->fft_length);
|
||||||
seg->block = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->block_size);
|
seg->sumout = ff_get_audio_buffer(ctx->inputs[0], seg->fft_length);
|
||||||
|
seg->blockin = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->block_size);
|
||||||
|
seg->blockout = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->block_size);
|
||||||
seg->buffer = ff_get_audio_buffer(ctx->inputs[0], seg->part_size);
|
seg->buffer = ff_get_audio_buffer(ctx->inputs[0], seg->part_size);
|
||||||
seg->coeff = ff_get_audio_buffer(ctx->inputs[1 + s->selir], seg->nb_partitions * seg->coeff_size * 2);
|
seg->coeff = ff_get_audio_buffer(ctx->inputs[1 + s->selir], seg->nb_partitions * seg->coeff_size * 2);
|
||||||
seg->input = ff_get_audio_buffer(ctx->inputs[0], seg->input_size);
|
seg->input = ff_get_audio_buffer(ctx->inputs[0], seg->input_size);
|
||||||
seg->output = ff_get_audio_buffer(ctx->inputs[0], seg->part_size);
|
seg->output = ff_get_audio_buffer(ctx->inputs[0], seg->part_size);
|
||||||
if (!seg->buffer || !seg->sum || !seg->block || !seg->coeff || !seg->input || !seg->output)
|
if (!seg->buffer || !seg->sumin || !seg->sumout || !seg->blockin || !seg->blockout || !seg->coeff || !seg->input || !seg->output)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -422,25 +424,27 @@ static void uninit_segment(AVFilterContext *ctx, AudioFIRSegment *seg)
|
|||||||
{
|
{
|
||||||
AudioFIRContext *s = ctx->priv;
|
AudioFIRContext *s = ctx->priv;
|
||||||
|
|
||||||
if (seg->rdft) {
|
if (seg->tx) {
|
||||||
for (int ch = 0; ch < s->nb_channels; ch++) {
|
for (int ch = 0; ch < s->nb_channels; ch++) {
|
||||||
av_rdft_end(seg->rdft[ch]);
|
av_tx_uninit(&seg->tx[ch]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
av_freep(&seg->rdft);
|
av_freep(&seg->tx);
|
||||||
|
|
||||||
if (seg->irdft) {
|
if (seg->itx) {
|
||||||
for (int ch = 0; ch < s->nb_channels; ch++) {
|
for (int ch = 0; ch < s->nb_channels; ch++) {
|
||||||
av_rdft_end(seg->irdft[ch]);
|
av_tx_uninit(&seg->itx[ch]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
av_freep(&seg->irdft);
|
av_freep(&seg->itx);
|
||||||
|
|
||||||
av_freep(&seg->output_offset);
|
av_freep(&seg->output_offset);
|
||||||
av_freep(&seg->part_index);
|
av_freep(&seg->part_index);
|
||||||
|
|
||||||
av_frame_free(&seg->block);
|
av_frame_free(&seg->blockin);
|
||||||
av_frame_free(&seg->sum);
|
av_frame_free(&seg->blockout);
|
||||||
|
av_frame_free(&seg->sumin);
|
||||||
|
av_frame_free(&seg->sumout);
|
||||||
av_frame_free(&seg->buffer);
|
av_frame_free(&seg->buffer);
|
||||||
av_frame_free(&seg->coeff);
|
av_frame_free(&seg->coeff);
|
||||||
av_frame_free(&seg->input);
|
av_frame_free(&seg->input);
|
||||||
@ -558,13 +562,13 @@ static int convert_coeffs(AVFilterContext *ctx)
|
|||||||
|
|
||||||
for (int segment = 0; segment < s->nb_segments; segment++) {
|
for (int segment = 0; segment < s->nb_segments; segment++) {
|
||||||
AudioFIRSegment *seg = &s->seg[segment];
|
AudioFIRSegment *seg = &s->seg[segment];
|
||||||
float *block = (float *)seg->block->extended_data[ch];
|
float *blockin = (float *)seg->blockin->extended_data[ch];
|
||||||
FFTComplex *coeff = (FFTComplex *)seg->coeff->extended_data[ch];
|
float *blockout = (float *)seg->blockout->extended_data[ch];
|
||||||
|
AVComplexFloat *coeff = (AVComplexFloat *)seg->coeff->extended_data[ch];
|
||||||
|
|
||||||
av_log(ctx, AV_LOG_DEBUG, "segment: %d\n", segment);
|
av_log(ctx, AV_LOG_DEBUG, "segment: %d\n", segment);
|
||||||
|
|
||||||
for (i = 0; i < seg->nb_partitions; i++) {
|
for (i = 0; i < seg->nb_partitions; i++) {
|
||||||
const float scale = 1.f / seg->part_size;
|
|
||||||
const int coffset = i * seg->coeff_size;
|
const int coffset = i * seg->coeff_size;
|
||||||
const int remaining = s->nb_taps - toffset;
|
const int remaining = s->nb_taps - toffset;
|
||||||
const int size = remaining >= seg->part_size ? seg->part_size : remaining;
|
const int size = remaining >= seg->part_size ? seg->part_size : remaining;
|
||||||
@ -577,19 +581,15 @@ static int convert_coeffs(AVFilterContext *ctx)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(block, 0, sizeof(*block) * seg->fft_length);
|
memset(blockin, 0, sizeof(*blockin) * seg->fft_length);
|
||||||
memcpy(block, time + toffset, size * sizeof(*block));
|
memcpy(blockin, time + toffset, size * sizeof(*blockin));
|
||||||
|
|
||||||
av_rdft_calc(seg->rdft[0], block);
|
seg->tx_fn(seg->tx[0], blockout, blockin, sizeof(float));
|
||||||
|
|
||||||
coeff[coffset].re = block[0] * scale;
|
for (n = 0; n < seg->part_size + 1; n++) {
|
||||||
coeff[coffset].im = 0;
|
coeff[coffset + n].re = blockout[2 * n];
|
||||||
for (n = 1; n < seg->part_size; n++) {
|
coeff[coffset + n].im = blockout[2 * n + 1];
|
||||||
coeff[coffset + n].re = block[2 * n] * scale;
|
|
||||||
coeff[coffset + n].im = block[2 * n + 1] * scale;
|
|
||||||
}
|
}
|
||||||
coeff[coffset + seg->part_size].re = block[1] * scale;
|
|
||||||
coeff[coffset + seg->part_size].im = 0;
|
|
||||||
|
|
||||||
toffset += size;
|
toffset += size;
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,10 @@
|
|||||||
#ifndef AVFILTER_AFIR_H
|
#ifndef AVFILTER_AFIR_H
|
||||||
#define AVFILTER_AFIR_H
|
#define AVFILTER_AFIR_H
|
||||||
|
|
||||||
|
#include "libavutil/tx.h"
|
||||||
#include "libavutil/common.h"
|
#include "libavutil/common.h"
|
||||||
#include "libavutil/float_dsp.h"
|
#include "libavutil/float_dsp.h"
|
||||||
#include "libavutil/opt.h"
|
#include "libavutil/opt.h"
|
||||||
#include "libavcodec/avfft.h"
|
|
||||||
|
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "avfilter.h"
|
#include "avfilter.h"
|
||||||
@ -43,14 +43,17 @@ typedef struct AudioFIRSegment {
|
|||||||
int *output_offset;
|
int *output_offset;
|
||||||
int *part_index;
|
int *part_index;
|
||||||
|
|
||||||
AVFrame *sum;
|
AVFrame *sumin;
|
||||||
AVFrame *block;
|
AVFrame *sumout;
|
||||||
|
AVFrame *blockin;
|
||||||
|
AVFrame *blockout;
|
||||||
AVFrame *buffer;
|
AVFrame *buffer;
|
||||||
AVFrame *coeff;
|
AVFrame *coeff;
|
||||||
AVFrame *input;
|
AVFrame *input;
|
||||||
AVFrame *output;
|
AVFrame *output;
|
||||||
|
|
||||||
RDFTContext **rdft, **irdft;
|
AVTXContext **tx, **itx;
|
||||||
|
av_tx_fn tx_fn, itx_fn;
|
||||||
} AudioFIRSegment;
|
} AudioFIRSegment;
|
||||||
|
|
||||||
typedef struct AudioFIRDSPContext {
|
typedef struct AudioFIRDSPContext {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user