Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
5109c381
Commit
5109c381
authored
May 31, 2018
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter: add acrossover filter
Signed-off-by:
Paul B Mahol
<
onemda@gmail.com
>
parent
63c69d51
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
364 additions
and
1 deletion
+364
-1
Changelog
Changelog
+1
-0
filters.texi
doc/filters.texi
+17
-0
Makefile
libavfilter/Makefile
+1
-0
af_acrossover.c
libavfilter/af_acrossover.c
+343
-0
allfilters.c
libavfilter/allfilters.c
+1
-0
version.h
libavfilter/version.h
+1
-1
No files found.
Changelog
View file @
5109c381
...
...
@@ -29,6 +29,7 @@ version <next>:
- AVS2 video encoder via libxavs2
- amultiply filter
- Block-Matching 3d (bm3d) denoising filter
- acrossover filter
version 4.0:
...
...
doc/filters.texi
View file @
5109c381
...
...
@@ -493,6 +493,23 @@ ffmpeg -i first.flac -i second.flac -filter_complex acrossfade=d=10:o=0:c1=exp:c
@
end
example
@
end
itemize
@
section
acrossover
Split
audio
stream
into
several
bands
.
This
filter
splits
audio
stream
into
two
or
more
frequency
ranges
.
Summing
all
streams
back
will
give
flat
output
.
The
filter
accepts
the
following
options
:
@
table
@
option
@
item
split
Set
split
frequencies
.
Those
must
be
positive
and
increasing
.
@
item
order
Set
filter
order
,
can
be
@
var
{
2
nd
},
@
var
{
4
th
}
or
@
var
{
8
th
}.
Default
is
@
var
{
4
th
}.
@
end
table
@
section
acrusher
Reduce
audio
bit
resolution
.
...
...
libavfilter/Makefile
View file @
5109c381
...
...
@@ -35,6 +35,7 @@ OBJS-$(CONFIG_ACOMPRESSOR_FILTER) += af_sidechaincompress.o
OBJS-$(CONFIG_ACONTRAST_FILTER)
+=
af_acontrast.o
OBJS-$(CONFIG_ACOPY_FILTER)
+=
af_acopy.o
OBJS-$(CONFIG_ACROSSFADE_FILTER)
+=
af_afade.o
OBJS-$(CONFIG_ACROSSOVER_FILTER)
+=
af_acrossover.o
OBJS-$(CONFIG_ACRUSHER_FILTER)
+=
af_acrusher.o
OBJS-$(CONFIG_ACUE_FILTER)
+=
f_cue.o
OBJS-$(CONFIG_ADECLICK_FILTER)
+=
af_adeclick.o
...
...
libavfilter/af_acrossover.c
0 → 100644
View file @
5109c381
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Crossover filter
*
* Split an audio stream into several bands.
*/
#include "libavutil/attributes.h"
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
#include "libavutil/internal.h"
#include "libavutil/opt.h"
#include "audio.h"
#include "avfilter.h"
#include "formats.h"
#include "internal.h"
#define MAX_SPLITS 16
#define MAX_BANDS MAX_SPLITS + 1
typedef
struct
BiquadContext
{
double
a0
,
a1
,
a2
;
double
b1
,
b2
;
double
i1
,
i2
;
double
o1
,
o2
;
}
BiquadContext
;
typedef
struct
CrossoverChannel
{
BiquadContext
lp
[
MAX_BANDS
][
4
];
BiquadContext
hp
[
MAX_BANDS
][
4
];
}
CrossoverChannel
;
typedef
struct
AudioCrossoverContext
{
const
AVClass
*
class
;
char
*
splits_str
;
int
order
;
int
filter_count
;
int
nb_splits
;
float
*
splits
;
CrossoverChannel
*
xover
;
}
AudioCrossoverContext
;
#define OFFSET(x) offsetof(AudioCrossoverContext, x)
#define AF AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
static
const
AVOption
acrossover_options
[]
=
{
{
"split"
,
"set split frequencies"
,
OFFSET
(
splits_str
),
AV_OPT_TYPE_STRING
,
{.
str
=
"500"
},
0
,
0
,
AF
},
{
"order"
,
"set order"
,
OFFSET
(
order
),
AV_OPT_TYPE_INT
,
{.
i64
=
1
},
0
,
2
,
AF
,
"m"
},
{
"2nd"
,
"2nd order"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
0
},
0
,
0
,
AF
,
"m"
},
{
"4th"
,
"4th order"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
1
},
0
,
0
,
AF
,
"m"
},
{
"8th"
,
"8th order"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
2
},
0
,
0
,
AF
,
"m"
},
{
NULL
}
};
AVFILTER_DEFINE_CLASS
(
acrossover
);
static
av_cold
int
init
(
AVFilterContext
*
ctx
)
{
AudioCrossoverContext
*
s
=
ctx
->
priv
;
char
*
p
,
*
arg
,
*
saveptr
=
NULL
;
int
i
,
ret
=
0
;
s
->
splits
=
av_calloc
(
MAX_SPLITS
,
sizeof
(
*
s
->
splits
));
if
(
!
s
->
splits
)
return
AVERROR
(
ENOMEM
);
p
=
s
->
splits_str
;
for
(
i
=
0
;
i
<
MAX_SPLITS
;
i
++
)
{
float
freq
;
if
(
!
(
arg
=
av_strtok
(
p
,
" |"
,
&
saveptr
)))
break
;
p
=
NULL
;
ret
=
sscanf
(
arg
,
"%f"
,
&
freq
);
if
(
freq
<=
0
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Frequency %f must be positive number.
\n
"
,
freq
);
return
AVERROR
(
EINVAL
);
}
if
(
i
>
0
&&
freq
<=
s
->
splits
[
i
-
1
])
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Frequency %f must be in increasing order.
\n
"
,
freq
);
return
AVERROR
(
EINVAL
);
}
s
->
splits
[
i
]
=
freq
;
}
s
->
nb_splits
=
i
;
for
(
i
=
0
;
i
<=
s
->
nb_splits
;
i
++
)
{
AVFilterPad
pad
=
{
0
};
char
*
name
;
pad
.
type
=
AVMEDIA_TYPE_AUDIO
;
name
=
av_asprintf
(
"out%d"
,
ctx
->
nb_outputs
);
if
(
!
name
)
return
AVERROR
(
ENOMEM
);
pad
.
name
=
name
;
if
((
ret
=
ff_insert_outpad
(
ctx
,
i
,
&
pad
))
<
0
)
{
av_freep
(
&
pad
.
name
);
return
ret
;
}
}
return
ret
;
}
static
void
set_lp
(
BiquadContext
*
b
,
float
fc
,
float
q
,
float
sr
)
{
double
omega
=
(
2
.
0
*
M_PI
*
fc
/
sr
);
double
sn
=
sin
(
omega
);
double
cs
=
cos
(
omega
);
double
alpha
=
(
sn
/
(
2
*
q
));
double
inv
=
(
1
.
0
/
(
1
.
0
+
alpha
));
b
->
a2
=
b
->
a0
=
(
inv
*
(
1
.
0
-
cs
)
*
0
.
5
);
b
->
a1
=
b
->
a0
+
b
->
a0
;
b
->
b1
=
-
2
.
*
cs
*
inv
;
b
->
b2
=
(
1
.
-
alpha
)
*
inv
;
}
static
void
set_hp
(
BiquadContext
*
b
,
float
fc
,
float
q
,
float
sr
)
{
double
omega
=
2
*
M_PI
*
fc
/
sr
;
double
sn
=
sin
(
omega
);
double
cs
=
cos
(
omega
);
double
alpha
=
sn
/
(
2
*
q
);
double
inv
=
1
.
0
/
(
1
.
0
+
alpha
);
b
->
a0
=
inv
*
(
1
.
+
cs
)
/
2
.;
b
->
a1
=
-
2
.
*
b
->
a0
;
b
->
a2
=
b
->
a0
;
b
->
b1
=
-
2
.
*
cs
*
inv
;
b
->
b2
=
(
1
.
-
alpha
)
*
inv
;
}
static
int
config_input
(
AVFilterLink
*
inlink
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
AudioCrossoverContext
*
s
=
ctx
->
priv
;
int
ch
,
band
,
sample_rate
=
inlink
->
sample_rate
;
double
q
;
s
->
xover
=
av_calloc
(
inlink
->
channels
,
sizeof
(
*
s
->
xover
));
if
(
!
s
->
xover
)
return
AVERROR
(
ENOMEM
);
switch
(
s
->
order
)
{
case
0
:
q
=
0
.
5
;
s
->
filter_count
=
1
;
break
;
case
1
:
q
=
M_SQRT1_2
;
s
->
filter_count
=
2
;
break
;
case
2
:
q
=
0
.
54
;
s
->
filter_count
=
4
;
break
;
}
for
(
ch
=
0
;
ch
<
inlink
->
channels
;
ch
++
)
{
for
(
band
=
0
;
band
<=
s
->
nb_splits
;
band
++
)
{
set_lp
(
&
s
->
xover
[
ch
].
lp
[
band
][
0
],
s
->
splits
[
band
],
q
,
sample_rate
);
set_hp
(
&
s
->
xover
[
ch
].
hp
[
band
][
0
],
s
->
splits
[
band
],
q
,
sample_rate
);
if
(
s
->
order
>
1
)
{
set_lp
(
&
s
->
xover
[
ch
].
lp
[
band
][
1
],
s
->
splits
[
band
],
1
.
34
,
sample_rate
);
set_hp
(
&
s
->
xover
[
ch
].
hp
[
band
][
1
],
s
->
splits
[
band
],
1
.
34
,
sample_rate
);
set_lp
(
&
s
->
xover
[
ch
].
lp
[
band
][
2
],
s
->
splits
[
band
],
q
,
sample_rate
);
set_hp
(
&
s
->
xover
[
ch
].
hp
[
band
][
2
],
s
->
splits
[
band
],
q
,
sample_rate
);
set_lp
(
&
s
->
xover
[
ch
].
lp
[
band
][
3
],
s
->
splits
[
band
],
1
.
34
,
sample_rate
);
set_hp
(
&
s
->
xover
[
ch
].
hp
[
band
][
3
],
s
->
splits
[
band
],
1
.
34
,
sample_rate
);
}
else
{
set_lp
(
&
s
->
xover
[
ch
].
lp
[
band
][
1
],
s
->
splits
[
band
],
q
,
sample_rate
);
set_hp
(
&
s
->
xover
[
ch
].
hp
[
band
][
1
],
s
->
splits
[
band
],
q
,
sample_rate
);
}
}
}
return
0
;
}
static
int
query_formats
(
AVFilterContext
*
ctx
)
{
AVFilterFormats
*
formats
;
AVFilterChannelLayouts
*
layouts
;
static
const
enum
AVSampleFormat
sample_fmts
[]
=
{
AV_SAMPLE_FMT_DBLP
,
AV_SAMPLE_FMT_NONE
};
int
ret
;
layouts
=
ff_all_channel_counts
();
if
(
!
layouts
)
return
AVERROR
(
ENOMEM
);
ret
=
ff_set_common_channel_layouts
(
ctx
,
layouts
);
if
(
ret
<
0
)
return
ret
;
formats
=
ff_make_format_list
(
sample_fmts
);
if
(
!
formats
)
return
AVERROR
(
ENOMEM
);
ret
=
ff_set_common_formats
(
ctx
,
formats
);
if
(
ret
<
0
)
return
ret
;
formats
=
ff_all_samplerates
();
if
(
!
formats
)
return
AVERROR
(
ENOMEM
);
return
ff_set_common_samplerates
(
ctx
,
formats
);
}
static
double
biquad_process
(
BiquadContext
*
b
,
double
in
)
{
double
out
=
in
*
b
->
a0
+
b
->
i1
*
b
->
a1
+
b
->
i2
*
b
->
a2
-
b
->
o1
*
b
->
b1
-
b
->
o2
*
b
->
b2
;
b
->
i2
=
b
->
i1
;
b
->
o2
=
b
->
o1
;
b
->
i1
=
in
;
b
->
o1
=
out
;
return
out
;
}
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
in
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
AudioCrossoverContext
*
s
=
ctx
->
priv
;
AVFrame
*
frames
[
MAX_BANDS
]
=
{
NULL
};
int
i
,
f
,
ch
,
band
,
ret
=
0
;
for
(
i
=
0
;
i
<
ctx
->
nb_outputs
;
i
++
)
{
frames
[
i
]
=
ff_get_audio_buffer
(
ctx
->
outputs
[
i
],
in
->
nb_samples
);
if
(
!
frames
[
i
])
{
ret
=
AVERROR
(
ENOMEM
);
break
;
}
frames
[
i
]
->
pts
=
in
->
pts
;
}
if
(
ret
<
0
)
goto
fail
;
for
(
ch
=
0
;
ch
<
inlink
->
channels
;
ch
++
)
{
const
double
*
src
=
(
const
double
*
)
in
->
extended_data
[
ch
];
CrossoverChannel
*
xover
=
&
s
->
xover
[
ch
];
for
(
band
=
0
;
band
<
ctx
->
nb_outputs
;
band
++
)
{
double
*
dst
=
(
double
*
)
frames
[
band
]
->
extended_data
[
ch
];
for
(
i
=
0
;
i
<
in
->
nb_samples
;
i
++
)
{
dst
[
i
]
=
src
[
i
];
for
(
f
=
0
;
f
<
s
->
filter_count
;
f
++
)
{
if
(
band
+
1
<
ctx
->
nb_outputs
)
{
BiquadContext
*
lp
=
&
xover
->
lp
[
band
][
f
];
dst
[
i
]
=
biquad_process
(
lp
,
dst
[
i
]);
}
if
(
band
-
1
>=
0
)
{
BiquadContext
*
hp
=
&
xover
->
hp
[
band
-
1
][
f
];
dst
[
i
]
=
biquad_process
(
hp
,
dst
[
i
]);
}
}
}
}
}
for
(
i
=
0
;
i
<
ctx
->
nb_outputs
;
i
++
)
{
ret
=
ff_filter_frame
(
ctx
->
outputs
[
i
],
frames
[
i
]);
if
(
ret
<
0
)
break
;
}
fail:
av_frame_free
(
&
in
);
return
ret
;
}
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
{
AudioCrossoverContext
*
s
=
ctx
->
priv
;
int
i
;
av_freep
(
&
s
->
splits
);
for
(
i
=
0
;
i
<
ctx
->
nb_outputs
;
i
++
)
av_freep
(
&
ctx
->
output_pads
[
i
].
name
);
}
static
const
AVFilterPad
inputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
filter_frame
=
filter_frame
,
.
config_props
=
config_input
,
},
{
NULL
}
};
AVFilter
ff_af_acrossover
=
{
.
name
=
"acrossover"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Split audio into per-bands streams."
),
.
priv_size
=
sizeof
(
AudioCrossoverContext
),
.
priv_class
=
&
acrossover_class
,
.
init
=
init
,
.
uninit
=
uninit
,
.
query_formats
=
query_formats
,
.
inputs
=
inputs
,
.
outputs
=
NULL
,
.
flags
=
AVFILTER_FLAG_DYNAMIC_OUTPUTS
,
};
libavfilter/allfilters.c
View file @
5109c381
...
...
@@ -29,6 +29,7 @@ extern AVFilter ff_af_acontrast;
extern
AVFilter
ff_af_acopy
;
extern
AVFilter
ff_af_acue
;
extern
AVFilter
ff_af_acrossfade
;
extern
AVFilter
ff_af_acrossover
;
extern
AVFilter
ff_af_acrusher
;
extern
AVFilter
ff_af_adeclick
;
extern
AVFilter
ff_af_adeclip
;
...
...
libavfilter/version.h
View file @
5109c381
...
...
@@ -30,7 +30,7 @@
#include "libavutil/version.h"
#define LIBAVFILTER_VERSION_MAJOR 7
#define LIBAVFILTER_VERSION_MINOR 3
1
#define LIBAVFILTER_VERSION_MINOR 3
2
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment