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
42e45ea8
Commit
42e45ea8
authored
Nov 27, 2023
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter/af_anlms: add double sample format support
parent
ea6817d2
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
194 additions
and
80 deletions
+194
-80
filters.texi
doc/filters.texi
+14
-0
af_anlms.c
libavfilter/af_anlms.c
+39
-80
anlms_template.c
libavfilter/anlms_template.c
+141
-0
No files found.
doc/filters.texi
View file @
42e45ea8
...
...
@@ -2687,6 +2687,20 @@ Pass error signal estimated samples.
Default value is @var{o}.
@end table
@item precision
Set which precision to use when processing samples.
@table @option
@item auto
Auto pick internal sample format depending on other filters.
@item float
Always use single-floating point precision sample format.
@item double
Always use double-floating point precision sample format.
@end table
@end table
@subsection Examples
...
...
libavfilter/af_anlms.c
View file @
42e45ea8
...
...
@@ -26,6 +26,7 @@
#include "audio.h"
#include "avfilter.h"
#include "filters.h"
#include "formats.h"
#include "internal.h"
enum
OutModes
{
...
...
@@ -45,6 +46,7 @@ typedef struct AudioNLMSContext {
float
eps
;
float
leakage
;
int
output_mode
;
int
precision
;
int
kernel_size
;
AVFrame
*
offset
;
...
...
@@ -56,6 +58,8 @@ typedef struct AudioNLMSContext {
int
anlmf
;
int
(
*
filter_channels
)(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
);
AVFloatDSPContext
*
fdsp
;
}
AudioNLMSContext
;
...
...
@@ -74,93 +78,32 @@ static const AVOption anlms_options[] = {
{
"o"
,
"output"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
OUT_MODE
},
0
,
0
,
AT
,
"mode"
},
{
"n"
,
"noise"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
NOISE_MODE
},
0
,
0
,
AT
,
"mode"
},
{
"e"
,
"error"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
ERROR_MODE
},
0
,
0
,
AT
,
"mode"
},
{
"precision"
,
"set processing precision"
,
OFFSET
(
precision
),
AV_OPT_TYPE_INT
,
{.
i64
=
0
},
0
,
2
,
A
,
"precision"
},
{
"auto"
,
"set auto processing precision"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
0
},
0
,
0
,
A
,
"precision"
},
{
"float"
,
"set single-floating point processing precision"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
1
},
0
,
0
,
A
,
"precision"
},
{
"double"
,
"set double-floating point processing precision"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
2
},
0
,
0
,
A
,
"precision"
},
{
NULL
}
};
AVFILTER_DEFINE_CLASS_EXT
(
anlms
,
"anlm(f|s)"
,
anlms_options
);
static
float
fir_sample
(
AudioNLMSContext
*
s
,
float
sample
,
float
*
delay
,
float
*
coeffs
,
float
*
tmp
,
int
*
offset
)
static
int
query_formats
(
AVFilterContext
*
ctx
)
{
const
int
order
=
s
->
order
;
float
output
;
delay
[
*
offset
]
=
sample
;
memcpy
(
tmp
,
coeffs
+
order
-
*
offset
,
order
*
sizeof
(
float
));
output
=
s
->
fdsp
->
scalarproduct_float
(
delay
,
tmp
,
s
->
kernel_size
);
if
(
--
(
*
offset
)
<
0
)
*
offset
=
order
-
1
;
return
output
;
}
static
float
process_sample
(
AudioNLMSContext
*
s
,
float
input
,
float
desired
,
float
*
delay
,
float
*
coeffs
,
float
*
tmp
,
int
*
offsetp
)
{
const
int
order
=
s
->
order
;
const
float
leakage
=
s
->
leakage
;
const
float
mu
=
s
->
mu
;
const
float
a
=
1
.
f
-
leakage
;
float
sum
,
output
,
e
,
norm
,
b
;
int
offset
=
*
offsetp
;
delay
[
offset
+
order
]
=
input
;
output
=
fir_sample
(
s
,
input
,
delay
,
coeffs
,
tmp
,
offsetp
);
e
=
desired
-
output
;
sum
=
s
->
fdsp
->
scalarproduct_float
(
delay
,
delay
,
s
->
kernel_size
);
norm
=
s
->
eps
+
sum
;
b
=
mu
*
e
/
norm
;
if
(
s
->
anlmf
)
b
*=
e
*
e
;
memcpy
(
tmp
,
delay
+
offset
,
order
*
sizeof
(
float
));
s
->
fdsp
->
vector_fmul_scalar
(
coeffs
,
coeffs
,
a
,
s
->
kernel_size
);
AudioNLMSContext
*
s
=
ctx
->
priv
;
static
const
enum
AVSampleFormat
sample_fmts
[
3
][
3
]
=
{
{
AV_SAMPLE_FMT_FLTP
,
AV_SAMPLE_FMT_DBLP
,
AV_SAMPLE_FMT_NONE
},
{
AV_SAMPLE_FMT_FLTP
,
AV_SAMPLE_FMT_NONE
},
{
AV_SAMPLE_FMT_DBLP
,
AV_SAMPLE_FMT_NONE
},
};
int
ret
;
s
->
fdsp
->
vector_fmac_scalar
(
coeffs
,
tmp
,
b
,
s
->
kernel_size
);
if
((
ret
=
ff_set_common_all_channel_counts
(
ctx
))
<
0
)
return
ret
;
memcpy
(
coeffs
+
order
,
coeffs
,
order
*
sizeof
(
float
));
if
((
ret
=
ff_set_common_formats_from_list
(
ctx
,
sample_fmts
[
s
->
precision
]))
<
0
)
return
ret
;
switch
(
s
->
output_mode
)
{
case
IN_MODE
:
output
=
input
;
break
;
case
DESIRED_MODE
:
output
=
desired
;
break
;
case
OUT_MODE
:
output
=
desired
-
output
;
break
;
case
NOISE_MODE
:
output
=
input
-
output
;
break
;
case
ERROR_MODE
:
break
;
}
return
output
;
}
static
int
process_channels
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
AudioNLMSContext
*
s
=
ctx
->
priv
;
AVFrame
*
out
=
arg
;
const
int
start
=
(
out
->
ch_layout
.
nb_channels
*
jobnr
)
/
nb_jobs
;
const
int
end
=
(
out
->
ch_layout
.
nb_channels
*
(
jobnr
+
1
))
/
nb_jobs
;
for
(
int
c
=
start
;
c
<
end
;
c
++
)
{
const
float
*
input
=
(
const
float
*
)
s
->
frame
[
0
]
->
extended_data
[
c
];
const
float
*
desired
=
(
const
float
*
)
s
->
frame
[
1
]
->
extended_data
[
c
];
float
*
delay
=
(
float
*
)
s
->
delay
->
extended_data
[
c
];
float
*
coeffs
=
(
float
*
)
s
->
coeffs
->
extended_data
[
c
];
float
*
tmp
=
(
float
*
)
s
->
tmp
->
extended_data
[
c
];
int
*
offset
=
(
int
*
)
s
->
offset
->
extended_data
[
c
];
float
*
output
=
(
float
*
)
out
->
extended_data
[
c
];
for
(
int
n
=
0
;
n
<
out
->
nb_samples
;
n
++
)
{
output
[
n
]
=
process_sample
(
s
,
input
[
n
],
desired
[
n
],
delay
,
coeffs
,
tmp
,
offset
);
if
(
ctx
->
is_disabled
)
output
[
n
]
=
input
[
n
];
}
}
return
0
;
return
ff_set_common_all_samplerates
(
ctx
);
}
static
int
activate
(
AVFilterContext
*
ctx
)
...
...
@@ -195,7 +138,7 @@ static int activate(AVFilterContext *ctx)
return
AVERROR
(
ENOMEM
);
}
ff_filter_execute
(
ctx
,
process
_channels
,
out
,
NULL
,
ff_filter_execute
(
ctx
,
s
->
filter
_channels
,
out
,
NULL
,
FFMIN
(
ctx
->
outputs
[
0
]
->
ch_layout
.
nb_channels
,
ff_filter_get_nb_threads
(
ctx
)));
out
->
pts
=
s
->
frame
[
0
]
->
pts
;
...
...
@@ -228,6 +171,13 @@ static int activate(AVFilterContext *ctx)
return
0
;
}
#define DEPTH 32
#include "anlms_template.c"
#undef DEPTH
#define DEPTH 64
#include "anlms_template.c"
static
int
config_output
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
ctx
=
outlink
->
src
;
...
...
@@ -247,6 +197,15 @@ static int config_output(AVFilterLink *outlink)
if
(
!
s
->
delay
||
!
s
->
coeffs
||
!
s
->
offset
||
!
s
->
tmp
)
return
AVERROR
(
ENOMEM
);
switch
(
outlink
->
format
)
{
case
AV_SAMPLE_FMT_DBLP
:
s
->
filter_channels
=
filter_channels_double
;
break
;
case
AV_SAMPLE_FMT_FLTP
:
s
->
filter_channels
=
filter_channels_float
;
break
;
}
return
0
;
}
...
...
@@ -317,7 +276,7 @@ const AVFilter ff_af_anlmf = {
.
activate
=
activate
,
FILTER_INPUTS
(
inputs
),
FILTER_OUTPUTS
(
outputs
),
FILTER_
SINGLE_SAMPLEFMT
(
AV_SAMPLE_FMT_FLTP
),
FILTER_
QUERY_FUNC
(
query_formats
),
.
flags
=
AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
|
AVFILTER_FLAG_SLICE_THREADS
,
.
process_command
=
ff_filter_process_command
,
...
...
libavfilter/anlms_template.c
0 → 100644
View file @
42e45ea8
/*
* 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
*/
#undef ONE
#undef ftype
#undef SAMPLE_FORMAT
#if DEPTH == 32
#define SAMPLE_FORMAT float
#define ftype float
#define ONE 1.f
#else
#define SAMPLE_FORMAT double
#define ftype double
#define ONE 1.0
#endif
#define fn3(a,b) a##_##b
#define fn2(a,b) fn3(a,b)
#define fn(a) fn2(a, SAMPLE_FORMAT)
#if DEPTH == 64
static
double
scalarproduct_double
(
const
double
*
v1
,
const
double
*
v2
,
int
len
)
{
double
p
=
0
.
0
;
for
(
int
i
=
0
;
i
<
len
;
i
++
)
p
+=
v1
[
i
]
*
v2
[
i
];
return
p
;
}
#endif
static
ftype
fn
(
fir_sample
)(
AudioNLMSContext
*
s
,
ftype
sample
,
ftype
*
delay
,
ftype
*
coeffs
,
ftype
*
tmp
,
int
*
offset
)
{
const
int
order
=
s
->
order
;
ftype
output
;
delay
[
*
offset
]
=
sample
;
memcpy
(
tmp
,
coeffs
+
order
-
*
offset
,
order
*
sizeof
(
ftype
));
#if DEPTH == 32
output
=
s
->
fdsp
->
scalarproduct_float
(
delay
,
tmp
,
s
->
kernel_size
);
#else
output
=
scalarproduct_double
(
delay
,
tmp
,
s
->
kernel_size
);
#endif
if
(
--
(
*
offset
)
<
0
)
*
offset
=
order
-
1
;
return
output
;
}
static
ftype
fn
(
process_sample
)(
AudioNLMSContext
*
s
,
ftype
input
,
ftype
desired
,
ftype
*
delay
,
ftype
*
coeffs
,
ftype
*
tmp
,
int
*
offsetp
)
{
const
int
order
=
s
->
order
;
const
ftype
leakage
=
s
->
leakage
;
const
ftype
mu
=
s
->
mu
;
const
ftype
a
=
ONE
-
leakage
;
ftype
sum
,
output
,
e
,
norm
,
b
;
int
offset
=
*
offsetp
;
delay
[
offset
+
order
]
=
input
;
output
=
fn
(
fir_sample
)(
s
,
input
,
delay
,
coeffs
,
tmp
,
offsetp
);
e
=
desired
-
output
;
#if DEPTH == 32
sum
=
s
->
fdsp
->
scalarproduct_float
(
delay
,
delay
,
s
->
kernel_size
);
#else
sum
=
scalarproduct_double
(
delay
,
delay
,
s
->
kernel_size
);
#endif
norm
=
s
->
eps
+
sum
;
b
=
mu
*
e
/
norm
;
if
(
s
->
anlmf
)
b
*=
e
*
e
;
memcpy
(
tmp
,
delay
+
offset
,
order
*
sizeof
(
ftype
));
#if DEPTH == 32
s
->
fdsp
->
vector_fmul_scalar
(
coeffs
,
coeffs
,
a
,
s
->
kernel_size
);
s
->
fdsp
->
vector_fmac_scalar
(
coeffs
,
tmp
,
b
,
s
->
kernel_size
);
#else
s
->
fdsp
->
vector_dmul_scalar
(
coeffs
,
coeffs
,
a
,
s
->
kernel_size
);
s
->
fdsp
->
vector_dmac_scalar
(
coeffs
,
tmp
,
b
,
s
->
kernel_size
);
#endif
memcpy
(
coeffs
+
order
,
coeffs
,
order
*
sizeof
(
ftype
));
switch
(
s
->
output_mode
)
{
case
IN_MODE
:
output
=
input
;
break
;
case
DESIRED_MODE
:
output
=
desired
;
break
;
case
OUT_MODE
:
output
=
desired
-
output
;
break
;
case
NOISE_MODE
:
output
=
input
-
output
;
break
;
case
ERROR_MODE
:
break
;
}
return
output
;
}
static
int
fn
(
filter_channels
)(
AVFilterContext
*
ctx
,
void
*
arg
,
int
jobnr
,
int
nb_jobs
)
{
AudioNLMSContext
*
s
=
ctx
->
priv
;
AVFrame
*
out
=
arg
;
const
int
start
=
(
out
->
ch_layout
.
nb_channels
*
jobnr
)
/
nb_jobs
;
const
int
end
=
(
out
->
ch_layout
.
nb_channels
*
(
jobnr
+
1
))
/
nb_jobs
;
for
(
int
c
=
start
;
c
<
end
;
c
++
)
{
const
ftype
*
input
=
(
const
ftype
*
)
s
->
frame
[
0
]
->
extended_data
[
c
];
const
ftype
*
desired
=
(
const
ftype
*
)
s
->
frame
[
1
]
->
extended_data
[
c
];
ftype
*
delay
=
(
ftype
*
)
s
->
delay
->
extended_data
[
c
];
ftype
*
coeffs
=
(
ftype
*
)
s
->
coeffs
->
extended_data
[
c
];
ftype
*
tmp
=
(
ftype
*
)
s
->
tmp
->
extended_data
[
c
];
int
*
offset
=
(
int
*
)
s
->
offset
->
extended_data
[
c
];
ftype
*
output
=
(
ftype
*
)
out
->
extended_data
[
c
];
for
(
int
n
=
0
;
n
<
out
->
nb_samples
;
n
++
)
{
output
[
n
]
=
fn
(
process_sample
)(
s
,
input
[
n
],
desired
[
n
],
delay
,
coeffs
,
tmp
,
offset
);
if
(
ctx
->
is_disabled
)
output
[
n
]
=
input
[
n
];
}
}
return
0
;
}
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