Fixes most aliasing issues.
Unified · Split
| @@ -3548,7 +3548,6 @@ afir_filter_select="rdft" · 3547 unmodified lines | |||
| 3548 | ametadata_filter_deps="avformat" | 3548 | ametadata_filter_deps="avformat" |
| 3549 | amovie_filter_deps="avcodec avformat" | 3549 | amovie_filter_deps="avcodec avformat" |
| 3550 | aresample_filter_deps="swresample" | 3550 | aresample_filter_deps="swresample" |
| 3551 | asoftclip_filter_deps="swresample" | ||
| 3552 | asr_filter_deps="pocketsphinx" | 3551 | asr_filter_deps="pocketsphinx" |
| 3553 | ass_filter_deps="libass" | 3552 | ass_filter_deps="libass" |
| 3554 | atempo_filter_deps="avcodec" | 3553 | atempo_filter_deps="avcodec" |
| @@ -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 | |||
| 29 | enum ASoftClipTypes { | 30 | enum 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 | ||
| 43 | typedef 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 | |||
| 42 | typedef struct ASoftClipContext { | 51 | typedef 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_PARAM | 69 | #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 | ||
| 65 | static const AVOption asoftclip_options[] = { | 71 | static 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 | |||
| 85 | static int query_formats(AVFilterContext *ctx) | 91 | static 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_NONE | 95 | 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 | ||
| 108 | static 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 | |||
| 143 | static 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 | |||
| 103 | static void filter_flt(ASoftClipContext *s, | 155 | static 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 | ||
| 268 | static 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 | |||
| 195 | static void filter_dbl(ASoftClipContext *s, | 280 | static 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); |
| 430 | fail: | ||
| 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 | ||
| 439 | static av_cold void uninit(AVFilterContext *ctx) | 476 | static 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 | ||
| 447 | static const AVFilterPad inputs[] = { | 484 | static const AVFilterPad inputs[] = { |