Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
ffmpeg
Project
Project
Details
Activity
Releases
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
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Stefan Westerfeld
ffmpeg
Commits
c94988a7
Commit
c94988a7
authored
Jan 03, 2023
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter/af_afade: add options to control unity/silence gains
parent
f0d2ed13
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
112 additions
and
26 deletions
+112
-26
filters.texi
doc/filters.texi
+8
-0
af_afade.c
libavfilter/af_afade.c
+104
-26
No files found.
doc/filters.texi
View file @
c94988a7
...
...
@@ -1380,6 +1380,14 @@ select inverted sine cardinal function
@item nofade
no fade applied
@end table
@item silence
Set the initial gain for fade-in or final gain for fade-out.
Default value is @code{0.0}.
@item unity
Set the initial gain for fade-out or final gain for fade-in.
Default value is @code{1.0}.
@end table
@subsection Commands
...
...
libavfilter/af_afade.c
View file @
c94988a7
...
...
@@ -39,6 +39,8 @@ typedef struct AudioFadeContext {
int64_t
start_sample
;
int64_t
duration
;
int64_t
start_time
;
double
silence
;
double
unity
;
int
overlap
;
int
cf0_eof
;
int
crossfade_is_over
;
...
...
@@ -46,7 +48,10 @@ typedef struct AudioFadeContext {
void
(
*
fade_samples
)(
uint8_t
**
dst
,
uint8_t
*
const
*
src
,
int
nb_samples
,
int
channels
,
int
direction
,
int64_t
start
,
int64_t
range
,
int
curve
);
int64_t
start
,
int64_t
range
,
int
curve
,
double
silence
,
double
unity
);
void
(
*
scale_samples
)(
uint8_t
**
dst
,
uint8_t
*
const
*
src
,
int
nb_samples
,
int
channels
,
double
unity
);
void
(
*
crossfade_samples
)(
uint8_t
**
dst
,
uint8_t
*
const
*
cf0
,
uint8_t
*
const
*
cf1
,
int
nb_samples
,
int
channels
,
...
...
@@ -67,7 +72,7 @@ enum CurveType { NONE = -1, TRI, QSIN, ESIN, HSIN, LOG, IPAR, QUA, CUB, SQU, CBR
AV_SAMPLE_FMT_NONE
};
static
double
fade_gain
(
int
curve
,
int64_t
index
,
int64_t
range
)
static
double
fade_gain
(
int
curve
,
int64_t
index
,
int64_t
range
,
double
silence
,
double
unity
)
{
#define CUBE(a) ((a)*(a)*(a))
double
gain
;
...
...
@@ -142,18 +147,19 @@ static double fade_gain(int curve, int64_t index, int64_t range)
break
;
}
return
gain
;
return
silence
+
(
unity
-
silence
)
*
gain
;
}
#define FADE_PLANAR(name, type) \
static void fade_samples_## name ##p(uint8_t **dst, uint8_t * const *src, \
int nb_samples, int channels, int dir, \
int64_t start, int64_t range, int curve) \
int64_t start, int64_t range,int curve,\
double silence, double unity) \
{ \
int i, c; \
\
for (i = 0; i < nb_samples; i++) { \
double gain = fade_gain(curve, start + i * dir,
range);
\
double gain = fade_gain(curve, start + i * dir,
range,silence,unity);
\
for (c = 0; c < channels; c++) { \
type *d = (type *)dst[c]; \
const type *s = (type *)src[c]; \
...
...
@@ -166,14 +172,15 @@ static void fade_samples_## name ##p(uint8_t **dst, uint8_t * const *src, \
#define FADE(name, type) \
static void fade_samples_## name (uint8_t **dst, uint8_t * const *src, \
int nb_samples, int channels, int dir, \
int64_t start, int64_t range, int curve) \
int64_t start, int64_t range, int curve, \
double silence, double unity) \
{ \
type *d = (type *)dst[0]; \
const type *s = (type *)src[0]; \
int i, c, k = 0; \
\
for (i = 0; i < nb_samples; i++) { \
double gain = fade_gain(curve, start + i * dir,
range);
\
double gain = fade_gain(curve, start + i * dir,
range,silence,unity);
\
for (c = 0; c < channels; c++, k++) \
d[k] = s[k] * gain; \
} \
...
...
@@ -189,20 +196,77 @@ FADE(flt, float)
FADE
(
s16
,
int16_t
)
FADE
(
s32
,
int32_t
)
#define SCALE_PLANAR(name, type) \
static void scale_samples_## name ##p(uint8_t **dst, uint8_t * const *src, \
int nb_samples, int channels, \
double gain) \
{ \
int i, c; \
\
for (i = 0; i < nb_samples; i++) { \
for (c = 0; c < channels; c++) { \
type *d = (type *)dst[c]; \
const type *s = (type *)src[c]; \
\
d[i] = s[i] * gain; \
} \
} \
}
#define SCALE(name, type) \
static void scale_samples_## name (uint8_t **dst, uint8_t * const *src, \
int nb_samples, int channels, double gain)\
{ \
type *d = (type *)dst[0]; \
const type *s = (type *)src[0]; \
int i, c, k = 0; \
\
for (i = 0; i < nb_samples; i++) { \
for (c = 0; c < channels; c++, k++) \
d[k] = s[k] * gain; \
} \
}
SCALE_PLANAR
(
dbl
,
double
)
SCALE_PLANAR
(
flt
,
float
)
SCALE_PLANAR
(
s16
,
int16_t
)
SCALE_PLANAR
(
s32
,
int32_t
)
SCALE
(
dbl
,
double
)
SCALE
(
flt
,
float
)
SCALE
(
s16
,
int16_t
)
SCALE
(
s32
,
int32_t
)
static
int
config_output
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
ctx
=
outlink
->
src
;
AudioFadeContext
*
s
=
ctx
->
priv
;
switch
(
outlink
->
format
)
{
case
AV_SAMPLE_FMT_DBL
:
s
->
fade_samples
=
fade_samples_dbl
;
break
;
case
AV_SAMPLE_FMT_DBLP
:
s
->
fade_samples
=
fade_samples_dblp
;
break
;
case
AV_SAMPLE_FMT_FLT
:
s
->
fade_samples
=
fade_samples_flt
;
break
;
case
AV_SAMPLE_FMT_FLTP
:
s
->
fade_samples
=
fade_samples_fltp
;
break
;
case
AV_SAMPLE_FMT_S16
:
s
->
fade_samples
=
fade_samples_s16
;
break
;
case
AV_SAMPLE_FMT_S16P
:
s
->
fade_samples
=
fade_samples_s16p
;
break
;
case
AV_SAMPLE_FMT_S32
:
s
->
fade_samples
=
fade_samples_s32
;
break
;
case
AV_SAMPLE_FMT_S32P
:
s
->
fade_samples
=
fade_samples_s32p
;
break
;
case
AV_SAMPLE_FMT_DBL
:
s
->
fade_samples
=
fade_samples_dbl
;
s
->
scale_samples
=
scale_samples_dbl
;
break
;
case
AV_SAMPLE_FMT_DBLP
:
s
->
fade_samples
=
fade_samples_dblp
;
s
->
scale_samples
=
scale_samples_dblp
;
break
;
case
AV_SAMPLE_FMT_FLT
:
s
->
fade_samples
=
fade_samples_flt
;
s
->
scale_samples
=
scale_samples_flt
;
break
;
case
AV_SAMPLE_FMT_FLTP
:
s
->
fade_samples
=
fade_samples_fltp
;
s
->
scale_samples
=
scale_samples_fltp
;
break
;
case
AV_SAMPLE_FMT_S16
:
s
->
fade_samples
=
fade_samples_s16
;
s
->
scale_samples
=
scale_samples_s16
;
break
;
case
AV_SAMPLE_FMT_S16P
:
s
->
fade_samples
=
fade_samples_s16p
;
s
->
scale_samples
=
scale_samples_s16p
;
break
;
case
AV_SAMPLE_FMT_S32
:
s
->
fade_samples
=
fade_samples_s32
;
s
->
scale_samples
=
scale_samples_s32
;
break
;
case
AV_SAMPLE_FMT_S32P
:
s
->
fade_samples
=
fade_samples_s32p
;
s
->
scale_samples
=
scale_samples_s32p
;
break
;
}
if
(
s
->
duration
)
...
...
@@ -252,6 +316,8 @@ static const AVOption afade_options[] = {
{
"losi"
,
"logistic sigmoid"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
LOSI
},
0
,
0
,
TFLAGS
,
"curve"
},
{
"sinc"
,
"sine cardinal function"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
SINC
},
0
,
0
,
TFLAGS
,
"curve"
},
{
"isinc"
,
"inverted sine cardinal function"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
ISINC
},
0
,
0
,
TFLAGS
,
"curve"
},
{
"silence"
,
"set the silence gain"
,
OFFSET
(
silence
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
0
},
0
,
1
,
TFLAGS
},
{
"unity"
,
"set the unity gain"
,
OFFSET
(
unity
),
AV_OPT_TYPE_DOUBLE
,
{.
dbl
=
1
},
0
,
1
,
TFLAGS
},
{
NULL
}
};
...
...
@@ -275,8 +341,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
AVFrame
*
out_buf
;
int64_t
cur_sample
=
av_rescale_q
(
buf
->
pts
,
inlink
->
time_base
,
(
AVRational
){
1
,
inlink
->
sample_rate
});
if
((
!
s
->
type
&&
(
s
->
start_sample
+
s
->
nb_samples
<
cur_sample
))
||
(
s
->
type
&&
(
cur_sample
+
nb_samples
<
s
->
start_sample
)))
if
(
s
->
unity
==
1
.
0
&&
((
!
s
->
type
&&
(
s
->
start_sample
+
s
->
nb_samples
<
cur_sample
))
||
(
s
->
type
&&
(
cur_sample
+
nb_samples
<
s
->
start_sample
))))
return
ff_filter_frame
(
outlink
,
buf
);
if
(
av_frame_is_writable
(
buf
))
{
...
...
@@ -290,8 +357,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
if
((
!
s
->
type
&&
(
cur_sample
+
nb_samples
<
s
->
start_sample
))
||
(
s
->
type
&&
(
s
->
start_sample
+
s
->
nb_samples
<
cur_sample
)))
{
av_samples_set_silence
(
out_buf
->
extended_data
,
0
,
nb_samples
,
out_buf
->
ch_layout
.
nb_channels
,
out_buf
->
format
);
if
(
s
->
silence
==
0
.)
{
av_samples_set_silence
(
out_buf
->
extended_data
,
0
,
nb_samples
,
out_buf
->
ch_layout
.
nb_channels
,
out_buf
->
format
);
}
else
{
s
->
scale_samples
(
out_buf
->
extended_data
,
buf
->
extended_data
,
nb_samples
,
buf
->
ch_layout
.
nb_channels
,
s
->
silence
);
}
}
else
if
((
s
->
type
&&
(
cur_sample
+
nb_samples
<
s
->
start_sample
))
||
(
!
s
->
type
&&
(
s
->
start_sample
+
s
->
nb_samples
<
cur_sample
)))
{
s
->
scale_samples
(
out_buf
->
extended_data
,
buf
->
extended_data
,
nb_samples
,
buf
->
ch_layout
.
nb_channels
,
s
->
unity
);
}
else
{
int64_t
start
;
...
...
@@ -303,7 +381,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
s
->
fade_samples
(
out_buf
->
extended_data
,
buf
->
extended_data
,
nb_samples
,
buf
->
ch_layout
.
nb_channels
,
s
->
type
?
-
1
:
1
,
start
,
s
->
nb_samples
,
s
->
curve
);
s
->
nb_samples
,
s
->
curve
,
s
->
silence
,
s
->
unity
);
}
if
(
buf
!=
out_buf
)
...
...
@@ -402,8 +480,8 @@ static void crossfade_samples_## name ##p(uint8_t **dst, uint8_t * const *cf0, \
int i, c; \
\
for (i = 0; i < nb_samples; i++) { \
double gain0 = fade_gain(curve0, nb_samples - 1 - i, nb_samples
);
\
double gain1 = fade_gain(curve1, i, nb_samples
);
\
double gain0 = fade_gain(curve0, nb_samples - 1 - i, nb_samples
,0.,1.);
\
double gain1 = fade_gain(curve1, i, nb_samples
, 0., 1.);
\
for (c = 0; c < channels; c++) { \
type *d = (type *)dst[c]; \
const type *s0 = (type *)cf0[c]; \
...
...
@@ -426,8 +504,8 @@ static void crossfade_samples_## name (uint8_t **dst, uint8_t * const *cf0, \
int i, c, k = 0; \
\
for (i = 0; i < nb_samples; i++) { \
double gain0 = fade_gain(curve0, nb_samples - 1
- i, nb_samples);
\
double gain1 = fade_gain(curve1, i, nb_samples
);
\
double gain0 = fade_gain(curve0, nb_samples - 1
-i,nb_samples,0.,1.);
\
double gain1 = fade_gain(curve1, i, nb_samples
, 0., 1.);
\
for (c = 0; c < channels; c++, k++) \
d[k] = s0[k] * gain0 + s1[k] * gain1; \
} \
...
...
@@ -525,7 +603,7 @@ static int activate(AVFilterContext *ctx)
}
s
->
fade_samples
(
out
->
extended_data
,
cf
[
0
]
->
extended_data
,
s
->
nb_samples
,
outlink
->
ch_layout
.
nb_channels
,
-
1
,
s
->
nb_samples
-
1
,
s
->
nb_samples
,
s
->
curve
);
outlink
->
ch_layout
.
nb_channels
,
-
1
,
s
->
nb_samples
-
1
,
s
->
nb_samples
,
s
->
curve
,
0
.,
1
.
);
out
->
pts
=
s
->
pts
;
s
->
pts
+=
av_rescale_q
(
s
->
nb_samples
,
(
AVRational
){
1
,
outlink
->
sample_rate
},
outlink
->
time_base
);
...
...
@@ -545,7 +623,7 @@ static int activate(AVFilterContext *ctx)
}
s
->
fade_samples
(
out
->
extended_data
,
cf
[
1
]
->
extended_data
,
s
->
nb_samples
,
outlink
->
ch_layout
.
nb_channels
,
1
,
0
,
s
->
nb_samples
,
s
->
curve2
);
outlink
->
ch_layout
.
nb_channels
,
1
,
0
,
s
->
nb_samples
,
s
->
curve2
,
0
.,
1
.
);
out
->
pts
=
s
->
pts
;
s
->
pts
+=
av_rescale_q
(
s
->
nb_samples
,
(
AVRational
){
1
,
outlink
->
sample_rate
},
outlink
->
time_base
);
...
...
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