]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/af_sofalizer.c
avcodec/v210dec: move DSP function setting into dedicated function
[ffmpeg] / libavfilter / af_sofalizer.c
index 02c0409043a4a7e99f44fc11867ff26f70a0932f..ccf3872e77b3f6447ed0a9cdb9aebe07fd8a7114 100644 (file)
@@ -35,6 +35,7 @@
 #include "libavutil/intmath.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "audio.h"
 
@@ -81,6 +82,7 @@ typedef struct SOFAlizerContext {
     int buffer_length;          /* is: longest IR plus max. delay in all SOFA files */
                                 /* then choose next power of 2 */
     int n_fft;                  /* number of samples in one FFT block */
+    int nb_samples;
 
                                 /* netCDF variables */
     int *delay[2];              /* broadband delay for each channel/IR to be convolved */
@@ -395,12 +397,12 @@ static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n
             /* current read position in ringbuffer: input sample write position
              * - delay for l-th ch. + diff. betw. IR length and buffer length
              * (mod buffer length) */
-            read = (wr - delay[l] - (n_samples - 1) + buffer_length) & modulo;
+            read = (wr - delay[l] - (ir_samples - 1) + buffer_length) & modulo;
 
-            if (read + n_samples < buffer_length) {
-                memmove(temp_src, bptr + read, n_samples * sizeof(*temp_src));
+            if (read + ir_samples < buffer_length) {
+                memmove(temp_src, bptr + read, ir_samples * sizeof(*temp_src));
             } else {
-                int len = FFMIN(n_samples - (read % n_samples), buffer_length - read);
+                int len = FFMIN(n_samples - (read % ir_samples), buffer_length - read);
 
                 memmove(temp_src, bptr + read, len * sizeof(*temp_src));
                 memmove(temp_src + len, bptr, (n_samples - len) * sizeof(*temp_src));
@@ -436,7 +438,7 @@ static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr,
     FFTComplex *hrtf = s->data_hrtf[jobnr]; /* get pointers to current HRTF data */
     int *n_clippings = &td->n_clippings[jobnr];
     float *ringbuffer = td->ringbuffer[jobnr];
-    const int n_samples = s->sofa.n_samples; /* length of one IR */
+    const int ir_samples = s->sofa.ir_samples; /* length of one IR */
     const int planar = in->format == AV_SAMPLE_FMT_FLTP;
     const int mult = 1 + !planar;
     float *dst = (float *)out->extended_data[jobnr * planar]; /* get pointer to audio output buffer */
@@ -462,7 +464,7 @@ static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr,
 
     /* find minimum between number of samples and output buffer length:
      * (important, if one IR is longer than the output buffer) */
-    n_read = FFMIN(s->sofa.n_samples, in->nb_samples);
+    n_read = FFMIN(ir_samples, in->nb_samples);
     for (j = 0; j < n_read; j++) {
         /* initialize output buf with saved signal from overflow buf */
         dst[mult * j]  = ringbuffer[wr];
@@ -543,7 +545,7 @@ static int sofalizer_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr,
         dst[mult * j] += fft_acc[j].re * fft_scale;
     }
 
-    for (j = 0; j < n_samples - 1; j++) { /* overflow length is IR length - 1 */
+    for (j = 0; j < ir_samples - 1; j++) { /* overflow length is IR length - 1 */
         /* write the rest of output signal to overflow buffer */
         int write_pos = (wr + j) & modulo;
 
@@ -588,7 +590,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 
     if (s->type == TIME_DOMAIN) {
         ctx->internal->execute(ctx, sofalizer_convolute, &td, NULL, 2);
-    } else {
+    } else if (s->type == FREQUENCY_DOMAIN) {
         ctx->internal->execute(ctx, sofalizer_fast_convolute, &td, NULL, 2);
     }
     emms_c();
@@ -603,6 +605,31 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     return ff_filter_frame(outlink, out);
 }
 
+static int activate(AVFilterContext *ctx)
+{
+    AVFilterLink *inlink = ctx->inputs[0];
+    AVFilterLink *outlink = ctx->outputs[0];
+    SOFAlizerContext *s = ctx->priv;
+    AVFrame *in;
+    int ret;
+
+    FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
+
+    if (s->nb_samples)
+        ret = ff_inlink_consume_samples(inlink, s->nb_samples, s->nb_samples, &in);
+    else
+        ret = ff_inlink_consume_frame(inlink, &in);
+    if (ret < 0)
+        return ret;
+    if (ret > 0)
+        return filter_frame(inlink, in);
+
+    FF_FILTER_FORWARD_STATUS(inlink, outlink);
+    FF_FILTER_FORWARD_WANTED(outlink, inlink);
+
+    return FFERROR_NOT_READY;
+}
+
 static int query_formats(AVFilterContext *ctx)
 {
     struct SOFAlizerContext *s = ctx->priv;
@@ -719,12 +746,20 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int
     n_samples = s->sofa.n_samples;
     ir_samples = s->sofa.ir_samples;
 
-    s->data_ir[0] = av_calloc(n_samples, sizeof(float) * s->n_conv);
-    s->data_ir[1] = av_calloc(n_samples, sizeof(float) * s->n_conv);
+    if (s->type == TIME_DOMAIN) {
+        s->data_ir[0] = av_calloc(n_samples, sizeof(float) * s->n_conv);
+        s->data_ir[1] = av_calloc(n_samples, sizeof(float) * s->n_conv);
+
+        if (!s->data_ir[0] || !s->data_ir[1]) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+    }
+
     s->delay[0] = av_calloc(s->n_conv, sizeof(int));
     s->delay[1] = av_calloc(s->n_conv, sizeof(int));
 
-    if (!s->data_ir[0] || !s->data_ir[1] || !s->delay[0] || !s->delay[1]) {
+    if (!s->delay[0] || !s->delay[1]) {
         ret = AVERROR(ENOMEM);
         goto fail;
     }
@@ -800,12 +835,12 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int
     if (s->type == FREQUENCY_DOMAIN) {
         av_fft_end(s->fft[0]);
         av_fft_end(s->fft[1]);
-        s->fft[0] = av_fft_init(log2(s->n_fft), 0);
-        s->fft[1] = av_fft_init(log2(s->n_fft), 0);
+        s->fft[0] = av_fft_init(av_log2(s->n_fft), 0);
+        s->fft[1] = av_fft_init(av_log2(s->n_fft), 0);
         av_fft_end(s->ifft[0]);
         av_fft_end(s->ifft[1]);
-        s->ifft[0] = av_fft_init(log2(s->n_fft), 1);
-        s->ifft[1] = av_fft_init(log2(s->n_fft), 1);
+        s->ifft[0] = av_fft_init(av_log2(s->n_fft), 1);
+        s->ifft[1] = av_fft_init(av_log2(s->n_fft), 1);
 
         if (!s->fft[0] || !s->fft[1] || !s->ifft[0] || !s->ifft[1]) {
             av_log(ctx, AV_LOG_ERROR, "Unable to create FFT contexts of size %d.\n", s->n_fft);
@@ -817,7 +852,7 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int
     if (s->type == TIME_DOMAIN) {
         s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
         s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels);
-    } else {
+    } else if (s->type == FREQUENCY_DOMAIN) {
         /* get temporary HRTF memory for L and R channel */
         data_hrtf_l = av_malloc_array(n_fft, sizeof(*data_hrtf_l) * n_conv);
         data_hrtf_r = av_malloc_array(n_fft, sizeof(*data_hrtf_r) * n_conv);
@@ -868,7 +903,7 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int
                 s->data_ir[0][offset + j] = lir[ir_samples - 1 - j] * gain_lin;
                 s->data_ir[1][offset + j] = rir[ir_samples - 1 - j] * gain_lin;
             }
-        } else {
+        } else if (s->type == FREQUENCY_DOMAIN) {
             memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l));
             memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r));
 
@@ -877,7 +912,7 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int
                 /* load non-reversed IRs of the specified source position
                  * sample-by-sample and apply gain,
                  * L channel is loaded to real part, R channel to imag part,
-                 * IRs ared shifted by L and R delay */
+                 * IRs are shifted by L and R delay */
                 fft_in_l[s->delay[0][i] + j].re = lir[j] * gain_lin;
                 fft_in_r[s->delay[1][i] + j].re = rir[j] * gain_lin;
             }
@@ -956,11 +991,8 @@ static int config_input(AVFilterLink *inlink)
     SOFAlizerContext *s = ctx->priv;
     int ret;
 
-    if (s->type == FREQUENCY_DOMAIN) {
-        inlink->partial_buf_size =
-        inlink->min_samples =
-        inlink->max_samples = s->framesize;
-    }
+    if (s->type == FREQUENCY_DOMAIN)
+        s->nb_samples = s->framesize;
 
     /* gain -3 dB per channel */
     s->gain_lfe = expf((s->gain - 3 * inlink->channels + s->lfe_gain) / 20 * M_LN10);
@@ -1039,7 +1071,6 @@ static const AVFilterPad inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
-        .filter_frame = filter_frame,
     },
     { NULL }
 };
@@ -1058,6 +1089,7 @@ AVFilter ff_af_sofalizer = {
     .priv_size     = sizeof(SOFAlizerContext),
     .priv_class    = &sofalizer_class,
     .init          = init,
+    .activate      = activate,
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,