Go to the documentation of this file.
41 #define MAX_BANDS MAX_SPLITS + 1
85 #define OFFSET(x) offsetof(AudioCrossoverContext, x)
86 #define AF AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
99 {
"18th",
"18th order (108 dB/8ve)",0,
AV_OPT_TYPE_CONST, {.i64=8}, 0, 0,
AF, .unit =
"m" },
100 {
"20th",
"20th order (120 dB/8ve)",0,
AV_OPT_TYPE_CONST, {.i64=9}, 0, 0,
AF, .unit =
"m" },
103 {
"precision",
"set processing precision",
OFFSET(precision),
AV_OPT_TYPE_INT, {.i64=0}, 0, 2,
AF, .unit =
"precision" },
104 {
"auto",
"set auto processing precision", 0,
AV_OPT_TYPE_CONST, {.i64=0}, 0, 0,
AF, .unit =
"precision" },
105 {
"float",
"set single-floating point processing precision", 0,
AV_OPT_TYPE_CONST, {.i64=1}, 0, 0,
AF, .unit =
"precision" },
106 {
"double",
"set double-floating point processing precision", 0,
AV_OPT_TYPE_CONST, {.i64=2}, 0, 0,
AF, .unit =
"precision" },
129 switch (
s->precision) {
131 sample_fmts_list = auto_sample_fmts;
152 char *p, *
arg, *saveptr =
NULL;
172 if (
c[0] ==
'd' &&
c[1] ==
'B')
187 char *p, *
arg, *saveptr =
NULL;
212 if (
i > 0 && freq <= s->splits[
i-1]) {
226 for (
i = 0;
i <=
s->nb_splits;
i++) {
245 double omega = 2. *
M_PI *
fc / sr;
246 double cosine = cos(omega);
247 double alpha = sin(omega) / (2. * q);
249 double b0 = (1. - cosine) / 2.;
250 double b1 = 1. - cosine;
251 double b2 = (1. - cosine) / 2.;
253 double a1 = -2. * cosine;
271 double omega = 2. *
M_PI *
fc / sr;
272 double cosine = cos(omega);
273 double alpha = sin(omega) / (2. * q);
275 double b0 = (1. + cosine) / 2.;
276 double b1 = -1. - cosine;
277 double b2 = (1. + cosine) / 2.;
279 double a1 = -2. * cosine;
297 double omega = 2. *
M_PI *
fc / sr;
298 double cosine = cos(omega);
299 double alpha = sin(omega) / (2. * q);
302 double a1 = -2. * cosine;
323 double omega = 2. *
M_PI *
fc / sr;
340 double n = order / 2.;
342 for (
int i = 0;
i < n / 2;
i++)
343 q[
i] = 1. / (-2. * cos(
M_PI * (2. * (
i + 1) + n - 1.) / (2. * n)));
346 #define BIQUAD_PROCESS(name, type) \
347 static void biquad_process_## name(const type *const c, \
349 type *dst, const type *src, \
352 const type b0 = c[B0]; \
353 const type b1 = c[B1]; \
354 const type b2 = c[B2]; \
355 const type a1 = c[A1]; \
356 const type a2 = c[A2]; \
360 for (int n = 0; n + 1 < nb_samples; n++) { \
364 out = in * b0 + z1; \
365 z1 = b1 * in + z2 + a1 * out; \
366 z2 = b2 * in + a2 * out; \
371 out = in * b0 + z1; \
372 z1 = b1 * in + z2 + a1 * out; \
373 z2 = b2 * in + a2 * out; \
377 if (nb_samples & 1) { \
378 const int n = nb_samples - 1; \
379 const type in = src[n]; \
382 out = in * b0 + z1; \
383 z1 = b1 * in + z2 + a1 * out; \
384 z2 = b2 * in + a2 * out; \
395 #define XOVER_PROCESS(name, type, one, ff) \
396 static int filter_channels_## name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
398 AudioCrossoverContext *s = ctx->priv; \
400 AVFrame **frames = s->frames; \
401 const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; \
402 const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; \
403 const int nb_samples = in->nb_samples; \
404 const int nb_outs = ctx->nb_outputs; \
405 const int first_order = s->first_order; \
407 for (int ch = start; ch < end; ch++) { \
408 const type *src = (const type *)in->extended_data[ch]; \
409 type *xover = (type *)s->xover->extended_data[ch]; \
411 s->fdsp->vector_## ff ##mul_scalar((type *)frames[0]->extended_data[ch], src, \
412 s->level_in, FFALIGN(nb_samples, sizeof(type))); \
414 for (int band = 0; band < nb_outs; band++) { \
415 for (int f = 0; band + 1 < nb_outs && f < s->filter_count; f++) { \
416 const type *prv = (const type *)frames[band]->extended_data[ch]; \
417 type *dst = (type *)frames[band + 1]->extended_data[ch]; \
418 const type *hsrc = f == 0 ? prv : dst; \
419 type *hp = xover + nb_outs * 20 + band * 20 + f * 2; \
420 const type *const hpc = (type *)&s->hp[band][f].c ## ff; \
422 biquad_process_## name(hpc, hp, dst, hsrc, nb_samples); \
425 for (int f = 0; band + 1 < nb_outs && f < s->filter_count; f++) { \
426 type *dst = (type *)frames[band]->extended_data[ch]; \
427 const type *lsrc = dst; \
428 type *lp = xover + band * 20 + f * 2; \
429 const type *const lpc = (type *)&s->lp[band][f].c ## ff; \
431 biquad_process_## name(lpc, lp, dst, lsrc, nb_samples); \
434 for (int aband = band + 1; aband + 1 < nb_outs; aband++) { \
436 const type *asrc = (const type *)frames[band]->extended_data[ch]; \
437 type *dst = (type *)frames[band]->extended_data[ch]; \
438 type *ap = xover + nb_outs * 40 + (aband * nb_outs + band) * 20; \
439 const type *const apc = (type *)&s->ap[aband][0].c ## ff; \
441 biquad_process_## name(apc, ap, dst, asrc, nb_samples); \
444 for (int f = first_order; f < s->ap_filter_count; f++) { \
445 const type *asrc = (const type *)frames[band]->extended_data[ch]; \
446 type *dst = (type *)frames[band]->extended_data[ch]; \
447 type *ap = xover + nb_outs * 40 + (aband * nb_outs + band) * 20 + f * 2;\
448 const type *const apc = (type *)&s->ap[aband][f].c ## ff; \
450 biquad_process_## name(apc, ap, dst, asrc, nb_samples); \
455 for (int band = 0; band < nb_outs; band++) { \
456 const type gain = s->gains[band] * ((band & 1 && first_order) ? -one : one); \
457 type *dst = (type *)frames[band]->extended_data[ch]; \
459 s->fdsp->vector_## ff ##mul_scalar(dst, dst, gain, \
460 FFALIGN(nb_samples, sizeof(type))); \
477 s->order = (
s->order_opt + 1) * 2;
478 s->filter_count =
s->order / 2;
479 s->first_order =
s->filter_count & 1;
480 s->ap_filter_count =
s->filter_count / 2 +
s->first_order;
483 for (
int band = 0; band <=
s->nb_splits; band++) {
484 if (
s->first_order) {
489 for (
int n =
s->first_order; n < s->filter_count; n++) {
490 const int idx =
s->filter_count / 2 - ((n +
s->first_order) / 2 -
s->first_order) - 1;
499 for (
int n =
s->first_order; n < s->ap_filter_count; n++) {
500 const int idx = (
s->filter_count / 2 - ((n * 2 +
s->first_order) / 2 -
s->first_order) - 1);
513 ctx->nb_outputs *
ctx->nb_outputs * 10));
527 for (
int i = 0;
i <
ctx->nb_outputs;
i++) {
543 for (
int i = 0;
i <
ctx->nb_outputs;
i++) {
556 for (
int i = 0;
i <
ctx->nb_outputs;
i++)
569 for (
int i = 0;
i <
ctx->nb_outputs;
i++) {
584 for (
int i = 0;
i <
ctx->nb_outputs;
i++) {
592 for (
int i = 0;
i <
ctx->nb_outputs;
i++) {
622 .
name =
"acrossover",
625 .priv_class = &acrossover_class,
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
@ AV_SAMPLE_FMT_FLTP
float, planar
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 minimum maximum flags name is the option name
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
BiquadCoeffs lp[MAX_BANDS][20]
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
static enum AVSampleFormat sample_fmts[]
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
char * av_asprintf(const char *fmt,...)
BiquadCoeffs hp[MAX_BANDS][20]
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
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).
#define FILTER_QUERY_FUNC(func)
AVFILTER_DEFINE_CLASS(acrossover)
#define fc(width, name, range_min, range_max)
#define BIQUAD_PROCESS(name, type)
const char * name
Filter name.
AVFrame * frames[MAX_BANDS]
A link between two filters.
int(* filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
#define FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, filter)
Forward the status on an output link to all input links.
static double b1(void *priv, double x, double y)
static const AVOption acrossover_options[]
if it could not because there are no more frames
static int parse_gains(AVFilterContext *ctx)
static void set_hp(BiquadCoeffs *b, double fc, double q, double sr)
A filter pad used for either input or output.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
const AVFilter ff_af_acrossover
#define FILTER_INPUTS(array)
int av_sscanf(const char *string, const char *format,...)
See libc sscanf manual for more information.
Describe the class of an AVClass context structure.
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
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
BiquadCoeffs ap[MAX_BANDS][20]
#define AVFILTER_FLAG_DYNAMIC_OUTPUTS
The number of the filter outputs is not determined just by AVFilter.outputs.
static int query_formats(AVFilterContext *ctx)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static av_cold void uninit(AVFilterContext *ctx)
static double b2(void *priv, double x, double y)
static void calc_q_factors(int order, double *q)
int nb_samples
number of audio samples (per channel) described by this frame
#define i(width, name, range_min, range_max)
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
AVSampleFormat
Audio sample formats.
const char * name
Pad name.
static void set_lp(BiquadCoeffs *b, double fc, double q, double sr)
static const AVFilterPad inputs[]
static void set_ap(BiquadCoeffs *b, double fc, double q, double sr)
enum AVMediaType type
AVFilterPad type.
static void set_ap1(BiquadCoeffs *b, double fc, double sr)
static av_cold int init(AVFilterContext *ctx)
@ AV_SAMPLE_FMT_DBLP
double, planar
static int activate(AVFilterContext *ctx)
int ff_outlink_get_status(AVFilterLink *link)
Get the status on an output link.
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
static int config_input(AVFilterLink *inlink)
static const int16_t alpha[]
int ff_append_outpad_free_name(AVFilterContext *f, AVFilterPad *p)
av_cold AVFloatDSPContext * avpriv_float_dsp_alloc(int bit_exact)
Allocate a float DSP context.
#define XOVER_PROCESS(name, type, one, ff)
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
static double b0(void *priv, double x, double y)
the definition of that something depends on the semantic of the filter The callback must examine the status of the filter s links and proceed accordingly The status of output links is stored in the status_in and status_out fields and tested by the ff_outlink_frame_wanted() function. If this function returns true
static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)