| @@ -26,6 +26,7 @@ · 25 unmodified lines |
| 26 | #include "audio.h" | 26 | #include "audio.h" |
| 27 | #include "avfilter.h" | 27 | #include "avfilter.h" |
| 28 | #include "filters.h" | 28 | #include "filters.h" |
| | 29 | #include "formats.h" |
| 29 | #include "internal.h" | 30 | #include "internal.h" |
| 30 | | 31 | |
| 31 | enum OutModes { | 32 | enum OutModes { |
| @@ -45,6 +46,7 @@ typedef struct AudioNLMSContext { · 13 unmodified lines |
| 45 | float eps; | 46 | float eps; |
| 46 | float leakage; | 47 | float leakage; |
| 47 | int output_mode; | 48 | int output_mode; |
| | 49 | int precision; |
| 48 | | 50 | |
| 49 | int kernel_size; | 51 | int kernel_size; |
| 50 | AVFrame *offset; | 52 | AVFrame *offset; |
| @@ -56,6 +58,8 @@ typedef struct AudioNLMSContext { · 5 unmodified lines |
| 56 | | 58 | |
| 57 | int anlmf; | 59 | int anlmf; |
| 58 | | 60 | |
| | 61 | int (*filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); |
| | 62 | |
| 59 | AVFloatDSPContext *fdsp; | 63 | AVFloatDSPContext *fdsp; |
| 60 | } AudioNLMSContext; | 64 | } AudioNLMSContext; |
| 61 | | 65 | |
| @@ -74,93 +78,32 @@ static const AVOption anlms_options[] = { · 12 unmodified lines |
| 74 | { "o", "output", 0, AV_OPT_TYPE_CONST, {.i64=OUT_MODE}, 0, 0, AT, "mode" }, | 78 | { "o", "output", 0, AV_OPT_TYPE_CONST, {.i64=OUT_MODE}, 0, 0, AT, "mode" }, |
| 75 | { "n", "noise", 0, AV_OPT_TYPE_CONST, {.i64=NOISE_MODE}, 0, 0, AT, "mode" }, | 79 | { "n", "noise", 0, AV_OPT_TYPE_CONST, {.i64=NOISE_MODE}, 0, 0, AT, "mode" }, |
| 76 | { "e", "error", 0, AV_OPT_TYPE_CONST, {.i64=ERROR_MODE}, 0, 0, AT, "mode" }, | 80 | { "e", "error", 0, AV_OPT_TYPE_CONST, {.i64=ERROR_MODE}, 0, 0, AT, "mode" }, |
| | 81 | { "precision", "set processing precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, A, "precision" }, |
| | 82 | { "auto", "set auto processing precision", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, A, "precision" }, |
| | 83 | { "float", "set single-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, A, "precision" }, |
| | 84 | { "double","set double-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, A, "precision" }, |
| 77 | { NULL } | 85 | { NULL } |
| 78 | }; | 86 | }; |
| 79 | | 87 | |
| 80 | AVFILTER_DEFINE_CLASS_EXT(anlms, "anlm(f|s)", anlms_options); | 88 | AVFILTER_DEFINE_CLASS_EXT(anlms, "anlm(f|s)", anlms_options); |
| 81 | | 89 | |
| 82 | static float fir_sample(AudioNLMSContext *s, float sample, float *delay, | 90 | static int query_formats(AVFilterContext *ctx) |
| 83 | float *coeffs, float *tmp, int *offset) | | |
| 84 | { | 91 | { |
| 85 | const int order = s->order; | 92 | AudioNLMSContext *s = ctx->priv; |
| 86 | float output; | 93 | static const enum AVSampleFormat sample_fmts[3][3] = { |
| 87 | | 94 | { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }, |
| 88 | delay[*offset] = sample; | 95 | { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, |
| 89 | | 96 | { AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }, |
| 90 | memcpy(tmp, coeffs + order - *offset, order * sizeof(float)); | 97 | }; |
| 91 | | 98 | int ret; |
| 92 | output = s->fdsp->scalarproduct_float(delay, tmp, s->kernel_size); | | |
| 93 | | | |
| 94 | if (--(*offset) < 0) | | |
| 95 | *offset = order - 1; | | |
| 96 | | | |
| 97 | return output; | | |
| 98 | } | | |
| 99 | | | |
| 100 | static float process_sample(AudioNLMSContext *s, float input, float desired, | | |
| 101 | float *delay, float *coeffs, float *tmp, int *offsetp) | | |
| 102 | { | | |
| 103 | const int order = s->order; | | |
| 104 | const float leakage = s->leakage; | | |
| 105 | const float mu = s->mu; | | |
| 106 | const float a = 1.f - leakage; | | |
| 107 | float sum, output, e, norm, b; | | |
| 108 | int offset = *offsetp; | | |
| 109 | | | |
| 110 | delay[offset + order] = input; | | |
| 111 | | | |
| 112 | output = fir_sample(s, input, delay, coeffs, tmp, offsetp); | | |
| 113 | e = desired - output; | | |
| 114 | | | |
| 115 | sum = s->fdsp->scalarproduct_float(delay, delay, s->kernel_size); | | |
| 116 | | | |
| 117 | norm = s->eps + sum; | | |
| 118 | b = mu * e / norm; | | |
| 119 | if (s->anlmf) | | |
| 120 | b *= e * e; | | |
| 121 | | | |
| 122 | memcpy(tmp, delay + offset, order * sizeof(float)); | | |
| 123 | | | |
| 124 | s->fdsp->vector_fmul_scalar(coeffs, coeffs, a, s->kernel_size); | | |
| 125 | | 99 | |
| 126 | s->fdsp->vector_fmac_scalar(coeffs, tmp, b, s->kernel_size); | 100 | if ((ret = ff_set_common_all_channel_counts(ctx)) < 0) |
| | 101 | return ret; |
| 127 | | 102 | |
| 128 | memcpy(coeffs + order, coeffs, order * sizeof(float)); | 103 | if ((ret = ff_set_common_formats_from_list(ctx, sample_fmts[s->precision])) < 0) |
| | 104 | return ret; |
| 129 | | 105 | |
| 130 | switch (s->output_mode) { | 106 | return ff_set_common_all_samplerates(ctx); |
| 131 | case IN_MODE: output = input; break; | | |
| 132 | case DESIRED_MODE: output = desired; break; | | |
| 133 | case OUT_MODE: output = desired - output; break; | | |
| 134 | case NOISE_MODE: output = input - output; break; | | |
| 135 | case ERROR_MODE: break; | | |
| 136 | } | | |
| 137 | return output; | | |
| 138 | } | | |
| 139 | | | |
| 140 | static int process_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | | |
| 141 | { | | |
| 142 | AudioNLMSContext *s = ctx->priv; | | |
| 143 | AVFrame *out = arg; | | |
| 144 | const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs; | | |
| 145 | const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; | | |
| 146 | | | |
| 147 | for (int c = start; c < end; c++) { | | |
| 148 | const float *input = (const float *)s->frame[0]->extended_data[c]; | | |
| 149 | const float *desired = (const float *)s->frame[1]->extended_data[c]; | | |
| 150 | float *delay = (float *)s->delay->extended_data[c]; | | |
| 151 | float *coeffs = (float *)s->coeffs->extended_data[c]; | | |
| 152 | float *tmp = (float *)s->tmp->extended_data[c]; | | |
| 153 | int *offset = (int *)s->offset->extended_data[c]; | | |
| 154 | float *output = (float *)out->extended_data[c]; | | |
| 155 | | | |
| 156 | for (int n = 0; n < out->nb_samples; n++) { | | |
| 157 | output[n] = process_sample(s, input[n], desired[n], delay, coeffs, tmp, offset); | | |
| 158 | if (ctx->is_disabled) | | |
| 159 | output[n] = input[n]; | | |
| 160 | } | | |
| 161 | } | | |
| 162 | | | |
| 163 | return 0; | | |
| 164 | } | 107 | } |
| 165 | | 108 | |
| 166 | static int activate(AVFilterContext *ctx) | 109 | static int activate(AVFilterContext *ctx) |
| @@ -195,7 +138,7 @@ static int activate(AVFilterContext *ctx) · 28 unmodified lines |
| 195 | return AVERROR(ENOMEM); | 138 | return AVERROR(ENOMEM); |
| 196 | } | 139 | } |
| 197 | | 140 | |
| 198 | ff_filter_execute(ctx, process_channels, out, NULL, | 141 | ff_filter_execute(ctx, s->filter_channels, out, NULL, |
| 199 | FFMIN(ctx->outputs[0]->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); | 142 | FFMIN(ctx->outputs[0]->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); |
| 200 | | 143 | |
| 201 | out->pts = s->frame[0]->pts; | 144 | out->pts = s->frame[0]->pts; |
| @@ -228,6 +171,13 @@ static int activate(AVFilterContext *ctx) · 26 unmodified lines |
| 228 | return 0; | 171 | return 0; |
| 229 | } | 172 | } |
| 230 | | 173 | |
| | 174 | #define DEPTH 32 |
| | 175 | #include "anlms_template.c" |
| | 176 | |
| | 177 | #undef DEPTH |
| | 178 | #define DEPTH 64 |
| | 179 | #include "anlms_template.c" |
| | 180 | |
| 231 | static int config_output(AVFilterLink *outlink) | 181 | static int config_output(AVFilterLink *outlink) |
| 232 | { | 182 | { |
| 233 | AVFilterContext *ctx = outlink->src; | 183 | AVFilterContext *ctx = outlink->src; |
| @@ -247,6 +197,15 @@ static int config_output(AVFilterLink *outlink) · 13 unmodified lines |
| 247 | if (!s->delay || !s->coeffs || !s->offset || !s->tmp) | 197 | if (!s->delay || !s->coeffs || !s->offset || !s->tmp) |
| 248 | return AVERROR(ENOMEM); | 198 | return AVERROR(ENOMEM); |
| 249 | | 199 | |
| | 200 | switch (outlink->format) { |
| | 201 | case AV_SAMPLE_FMT_DBLP: |
| | 202 | s->filter_channels = filter_channels_double; |
| | 203 | break; |
| | 204 | case AV_SAMPLE_FMT_FLTP: |
| | 205 | s->filter_channels = filter_channels_float; |
| | 206 | break; |
| | 207 | } |
| | 208 | |
| 250 | return 0; | 209 | return 0; |
| 251 | } | 210 | } |
| 252 | | 211 | |
| @@ -317,7 +276,7 @@ const AVFilter ff_af_anlmf = { · 64 unmodified lines |
| 317 | .activate = activate, | 276 | .activate = activate, |
| 318 | FILTER_INPUTS(inputs), | 277 | FILTER_INPUTS(inputs), |
| 319 | FILTER_OUTPUTS(outputs), | 278 | FILTER_OUTPUTS(outputs), |
| 320 | FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_FLTP), | 279 | FILTER_QUERY_FUNC(query_formats), |
| 321 | .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | | 280 | .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | |
| 322 | AVFILTER_FLAG_SLICE_THREADS, | 281 | AVFILTER_FLAG_SLICE_THREADS, |
| 323 | .process_command = ff_filter_process_command, | 282 | .process_command = ff_filter_process_command, |