History

avfilter/af_asoftclip: rewrite oversampling

Fixes most aliasing issues.

Paul B Mahol committed 5 years ago

Commit 94d4cc21 parent 3e127b52 files · +171 −135Browse files

Unified · Split

2 files
  1. configure +0 −1
  2. libavfilter/af_asoftclip.c +171 −134
configure+0−1
@@ -3548,7 +3548,6 @@ afir_filter_select="rdft" · 3547 unmodified lines
3548ametadata_filter_deps="avformat"3548ametadata_filter_deps="avformat"
3549amovie_filter_deps="avcodec avformat"3549amovie_filter_deps="avcodec avformat"
3550aresample_filter_deps="swresample"3550aresample_filter_deps="swresample"
3551asoftclip_filter_deps="swresample"
3552asr_filter_deps="pocketsphinx"3551asr_filter_deps="pocketsphinx"
3553ass_filter_deps="libass"3552ass_filter_deps="libass"
3554atempo_filter_deps="avcodec"3553atempo_filter_deps="avcodec"
libavfilter/af_asoftclip.c+171−134
@@ -21,11 +21,12 @@ · 20 unmodified lines
21#include "libavutil/avassert.h"21#include "libavutil/avassert.h"
22#include "libavutil/channel_layout.h"22#include "libavutil/channel_layout.h"
23#include "libavutil/opt.h"23#include "libavutil/opt.h"
24#include "libswresample/swresample.h"
25#include "avfilter.h"24#include "avfilter.h"
26#include "audio.h"25#include "audio.h"
27#include "formats.h"26#include "formats.h"
28 27
28#define MAX_OVERSAMPLE 64
29
29enum ASoftClipTypes {30enum ASoftClipTypes {
30 ASC_HARD = -1,31 ASC_HARD = -1,
31 ASC_TANH,32 ASC_TANH,
@@ -39,6 +40,14 @@ enum ASoftClipTypes { · 7 unmodified lines
39 NB_TYPES,40 NB_TYPES,
40};41};
41 42
43typedef struct Lowpass {
44 float fb0, fb1, fb2;
45 float fa0, fa1, fa2;
46
47 double db0, db1, db2;
48 double da0, da1, da2;
49} Lowpass;
50
42typedef struct ASoftClipContext {51typedef struct ASoftClipContext {
43 const AVClass *class;52 const AVClass *class;
44 53
@@ -49,10 +58,8 @@ typedef struct ASoftClipContext { · 4 unmodified lines
49 double output;58 double output;
50 double param;59 double param;
51 60
52 SwrContext *up_ctx;61 Lowpass lowpass[MAX_OVERSAMPLE];
53 SwrContext *down_ctx;62 AVFrame *frame[2];
54
55 AVFrame *frame;
56 63
57 void (*filter)(struct ASoftClipContext *s, void **dst, const void **src,64 void (*filter)(struct ASoftClipContext *s, void **dst, const void **src,
58 int nb_samples, int channels, int start, int end);65 int nb_samples, int channels, int start, int end);
@@ -60,7 +67,6 @@ typedef struct ASoftClipContext { · 1 unmodified line
60 67
61#define OFFSET(x) offsetof(ASoftClipContext, x)68#define OFFSET(x) offsetof(ASoftClipContext, x)
62#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM69#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
63#define F AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
64 70
65static const AVOption asoftclip_options[] = {71static const AVOption asoftclip_options[] = {
66 { "type", "set softclip type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, -1, NB_TYPES-1, A, "types" },72 { "type", "set softclip type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, -1, NB_TYPES-1, A, "types" },
@@ -76,7 +82,7 @@ static const AVOption asoftclip_options[] = { · 9 unmodified lines
76 { "threshold", "set softclip threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.000001, 1, A },82 { "threshold", "set softclip threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.000001, 1, A },
77 { "output", "set softclip output gain", OFFSET(output), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.000001, 16, A },83 { "output", "set softclip output gain", OFFSET(output), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.000001, 16, A },
78 { "param", "set softclip parameter", OFFSET(param), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.01, 3, A },84 { "param", "set softclip parameter", OFFSET(param), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.01, 3, A },
79 { "oversample", "set oversample factor", OFFSET(oversample), AV_OPT_TYPE_INT, {.i64=1}, 1, 32, F },85 { "oversample", "set oversample factor", OFFSET(oversample), AV_OPT_TYPE_INT, {.i64=1}, 1, MAX_OVERSAMPLE, A },
80 { NULL }86 { NULL }
81};87};
82 88
@@ -85,8 +91,7 @@ AVFILTER_DEFINE_CLASS(asoftclip); · 2 unmodified lines
85static int query_formats(AVFilterContext *ctx)91static int query_formats(AVFilterContext *ctx)
86{92{
87 static const enum AVSampleFormat sample_fmts[] = {93 static const enum AVSampleFormat sample_fmts[] = {
88 AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,94 AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP,
89 AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
90 AV_SAMPLE_FMT_NONE95 AV_SAMPLE_FMT_NONE
91 };96 };
92 int ret = ff_set_common_formats_from_list(ctx, sample_fmts);97 int ret = ff_set_common_formats_from_list(ctx, sample_fmts);
@@ -100,42 +105,103 @@ static int query_formats(AVFilterContext *ctx) · 7 unmodified lines
100 return ff_set_common_all_samplerates(ctx);105 return ff_set_common_all_samplerates(ctx);
101}106}
102 107
108static void get_lowpass(Lowpass *s,
109 double frequency,
110 double sample_rate)
111{
112 double w0 = 2 * M_PI * frequency / sample_rate;
113 double alpha = sin(w0) / (2 * 0.8);
114 double factor;
115
116 s->da0 = 1 + alpha;
117 s->da1 = -2 * cos(w0);
118 s->da2 = 1 - alpha;
119 s->db0 = (1 - cos(w0)) / 2;
120 s->db1 = 1 - cos(w0);
121 s->db2 = (1 - cos(w0)) / 2;
122
123 s->da1 /= s->da0;
124 s->da2 /= s->da0;
125 s->db0 /= s->da0;
126 s->db1 /= s->da0;
127 s->db2 /= s->da0;
128 s->da0 /= s->da0;
129
130 factor = (s->da0 + s->da1 + s->da2) / (s->db0 + s->db1 + s->db2);
131 s->db0 *= factor;
132 s->db1 *= factor;
133 s->db2 *= factor;
134
135 s->fa0 = s->da0;
136 s->fa1 = s->da1;
137 s->fa2 = s->da2;
138 s->fb0 = s->db0;
139 s->fb1 = s->db1;
140 s->fb2 = s->db2;
141}
142
143static inline float run_lowpassf(const Lowpass *const s,
144 float src, float *w)
145{
146 float dst;
147
148 dst = src * s->fb0 + w[0];
149 w[0] = s->fb1 * src + w[1] - s->fa1 * dst;
150 w[1] = s->fb2 * src - s->fa2 * dst;
151
152 return dst;
153}
154
103static void filter_flt(ASoftClipContext *s,155static void filter_flt(ASoftClipContext *s,
104 void **dptr, const void **sptr,156 void **dptr, const void **sptr,
105 int nb_samples, int channels,157 int nb_samples, int channels,
106 int start, int end)158 int start, int end)
107{159{
160 const int oversample = s->oversample;
161 const int nb_osamples = nb_samples * oversample;
162 const float scale = oversample > 1 ? oversample * 0.5f : 1.f;
108 float threshold = s->threshold;163 float threshold = s->threshold;
109 float gain = s->output * threshold;164 float gain = s->output * threshold;
110 float factor = 1.f / threshold;165 float factor = 1.f / threshold;
111 float param = s->param;166 float param = s->param;
112 167
113 for (int c = start; c < end; c++) {168 for (int c = start; c < end; c++) {
169 float *w = (float *)(s->frame[0]->extended_data[c]) + 2 * (oversample - 1);
114 const float *src = sptr[c];170 const float *src = sptr[c];
115 float *dst = dptr[c];171 float *dst = dptr[c];
116 172
173 for (int n = 0; n < nb_samples; n++) {
174 dst[oversample * n] = src[n];
175
176 for (int m = 1; m < oversample; m++)
177 dst[oversample * n + m] = 0.f;
178 }
179
180 for (int n = 0; n < nb_osamples && oversample > 1; n++)
181 dst[n] = run_lowpassf(&s->lowpass[oversample - 1], dst[n], w);
182
117 switch (s->type) {183 switch (s->type) {
118 case ASC_HARD:184 case ASC_HARD:
119 for (int n = 0; n < nb_samples; n++) {185 for (int n = 0; n < nb_osamples; n++) {
120 dst[n] = av_clipf(src[n] * factor, -1.f, 1.f);186 dst[n] = av_clipf(dst[n] * factor, -1.f, 1.f);
121 dst[n] *= gain;187 dst[n] *= gain;
122 }188 }
123 break;189 break;
124 case ASC_TANH:190 case ASC_TANH:
125 for (int n = 0; n < nb_samples; n++) {191 for (int n = 0; n < nb_osamples; n++) {
126 dst[n] = tanhf(src[n] * factor * param);192 dst[n] = tanhf(dst[n] * factor * param);
127 dst[n] *= gain;193 dst[n] *= gain;
128 }194 }
129 break;195 break;
130 case ASC_ATAN:196 case ASC_ATAN:
131 for (int n = 0; n < nb_samples; n++) {197 for (int n = 0; n < nb_osamples; n++) {
132 dst[n] = 2.f / M_PI * atanf(src[n] * factor * param);198 dst[n] = 2.f / M_PI * atanf(dst[n] * factor * param);
133 dst[n] *= gain;199 dst[n] *= gain;
134 }200 }
135 break;201 break;
136 case ASC_CUBIC:202 case ASC_CUBIC:
137 for (int n = 0; n < nb_samples; n++) {203 for (int n = 0; n < nb_osamples; n++) {
138 float sample = src[n] * factor;204 float sample = dst[n] * factor;
139 205
140 if (FFABS(sample) >= 1.5f)206 if (FFABS(sample) >= 1.5f)
141 dst[n] = FFSIGN(sample);207 dst[n] = FFSIGN(sample);
@@ -145,22 +211,22 @@ static void filter_flt(ASoftClipContext *s, · 3 unmodified lines
145 }211 }
146 break;212 break;
147 case ASC_EXP:213 case ASC_EXP:
148 for (int n = 0; n < nb_samples; n++) {214 for (int n = 0; n < nb_osamples; n++) {
149 dst[n] = 2.f / (1.f + expf(-2.f * src[n] * factor)) - 1.;215 dst[n] = 2.f / (1.f + expf(-2.f * dst[n] * factor)) - 1.;
150 dst[n] *= gain;216 dst[n] *= gain;
151 }217 }
152 break;218 break;
153 case ASC_ALG:219 case ASC_ALG:
154 for (int n = 0; n < nb_samples; n++) {220 for (int n = 0; n < nb_osamples; n++) {
155 float sample = src[n] * factor;221 float sample = dst[n] * factor;
156 222
157 dst[n] = sample / (sqrtf(param + sample * sample));223 dst[n] = sample / (sqrtf(param + sample * sample));
158 dst[n] *= gain;224 dst[n] *= gain;
159 }225 }
160 break;226 break;
161 case ASC_QUINTIC:227 case ASC_QUINTIC:
162 for (int n = 0; n < nb_samples; n++) {228 for (int n = 0; n < nb_osamples; n++) {
163 float sample = src[n] * factor;229 float sample = dst[n] * factor;
164 230
165 if (FFABS(sample) >= 1.25)231 if (FFABS(sample) >= 1.25)
166 dst[n] = FFSIGN(sample);232 dst[n] = FFSIGN(sample);
@@ -170,8 +236,8 @@ static void filter_flt(ASoftClipContext *s, · 3 unmodified lines
170 }236 }
171 break;237 break;
172 case ASC_SIN:238 case ASC_SIN:
173 for (int n = 0; n < nb_samples; n++) {239 for (int n = 0; n < nb_osamples; n++) {
174 float sample = src[n] * factor;240 float sample = dst[n] * factor;
175 241
176 if (FFABS(sample) >= M_PI_2)242 if (FFABS(sample) >= M_PI_2)
177 dst[n] = FFSIGN(sample);243 dst[n] = FFSIGN(sample);
@@ -181,53 +247,86 @@ static void filter_flt(ASoftClipContext *s, · 3 unmodified lines
181 }247 }
182 break;248 break;
183 case ASC_ERF:249 case ASC_ERF:
184 for (int n = 0; n < nb_samples; n++) {250 for (int n = 0; n < nb_osamples; n++) {
185 dst[n] = erff(src[n] * factor);251 dst[n] = erff(dst[n] * factor);
186 dst[n] *= gain;252 dst[n] *= gain;
187 }253 }
188 break;254 break;
189 default:255 default:
190 av_assert0(0);256 av_assert0(0);
191 }257 }
258
259 w = (float *)(s->frame[1]->extended_data[c]) + 2 * (oversample - 1);
260 for (int n = 0; n < nb_osamples && oversample > 1; n++)
261 dst[n] = run_lowpassf(&s->lowpass[oversample - 1], dst[n], w);
262
263 for (int n = 0; n < nb_samples; n++)
264 dst[n] = dst[n * oversample] * scale;
192 }265 }
193}266}
194 267
268static inline double run_lowpassd(const Lowpass *const s,
269 double src, double *w)
270{
271 double dst;
272
273 dst = src * s->db0 + w[0];
274 w[0] = s->db1 * src + w[1] - s->da1 * dst;
275 w[1] = s->db2 * src - s->da2 * dst;
276
277 return dst;
278}
279
195static void filter_dbl(ASoftClipContext *s,280static void filter_dbl(ASoftClipContext *s,
196 void **dptr, const void **sptr,281 void **dptr, const void **sptr,
197 int nb_samples, int channels,282 int nb_samples, int channels,
198 int start, int end)283 int start, int end)
199{284{
285 const int oversample = s->oversample;
286 const int nb_osamples = nb_samples * oversample;
287 const double scale = oversample > 1 ? oversample * 0.5 : 1.;
200 double threshold = s->threshold;288 double threshold = s->threshold;
201 double gain = s->output * threshold;289 double gain = s->output * threshold;
202 double factor = 1. / threshold;290 double factor = 1. / threshold;
203 double param = s->param;291 double param = s->param;
204 292
205 for (int c = start; c < end; c++) {293 for (int c = start; c < end; c++) {
294 double *w = (double *)(s->frame[0]->extended_data[c]) + 2 * (oversample - 1);
206 const double *src = sptr[c];295 const double *src = sptr[c];
207 double *dst = dptr[c];296 double *dst = dptr[c];
208 297
298 for (int n = 0; n < nb_samples; n++) {
299 dst[oversample * n] = src[n];
300
301 for (int m = 1; m < oversample; m++)
302 dst[oversample * n + m] = 0.f;
303 }
304
305 for (int n = 0; n < nb_osamples && oversample > 1; n++)
306 dst[n] = run_lowpassd(&s->lowpass[oversample - 1], dst[n], w);
307
209 switch (s->type) {308 switch (s->type) {
210 case ASC_HARD:309 case ASC_HARD:
211 for (int n = 0; n < nb_samples; n++) {310 for (int n = 0; n < nb_osamples; n++) {
212 dst[n] = av_clipd(src[n] * factor, -1., 1.);311 dst[n] = av_clipd(dst[n] * factor, -1., 1.);
213 dst[n] *= gain;312 dst[n] *= gain;
214 }313 }
215 break;314 break;
216 case ASC_TANH:315 case ASC_TANH:
217 for (int n = 0; n < nb_samples; n++) {316 for (int n = 0; n < nb_osamples; n++) {
218 dst[n] = tanh(src[n] * factor * param);317 dst[n] = tanh(dst[n] * factor * param);
219 dst[n] *= gain;318 dst[n] *= gain;
220 }319 }
221 break;320 break;
222 case ASC_ATAN:321 case ASC_ATAN:
223 for (int n = 0; n < nb_samples; n++) {322 for (int n = 0; n < nb_osamples; n++) {
224 dst[n] = 2. / M_PI * atan(src[n] * factor * param);323 dst[n] = 2. / M_PI * atan(dst[n] * factor * param);
225 dst[n] *= gain;324 dst[n] *= gain;
226 }325 }
227 break;326 break;
228 case ASC_CUBIC:327 case ASC_CUBIC:
229 for (int n = 0; n < nb_samples; n++) {328 for (int n = 0; n < nb_osamples; n++) {
230 double sample = src[n] * factor;329 double sample = dst[n] * factor;
231 330
232 if (FFABS(sample) >= 1.5)331 if (FFABS(sample) >= 1.5)
233 dst[n] = FFSIGN(sample);332 dst[n] = FFSIGN(sample);
@@ -237,22 +336,22 @@ static void filter_dbl(ASoftClipContext *s, · 3 unmodified lines
237 }336 }
238 break;337 break;
239 case ASC_EXP:338 case ASC_EXP:
240 for (int n = 0; n < nb_samples; n++) {339 for (int n = 0; n < nb_osamples; n++) {
241 dst[n] = 2. / (1. + exp(-2. * src[n] * factor)) - 1.;340 dst[n] = 2. / (1. + exp(-2. * dst[n] * factor)) - 1.;
242 dst[n] *= gain;341 dst[n] *= gain;
243 }342 }
244 break;343 break;
245 case ASC_ALG:344 case ASC_ALG:
246 for (int n = 0; n < nb_samples; n++) {345 for (int n = 0; n < nb_osamples; n++) {
247 double sample = src[n] * factor;346 double sample = dst[n] * factor;
248 347
249 dst[n] = sample / (sqrt(param + sample * sample));348 dst[n] = sample / (sqrt(param + sample * sample));
250 dst[n] *= gain;349 dst[n] *= gain;
251 }350 }
252 break;351 break;
253 case ASC_QUINTIC:352 case ASC_QUINTIC:
254 for (int n = 0; n < nb_samples; n++) {353 for (int n = 0; n < nb_osamples; n++) {
255 double sample = src[n] * factor;354 double sample = dst[n] * factor;
256 355
257 if (FFABS(sample) >= 1.25)356 if (FFABS(sample) >= 1.25)
258 dst[n] = FFSIGN(sample);357 dst[n] = FFSIGN(sample);
@@ -262,8 +361,8 @@ static void filter_dbl(ASoftClipContext *s, · 3 unmodified lines
262 }361 }
263 break;362 break;
264 case ASC_SIN:363 case ASC_SIN:
265 for (int n = 0; n < nb_samples; n++) {364 for (int n = 0; n < nb_osamples; n++) {
266 double sample = src[n] * factor;365 double sample = dst[n] * factor;
267 366
268 if (FFABS(sample) >= M_PI_2)367 if (FFABS(sample) >= M_PI_2)
269 dst[n] = FFSIGN(sample);368 dst[n] = FFSIGN(sample);
@@ -273,14 +372,21 @@ static void filter_dbl(ASoftClipContext *s, · 3 unmodified lines
273 }372 }
274 break;373 break;
275 case ASC_ERF:374 case ASC_ERF:
276 for (int n = 0; n < nb_samples; n++) {375 for (int n = 0; n < nb_osamples; n++) {
277 dst[n] = erf(src[n] * factor);376 dst[n] = erf(dst[n] * factor);
278 dst[n] *= gain;377 dst[n] *= gain;
279 }378 }
280 break;379 break;
281 default:380 default:
282 av_assert0(0);381 av_assert0(0);
283 }382 }
383
384 w = (double *)(s->frame[1]->extended_data[c]) + 2 * (oversample - 1);
385 for (int n = 0; n < nb_osamples && oversample > 1; n++)
386 dst[n] = run_lowpassd(&s->lowpass[oversample - 1], dst[n], w);
387
388 for (int n = 0; n < nb_samples; n++)
389 dst[n] = dst[n * oversample] * scale;
284 }390 }
285}391}
286 392
@@ -288,47 +394,21 @@ static int config_input(AVFilterLink *inlink) · 1 unmodified line
288{394{
289 AVFilterContext *ctx = inlink->dst;395 AVFilterContext *ctx = inlink->dst;
290 ASoftClipContext *s = ctx->priv;396 ASoftClipContext *s = ctx->priv;
291 int ret;
292 397
293 switch (inlink->format) {398 switch (inlink->format) {
294 case AV_SAMPLE_FMT_FLT:
295 case AV_SAMPLE_FMT_FLTP: s->filter = filter_flt; break;399 case AV_SAMPLE_FMT_FLTP: s->filter = filter_flt; break;
296 case AV_SAMPLE_FMT_DBL:
297 case AV_SAMPLE_FMT_DBLP: s->filter = filter_dbl; break;400 case AV_SAMPLE_FMT_DBLP: s->filter = filter_dbl; break;
298 default: av_assert0(0);401 default: av_assert0(0);
299 }402 }
300 403
301 if (s->oversample <= 1)404 s->frame[0] = ff_get_audio_buffer(inlink, 2 * MAX_OVERSAMPLE);
302 return 0;405 s->frame[1] = ff_get_audio_buffer(inlink, 2 * MAX_OVERSAMPLE);
303 406 if (!s->frame[0] || !s->frame[1])
304 s->up_ctx = swr_alloc();
305 s->down_ctx = swr_alloc();
306 if (!s->up_ctx || !s->down_ctx)
307 return AVERROR(ENOMEM);407 return AVERROR(ENOMEM);
308 408
309 av_opt_set_int(s->up_ctx, "in_channel_layout", inlink->channel_layout, 0);409 for (int i = 0; i < MAX_OVERSAMPLE; i++) {
310 av_opt_set_int(s->up_ctx, "in_sample_rate", inlink->sample_rate, 0);410 get_lowpass(&s->lowpass[i], inlink->sample_rate / 2, inlink->sample_rate * (i + 1));
311 av_opt_set_sample_fmt(s->up_ctx, "in_sample_fmt", inlink->format, 0);411 }
312
313 av_opt_set_int(s->up_ctx, "out_channel_layout", inlink->channel_layout, 0);
314 av_opt_set_int(s->up_ctx, "out_sample_rate", inlink->sample_rate * s->oversample, 0);
315 av_opt_set_sample_fmt(s->up_ctx, "out_sample_fmt", inlink->format, 0);
316
317 av_opt_set_int(s->down_ctx, "in_channel_layout", inlink->channel_layout, 0);
318 av_opt_set_int(s->down_ctx, "in_sample_rate", inlink->sample_rate * s->oversample, 0);
319 av_opt_set_sample_fmt(s->down_ctx, "in_sample_fmt", inlink->format, 0);
320
321 av_opt_set_int(s->down_ctx, "out_channel_layout", inlink->channel_layout, 0);
322 av_opt_set_int(s->down_ctx, "out_sample_rate", inlink->sample_rate, 0);
323 av_opt_set_sample_fmt(s->down_ctx, "out_sample_fmt", inlink->format, 0);
324
325 ret = swr_init(s->up_ctx);
326 if (ret < 0)
327 return ret;
328
329 ret = swr_init(s->down_ctx);
330 if (ret < 0)
331 return ret;
332 412
333 return 0;413 return 0;
334}414}
@@ -361,14 +441,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 26 unmodified lines
361 AVFilterContext *ctx = inlink->dst;441 AVFilterContext *ctx = inlink->dst;
362 ASoftClipContext *s = ctx->priv;442 ASoftClipContext *s = ctx->priv;
363 AVFilterLink *outlink = ctx->outputs[0];443 AVFilterLink *outlink = ctx->outputs[0];
364 int ret, nb_samples, channels;444 int nb_samples, channels;
365 ThreadData td;445 ThreadData td;
366 AVFrame *out;446 AVFrame *out;
367 447
368 if (av_frame_is_writable(in)) {448 if (av_frame_is_writable(in) && s->oversample == 1) {
369 out = in;449 out = in;
370 } else {450 } else {
371 out = ff_get_audio_buffer(outlink, in->nb_samples);451 out = ff_get_audio_buffer(outlink, in->nb_samples * s->oversample);
372 if (!out) {452 if (!out) {
373 av_frame_free(&in);453 av_frame_free(&in);
374 return AVERROR(ENOMEM);454 return AVERROR(ENOMEM);
@@ -376,72 +456,29 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 1 unmodified line
376 av_frame_copy_props(out, in);456 av_frame_copy_props(out, in);
377 }457 }
378 458
379 if (av_sample_fmt_is_planar(in->format)) {459 nb_samples = in->nb_samples;
380 nb_samples = in->nb_samples;460 channels = in->channels;
381 channels = in->channels;
382 } else {
383 nb_samples = in->channels * in->nb_samples;
384 channels = 1;
385 }
386
387 if (s->oversample > 1) {
388 s->frame = ff_get_audio_buffer(outlink, in->nb_samples * s->oversample);
389 if (!s->frame) {
390 ret = AVERROR(ENOMEM);
391 goto fail;
392 }
393 461
394 ret = swr_convert(s->up_ctx, (uint8_t**)s->frame->extended_data, in->nb_samples * s->oversample,462 td.in = in;
395 (const uint8_t **)in->extended_data, in->nb_samples);463 td.out = out;
396 if (ret < 0)464 td.nb_samples = nb_samples;
397 goto fail;465 td.channels = channels;
398 466 ff_filter_execute(ctx, filter_channels, &td, NULL,
399 td.in = s->frame;467 FFMIN(channels, ff_filter_get_nb_threads(ctx)));
400 td.out = s->frame;
401 td.nb_samples = av_sample_fmt_is_planar(in->format) ? ret : ret * in->channels;
402 td.channels = channels;
403 ff_filter_execute(ctx, filter_channels, &td, NULL,
404 FFMIN(channels, ff_filter_get_nb_threads(ctx)));
405
406 ret = swr_convert(s->down_ctx, (uint8_t**)out->extended_data, out->nb_samples,
407 (const uint8_t **)s->frame->extended_data, ret);
408 if (ret < 0)
409 goto fail;
410
411 if (out->pts)
412 out->pts -= s->delay;
413 s->delay += in->nb_samples - ret;
414 out->nb_samples = ret;
415
416 av_frame_free(&s->frame);
417 } else {
418 td.in = in;
419 td.out = out;
420 td.nb_samples = nb_samples;
421 td.channels = channels;
422 ff_filter_execute(ctx, filter_channels, &td, NULL,
423 FFMIN(channels, ff_filter_get_nb_threads(ctx)));
424 }
425 468
426 if (out != in)469 if (out != in)
427 av_frame_free(&in);470 av_frame_free(&in);
428 471
472 out->nb_samples /= s->oversample;
429 return ff_filter_frame(outlink, out);473 return ff_filter_frame(outlink, out);
430fail:
431 if (out != in)
432 av_frame_free(&out);
433 av_frame_free(&in);
434 av_frame_free(&s->frame);
435
436 return ret;
437}474}
438 475
439static av_cold void uninit(AVFilterContext *ctx)476static av_cold void uninit(AVFilterContext *ctx)
440{477{
441 ASoftClipContext *s = ctx->priv;478 ASoftClipContext *s = ctx->priv;
442 479
443 swr_free(&s->up_ctx);480 av_frame_free(&s->frame[0]);
444 swr_free(&s->down_ctx);481 av_frame_free(&s->frame[1]);
445}482}
446 483
447static const AVFilterPad inputs[] = {484static const AVFilterPad inputs[] = {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t