FFmpeg: libavfilter/af_adeclick.c Source File
Go to the documentation of this file. 1 /*
2 * Copyright (c) 2018 Paul B Mahol
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
28
47
50
58
65
71
73
80
84
86 double sigmae, double *detection,
87 double *acoefficients, uint8_t *click,
int *
index,
88 const double *
src,
double *
dst);
90
91 #define OFFSET(x) offsetof(AudioDeclickContext, x)
92 #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
93
112 };
113
115
117 {
121
123 s->window_size =
FFMAX(100,
inlink->sample_rate *
s->w / 1000.);
124 s->ar_order =
FFMAX(
s->window_size *
s->ar / 100., 1);
125 s->nb_burst_samples =
s->window_size *
s->burst / 1000.;
126 s->hop_size =
FFMAX(1,
s->window_size * (1. - (
s->overlap / 100.)));
127
128 s->window_func_lut =
av_calloc(
s->window_size,
sizeof(*
s->window_func_lut));
129 if (!
s->window_func_lut)
131
132 {
133 double *tx_in[2], *tx_out[2];
138
139 tx_size = 1 << (32 -
ff_clz(
s->window_size));
140
145
146 scale = 1.0 / tx_size;
150
151 tx_in[0] =
av_calloc(tx_size + 2,
sizeof(*tx_in[0]));
152 tx_in[1] =
av_calloc(tx_size + 2,
sizeof(*tx_in[1]));
153 tx_out[0] =
av_calloc(tx_size + 2,
sizeof(*tx_out[0]));
154 tx_out[1] =
av_calloc(tx_size + 2,
sizeof(*tx_out[1]));
155 if (!tx_in[0] || !tx_in[1] || !tx_out[0] || !tx_out[1])
157
158 for (
int n = 0; n <
s->window_size -
s->hop_size; n++)
159 tx_in[0][n] = 1.0;
160
161 for (
int n = 0; n <
s->hop_size; n++)
162 tx_in[1][n] = 1.0;
163
164 tx_fn(tx, tx_out[0], tx_in[0], sizeof(double));
165 tx_fn(tx, tx_out[1], tx_in[1], sizeof(double));
166
167 for (int n = 0; n <= tx_size/2; n++) {
168 double re0 = tx_out[0][2*n];
169 double im0 = tx_out[0][2*n+1];
170 double re1 = tx_out[1][2*n];
171 double im1 = tx_out[1][2*n+1];
172
173 tx_in[0][2*n] = re0 * re1 - im0 * im1;
174 tx_in[0][2*n+1] = re0 * im1 + re1 * im0;
175 }
176
178
179 scale = 1.0 / (
s->window_size -
s->hop_size);
180 for (
int n = 0; n <
s->window_size; n++)
181 s->window_func_lut[n] = tx_out[0][n] *
scale;
182
185
190 }
191
201 if (!
s->in || !
s->out || !
s->buffer || !
s->is || !
s->enabled)
203
210 s->overlap_skip =
s->method ? (
s->window_size -
s->hop_size) / 2 : 0;
211 if (
s->overlap_skip > 0) {
214 }
215
216 s->nb_channels =
inlink->ch_layout.nb_channels;
220
221 for (
i = 0;
i <
inlink->ch_layout.nb_channels;
i++) {
223
224 c->detection =
av_calloc(
s->window_size,
sizeof(*
c->detection));
225 c->auxiliary =
av_calloc(
s->ar_order + 1,
sizeof(*
c->auxiliary));
226 c->acoefficients =
av_calloc(
s->ar_order + 1,
sizeof(*
c->acoefficients));
227 c->acorrelation =
av_calloc(
s->ar_order + 1,
sizeof(*
c->acorrelation));
229 c->click =
av_calloc(
s->window_size,
sizeof(*
c->click));
230 c->index =
av_calloc(
s->window_size,
sizeof(*
c->index));
231 c->interpolated =
av_calloc(
s->window_size,
sizeof(*
c->interpolated));
232 if (!
c->auxiliary || !
c->acoefficients || !
c->detection || !
c->click ||
233 !
c->index || !
c->interpolated || !
c->acorrelation || !
c->tmp)
235 }
236
237 return 0;
238 }
239
242 {
244
245 for (
i = 0;
i <= order;
i++) {
247
248 for (j =
i; j <
size; j++)
250
252 }
253 }
254
257 {
260
262
264
265 /* Levinson-Durbin algorithm */
266 k[0] =
a[0] = -
r[1] /
r[0];
267 alpha =
r[0] * (1. - k[0] * k[0]);
269 double epsilon = 0.;
270
271 for (j = 0; j <
i; j++)
272 epsilon +=
a[j] *
r[
i - j];
274
277 for (j =
i - 1; j >= 0; j--)
278 k[j] =
a[j] + k[
i] *
a[
i - j - 1];
279 for (j = 0; j <=
i; j++)
281 }
282
283 k[0] = 1.;
286
288 }
289
291 {
293
296 return 0;
297
298 return 1;
299 }
300
302 {
304
306 return 1;
307
310
311 while (start <= end) {
312 i = (end + start) / 2;
314 return 0;
319 }
320
321 return 1;
322 }
323
325 {
327
328 for (
i = 0;
i < n;
i++) {
329 const int in =
i * n;
331
333 for (j = 0; j <
i; j++)
335
337 return -1;
338 }
339
341 for (j =
i + 1; j < n; j++) {
342 const int jn = j * n;
343 double x;
344
346 for (k = 0; k <
i; k++)
349 }
350 }
351
352 return 0;
353 }
354
356 double *vector,
int n,
double *
out)
357 {
359 double *y;
360
364
367 if (!y)
369
370 for (
i = 0;
i < n;
i++) {
371 const int in =
i * n;
373
375 for (j = 0; j <
i; j++)
378 }
379
380 for (
i = n - 1;
i >= 0;
i--) {
382 for (j =
i + 1; j < n; j++)
384 }
385
386 return 0;
387 }
388
390 double *acoefficients,
int *
index,
int nb_errors,
391 double *auxiliary, double *interpolated)
392 {
395
396 av_fast_malloc(&
c->matrix, &
c->matrix_size, nb_errors * nb_errors *
sizeof(*
c->matrix));
400
403 if (!vector)
405
407
408 for (
i = 0;
i < nb_errors;
i++) {
409 const int im =
i * nb_errors;
410
411 for (j =
i; j < nb_errors; j++) {
414 } else {
416 }
417 }
418 }
419
420 for (
i = 0;
i < nb_errors;
i++) {
422
426
428 }
429
431 }
432
434 double unused0,
435 double *unused1, double *unused2,
437 const double *
src,
double *
dst)
438 {
440 double max_amplitude = 0;
441 unsigned *histogram;
443
444 av_fast_malloc(&
c->histogram, &
c->histogram_size,
s->nb_hbins *
sizeof(*
c->histogram));
447 histogram =
c->histogram;
448 memset(histogram, 0,
sizeof(*histogram) *
s->nb_hbins);
449
450 for (
i = 0;
i <
s->window_size;
i++) {
452
456 }
457
458 for (
i =
s->nb_hbins - 1;
i > 1;
i--) {
461 max_amplitude =
i / (
double)
s->nb_hbins;
462 }
463 break;
464 }
465 }
466
467 if (max_amplitude > 0.) {
468 for (
i = 0;
i <
s->window_size;
i++) {
470 }
471 }
472
473 memset(
clip, 0,
s->ar_order *
sizeof(*
clip));
474 memset(
clip + (
s->window_size -
s->ar_order), 0,
s->ar_order *
sizeof(*
clip));
475
479
480 return nb_clips;
481 }
482
484 double sigmae,
485 double *detection, double *acoefficients,
486 uint8_t *click,
int *
index,
487 const double *
src,
double *
dst)
488 {
490 int i, j, nb_clicks = 0, prev = -1;
491
492 memset(detection, 0,
s->window_size *
sizeof(*detection));
493
495 for (j = 0; j <=
s->ar_order; j++) {
496 detection[
i] += acoefficients[j] *
src[
i - j];
497 }
498 }
499
500 for (
i = 0;
i <
s->window_size;
i++) {
503 }
504
505 for (
i = 0;
i <
s->window_size;
i++) {
507 continue;
508
510 for (j = prev + 1; j <
i; j++)
511 click[j] = 1;
513 }
514
515 memset(click, 0,
s->ar_order *
sizeof(*click));
516 memset(click + (
s->window_size -
s->ar_order), 0,
s->ar_order *
sizeof(*click));
517
521
522 return nb_clicks;
523 }
524
528
530 {
534 const double *
src = (
const double *)
s->in->extended_data[ch];
535 double *
is = (
double *)
s->is->extended_data[ch];
536 double *
dst = (
double *)
s->out->extended_data[ch];
537 double *ptr = (
double *)
out->extended_data[ch];
538 double *buf = (
double *)
s->buffer->extended_data[ch];
539 const double *
w =
s->window_func_lut;
541 double sigmae;
543
545
547 double *interpolated =
c->interpolated;
549 int nb_errors;
550
551 nb_errors =
s->detector(
s,
c, sigmae,
c->detection,
c->acoefficients,
553 if (nb_errors > 0) {
554 double *enabled = (
double *)
s->enabled->extended_data[0];
555
557 nb_errors,
c->auxiliary, interpolated);
560
562
563 for (j = 0; j < nb_errors; j++) {
564 if (enabled[
index[j]]) {
567 }
568 }
569 }
570 } else {
571 memcpy(
dst,
src,
s->window_size *
sizeof(*
dst));
572 }
573
574 if (
s->method == 0) {
575 for (j = 0; j <
s->window_size; j++)
576 buf[j] +=
dst[j] *
w[j];
577 } else {
578 const int skip =
s->overlap_skip;
579
580 for (j = 0; j <
s->hop_size; j++)
582 }
583 for (j = 0; j <
s->hop_size; j++)
584 ptr[j] = buf[j];
585
586 memmove(buf, buf +
s->hop_size, (
s->window_size * 2 -
s->hop_size) *
sizeof(*buf));
587 memmove(
is,
is +
s->hop_size, (
s->window_size -
s->hop_size) *
sizeof(*
is));
588 memset(buf +
s->window_size * 2 -
s->hop_size, 0,
s->hop_size *
sizeof(*buf));
589 memset(
is +
s->window_size -
s->hop_size, 0,
s->hop_size *
sizeof(*
is));
590
591 return 0;
592 }
593
595 {
600 int ret = 0, j, ch, detected_errors = 0;
602
606
611
616
617 for (ch = 0; ch <
s->in->ch_layout.nb_channels; ch++) {
618 double *
is = (
double *)
s->is->extended_data[ch];
619
620 for (j = 0; j <
s->hop_size; j++) {
622 detected_errors++;
623 }
624 }
625
628
629 if (
s->samples_left > 0)
630 out->nb_samples =
FFMIN(
s->hop_size,
s->samples_left);
631
634
635 s->detected_errors += detected_errors;
636 s->nb_samples +=
out->nb_samples *
inlink->ch_layout.nb_channels;
637
641
642 if (
s->samples_left > 0) {
643 s->samples_left -=
s->hop_size;
644 if (
s->samples_left <= 0)
646 }
647
652 }
653
655 {
662
664
669 double *e = (
double *)
s->enabled->extended_data[0];
670
673
677 e[
i] = !
ctx->is_disabled;
678
683 }
684
688
691 return 0;
692 }
693
699 return 0;
700 }
701 }
702
703 if (
s->eof &&
s->samples_left <= 0) {
705 return 0;
706 }
707
710
712 }
713
715 {
717
718 s->is_declip = !strcmp(
ctx->filter->name,
"adeclip");
721 } else {
723 }
724
725 return 0;
726 }
727
729 {
732
733 if (
s->nb_samples > 0)
735 s->is_declip ?
"clips" :
"clicks",
s->detected_errors,
736 s->nb_samples, 100. *
s->detected_errors /
s->nb_samples);
737
746
748 for (
i = 0;
i <
s->nb_channels;
i++) {
750
762 c->histogram_size = 0;
767 }
768 }
771 }
772
774 {
778 },
779 };
780
785 .priv_class = &adeclick_class,
793 };
794
813 };
814
816
821 .priv_class = &adeclip_class,
829 };
void av_audio_fifo_free(AVAudioFifo *af)
Free an AVAudioFifo.
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Filter the word "frame" indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
The official guide to swscale for confused that is
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
#define AVERROR_EOF
End of file.
int av_audio_fifo_write(AVAudioFifo *af, void *const *data, int nb_samples)
Write data to an AVAudioFifo.
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define FILTER_INPUTS(array)
This structure describes decoded (raw) audio or video data.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
static av_cold int init(AVFilterContext *ctx)
const char * name
Filter name.
A link between two filters.
static int activate(AVFilterContext *ctx)
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
const AVFilter ff_af_adeclip
av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags)
Initialize a transform context with the given configuration (i)MDCTs with an odd length are currently...
Context for an Audio FIFO Buffer.
int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
Drain data from an AVAudioFifo.
A filter pad used for either input or output.
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
@ AV_OPT_TYPE_DOUBLE
Underlying C type is double.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
static int detect_clicks(AudioDeclickContext *s, DeclickChannel *c, double sigmae, double *detection, double *acoefficients, uint8_t *click, int *index, const double *src, double *dst)
#define FILTER_OUTPUTS(array)
static av_cold void uninit(AVFilterContext *ctx)
static int config_input(AVFilterLink *inlink)
static void autocorrelation(const double *input, int order, int size, double *output, double scale)
Describe the class of an AVClass context structure.
static __device__ float fabs(float a)
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link's FIFO and update the link's stats.
Rational number (pair of numerator and denominator).
AVAudioFifo * av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels, int nb_samples)
Allocate an AVAudioFifo.
const AVFilterPad ff_audio_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_AUDIO.
int(* detector)(struct AudioDeclickContext *s, DeclickChannel *c, double sigmae, double *detection, double *acoefficients, uint8_t *click, int *index, const double *src, double *dst)
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
#define FILTER_SINGLE_SAMPLEFMT(sample_fmt_)
static int filter_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs)
static const AVOption adeclick_options[]
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
double fmin(double, double)
#define AV_NOPTS_VALUE
Undefined timestamp value.
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
int av_audio_fifo_peek(const AVAudioFifo *af, void *const *data, int nb_samples)
Peek data from an AVAudioFifo.
FF_FILTER_FORWARD_WANTED(outlink, inlink)
int av_audio_fifo_size(AVAudioFifo *af)
Get the current number of samples in the AVAudioFifo available for reading.
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
static double autoregression(const double *samples, int ar_order, int nb_samples, double *k, double *r, double *a)
static int interpolation(DeclickChannel *c, const double *src, int ar_order, double *acoefficients, int *index, int nb_errors, double *auxiliary, double *interpolated)
av_cold void av_tx_uninit(AVTXContext **ctx)
Frees a context and sets *ctx to NULL, does nothing when *ctx == NULL.
#define AV_LOG_INFO
Standard information.
static int detect_clips(AudioDeclickContext *s, DeclickChannel *c, double unused0, double *unused1, double *unused2, uint8_t *clip, int *index, const double *src, double *dst)
int nb_samples
number of audio samples (per channel) described by this frame
static int filter_frame(AVFilterLink *inlink)
#define i(width, name, range_min, range_max)
static int find_index(int *index, int value, int size)
static const AVOption adeclip_options[]
uint8_t ** extended_data
pointers to the data planes/channels.
Used for passing data between threads.
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
const char * name
Pad name.
void * av_calloc(size_t nmemb, size_t size)
static int factorization(double *matrix, int n)
AVFILTER_DEFINE_CLASS(adeclick)
static const AVFilterPad inputs[]
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ AV_SAMPLE_FMT_DBLP
double, planar
Filter the word "frame" indicates either a video frame or a group of audio samples
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
static void scale(int *out, const int *in, const int w, const int h, const int shift)
static const int16_t alpha[]
static int do_interpolation(DeclickChannel *c, double *matrix, double *vector, int n, double *out)
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will have its filter_frame() c...
const AVFilter ff_af_adeclick
static int isfinite_array(double *samples, int nb_samples)
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
Generated on Fri Aug 22 2025 13:59:03 for FFmpeg by
doxygen
1.8.17