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
fab18639
Commit
fab18639
authored
Jun 03, 2017
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter/af_surround: add support for some upmixing of 3.0, 2.1 and 5.1 channel layout
Signed-off-by:
Paul B Mahol
<
onemda@gmail.com
>
parent
88050481
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
462 additions
and
63 deletions
+462
-63
filters.texi
doc/filters.texi
+7
-1
af_surround.c
libavfilter/af_surround.c
+455
-62
No files found.
doc/filters.texi
View file @
fab18639
...
@@ -3795,7 +3795,7 @@ Set level of input signal of original channel. Default is 0.8.
...
@@ -3795,7 +3795,7 @@ Set level of input signal of original channel. Default is 0.8.
@section surround
@section surround
Apply audio surround upmix filter.
Apply audio surround upmix filter.
This filter allows to produce multichannel output from
stereo
audio stream.
This filter allows to produce multichannel output from audio stream.
The filter accepts the following options:
The filter accepts the following options:
...
@@ -3806,6 +3806,12 @@ Set output channel layout. By default, this is @var{5.1}.
...
@@ -3806,6 +3806,12 @@ Set output channel layout. By default, this is @var{5.1}.
See @ref{channel layout syntax,,the Channel Layout section in the ffmpeg-utils(1) manual,ffmpeg-utils}
See @ref{channel layout syntax,,the Channel Layout section in the ffmpeg-utils(1) manual,ffmpeg-utils}
for the required syntax.
for the required syntax.
@item chl_in
Set input channel layout. By default, this is @var{stereo}.
See @ref{channel layout syntax,,the Channel Layout section in the ffmpeg-utils(1) manual,ffmpeg-utils}
for the required syntax.
@item level_in
@item level_in
Set input volume level. By default, this is @var{1}.
Set input volume level. By default, this is @var{1}.
...
...
libavfilter/af_surround.c
View file @
fab18639
...
@@ -30,6 +30,7 @@ typedef struct AudioSurroundContext {
...
@@ -30,6 +30,7 @@ typedef struct AudioSurroundContext {
const
AVClass
*
class
;
const
AVClass
*
class
;
char
*
out_channel_layout_str
;
char
*
out_channel_layout_str
;
char
*
in_channel_layout_str
;
float
level_in
;
float
level_in
;
float
level_out
;
float
level_out
;
int
output_lfe
;
int
output_lfe
;
...
@@ -40,6 +41,7 @@ typedef struct AudioSurroundContext {
...
@@ -40,6 +41,7 @@ typedef struct AudioSurroundContext {
float
highcut
;
float
highcut
;
uint64_t
out_channel_layout
;
uint64_t
out_channel_layout
;
uint64_t
in_channel_layout
;
int
nb_in_channels
;
int
nb_in_channels
;
int
nb_out_channels
;
int
nb_out_channels
;
...
@@ -55,13 +57,41 @@ typedef struct AudioSurroundContext {
...
@@ -55,13 +57,41 @@ typedef struct AudioSurroundContext {
int64_t
pts
;
int64_t
pts
;
void
(
*
upmix
)(
AVFilterContext
*
ctx
,
void
(
*
filter
)(
AVFilterContext
*
ctx
);
float
l_phase
,
void
(
*
upmix_stereo
)(
AVFilterContext
*
ctx
,
float
r_phase
,
float
l_phase
,
float
c_phase
,
float
r_phase
,
float
mag_total
,
float
c_phase
,
float
x
,
float
y
,
float
mag_total
,
int
n
);
float
x
,
float
y
,
int
n
);
void
(
*
upmix_2_1
)(
AVFilterContext
*
ctx
,
float
l_phase
,
float
r_phase
,
float
c_phase
,
float
mag_total
,
float
lfe_im
,
float
lfe_re
,
float
x
,
float
y
,
int
n
);
void
(
*
upmix_3_0
)(
AVFilterContext
*
ctx
,
float
l_phase
,
float
r_phase
,
float
c_mag
,
float
c_phase
,
float
mag_total
,
float
x
,
float
y
,
int
n
);
void
(
*
upmix_5_1
)(
AVFilterContext
*
ctx
,
float
c_re
,
float
c_im
,
float
lfe_re
,
float
lfe_im
,
float
mag_totall
,
float
mag_totalr
,
float
fl_phase
,
float
fr_phase
,
float
bl_phase
,
float
br_phase
,
float
sl_phase
,
float
sr_phase
,
float
xl
,
float
yl
,
float
xr
,
float
yr
,
int
n
);
}
AudioSurroundContext
;
}
AudioSurroundContext
;
static
int
query_formats
(
AVFilterContext
*
ctx
)
static
int
query_formats
(
AVFilterContext
*
ctx
)
...
@@ -88,7 +118,7 @@ static int query_formats(AVFilterContext *ctx)
...
@@ -88,7 +118,7 @@ static int query_formats(AVFilterContext *ctx)
return
ret
;
return
ret
;
layouts
=
NULL
;
layouts
=
NULL
;
ret
=
ff_add_channel_layout
(
&
layouts
,
AV_CH_LAYOUT_STEREO
);
ret
=
ff_add_channel_layout
(
&
layouts
,
s
->
in_channel_layout
);
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
...
@@ -313,6 +343,41 @@ static void upmix_3_1(AVFilterContext *ctx,
...
@@ -313,6 +343,41 @@ static void upmix_3_1(AVFilterContext *ctx,
dstlfe
[
2
*
n
+
1
]
=
lfe_mag
*
sinf
(
c_phase
);
dstlfe
[
2
*
n
+
1
]
=
lfe_mag
*
sinf
(
c_phase
);
}
}
static
void
upmix_3_1_surround
(
AVFilterContext
*
ctx
,
float
l_phase
,
float
r_phase
,
float
c_phase
,
float
c_mag
,
float
mag_total
,
float
x
,
float
y
,
int
n
)
{
AudioSurroundContext
*
s
=
ctx
->
priv
;
float
lfe_mag
,
l_mag
,
r_mag
,
*
dstc
,
*
dstl
,
*
dstr
,
*
dstlfe
;
dstl
=
(
float
*
)
s
->
output
->
extended_data
[
0
];
dstr
=
(
float
*
)
s
->
output
->
extended_data
[
1
];
dstc
=
(
float
*
)
s
->
output
->
extended_data
[
2
];
dstlfe
=
(
float
*
)
s
->
output
->
extended_data
[
3
];
get_lfe
(
s
->
output_lfe
,
n
,
s
->
lowcut
,
s
->
highcut
,
&
lfe_mag
,
&
c_mag
);
l_mag
=
sqrtf
(.
5
f
*
(
x
+
1
.
f
))
*
((
y
+
1
.
f
)
*
.
5
f
)
*
mag_total
;
r_mag
=
sqrtf
(.
5
f
*
(
-
x
+
1
.
f
))
*
((
y
+
1
.
f
)
*
.
5
f
)
*
mag_total
;
dstl
[
2
*
n
]
=
l_mag
*
cosf
(
l_phase
);
dstl
[
2
*
n
+
1
]
=
l_mag
*
sinf
(
l_phase
);
dstr
[
2
*
n
]
=
r_mag
*
cosf
(
r_phase
);
dstr
[
2
*
n
+
1
]
=
r_mag
*
sinf
(
r_phase
);
dstc
[
2
*
n
]
=
c_mag
*
cosf
(
c_phase
);
dstc
[
2
*
n
+
1
]
=
c_mag
*
sinf
(
c_phase
);
dstlfe
[
2
*
n
]
=
lfe_mag
*
cosf
(
c_phase
);
dstlfe
[
2
*
n
+
1
]
=
lfe_mag
*
sinf
(
c_phase
);
}
static
void
upmix_4_0
(
AVFilterContext
*
ctx
,
static
void
upmix_4_0
(
AVFilterContext
*
ctx
,
float
l_phase
,
float
l_phase
,
float
r_phase
,
float
r_phase
,
...
@@ -471,6 +536,98 @@ static void upmix_5_1_back(AVFilterContext *ctx,
...
@@ -471,6 +536,98 @@ static void upmix_5_1_back(AVFilterContext *ctx,
dstrs
[
2
*
n
+
1
]
=
rs_mag
*
sinf
(
r_phase
);
dstrs
[
2
*
n
+
1
]
=
rs_mag
*
sinf
(
r_phase
);
}
}
static
void
upmix_5_1_back_surround
(
AVFilterContext
*
ctx
,
float
l_phase
,
float
r_phase
,
float
c_phase
,
float
c_mag
,
float
mag_total
,
float
x
,
float
y
,
int
n
)
{
AudioSurroundContext
*
s
=
ctx
->
priv
;
float
lfe_mag
,
l_mag
,
r_mag
,
*
dstc
,
*
dstl
,
*
dstr
,
*
dstlfe
;
float
ls_mag
,
rs_mag
,
*
dstls
,
*
dstrs
;
dstl
=
(
float
*
)
s
->
output
->
extended_data
[
0
];
dstr
=
(
float
*
)
s
->
output
->
extended_data
[
1
];
dstc
=
(
float
*
)
s
->
output
->
extended_data
[
2
];
dstlfe
=
(
float
*
)
s
->
output
->
extended_data
[
3
];
dstls
=
(
float
*
)
s
->
output
->
extended_data
[
4
];
dstrs
=
(
float
*
)
s
->
output
->
extended_data
[
5
];
get_lfe
(
s
->
output_lfe
,
n
,
s
->
lowcut
,
s
->
highcut
,
&
lfe_mag
,
&
c_mag
);
l_mag
=
sqrtf
(.
5
f
*
(
x
+
1
.
f
))
*
((
y
+
1
.
f
)
*
.
5
f
)
*
mag_total
;
r_mag
=
sqrtf
(.
5
f
*
(
-
x
+
1
.
f
))
*
((
y
+
1
.
f
)
*
.
5
f
)
*
mag_total
;
ls_mag
=
sqrtf
(.
5
f
*
(
x
+
1
.
f
))
*
(
1
.
f
-
((
y
+
1
.
f
)
*
.
5
f
))
*
mag_total
;
rs_mag
=
sqrtf
(.
5
f
*
(
-
x
+
1
.
f
))
*
(
1
.
f
-
((
y
+
1
.
f
)
*
.
5
f
))
*
mag_total
;
dstl
[
2
*
n
]
=
l_mag
*
cosf
(
l_phase
);
dstl
[
2
*
n
+
1
]
=
l_mag
*
sinf
(
l_phase
);
dstr
[
2
*
n
]
=
r_mag
*
cosf
(
r_phase
);
dstr
[
2
*
n
+
1
]
=
r_mag
*
sinf
(
r_phase
);
dstc
[
2
*
n
]
=
c_mag
*
cosf
(
c_phase
);
dstc
[
2
*
n
+
1
]
=
c_mag
*
sinf
(
c_phase
);
dstlfe
[
2
*
n
]
=
lfe_mag
*
cosf
(
c_phase
);
dstlfe
[
2
*
n
+
1
]
=
lfe_mag
*
sinf
(
c_phase
);
dstls
[
2
*
n
]
=
ls_mag
*
cosf
(
l_phase
);
dstls
[
2
*
n
+
1
]
=
ls_mag
*
sinf
(
l_phase
);
dstrs
[
2
*
n
]
=
rs_mag
*
cosf
(
r_phase
);
dstrs
[
2
*
n
+
1
]
=
rs_mag
*
sinf
(
r_phase
);
}
static
void
upmix_5_1_back_2_1
(
AVFilterContext
*
ctx
,
float
l_phase
,
float
r_phase
,
float
c_phase
,
float
mag_total
,
float
lfe_re
,
float
lfe_im
,
float
x
,
float
y
,
int
n
)
{
AudioSurroundContext
*
s
=
ctx
->
priv
;
float
c_mag
,
l_mag
,
r_mag
,
*
dstc
,
*
dstl
,
*
dstr
,
*
dstlfe
;
float
ls_mag
,
rs_mag
,
*
dstls
,
*
dstrs
;
dstl
=
(
float
*
)
s
->
output
->
extended_data
[
0
];
dstr
=
(
float
*
)
s
->
output
->
extended_data
[
1
];
dstc
=
(
float
*
)
s
->
output
->
extended_data
[
2
];
dstlfe
=
(
float
*
)
s
->
output
->
extended_data
[
3
];
dstls
=
(
float
*
)
s
->
output
->
extended_data
[
4
];
dstrs
=
(
float
*
)
s
->
output
->
extended_data
[
5
];
c_mag
=
sqrtf
(
1
.
f
-
fabsf
(
x
))
*
((
y
+
1
.
f
)
*
.
5
f
)
*
mag_total
;
l_mag
=
sqrtf
(.
5
f
*
(
x
+
1
.
f
))
*
((
y
+
1
.
f
)
*
.
5
f
)
*
mag_total
;
r_mag
=
sqrtf
(.
5
f
*
(
-
x
+
1
.
f
))
*
((
y
+
1
.
f
)
*
.
5
f
)
*
mag_total
;
ls_mag
=
sqrtf
(.
5
f
*
(
x
+
1
.
f
))
*
(
1
.
f
-
((
y
+
1
.
f
)
*
.
5
f
))
*
mag_total
;
rs_mag
=
sqrtf
(.
5
f
*
(
-
x
+
1
.
f
))
*
(
1
.
f
-
((
y
+
1
.
f
)
*
.
5
f
))
*
mag_total
;
dstl
[
2
*
n
]
=
l_mag
*
cosf
(
l_phase
);
dstl
[
2
*
n
+
1
]
=
l_mag
*
sinf
(
l_phase
);
dstr
[
2
*
n
]
=
r_mag
*
cosf
(
r_phase
);
dstr
[
2
*
n
+
1
]
=
r_mag
*
sinf
(
r_phase
);
dstc
[
2
*
n
]
=
c_mag
*
cosf
(
c_phase
);
dstc
[
2
*
n
+
1
]
=
c_mag
*
sinf
(
c_phase
);
dstlfe
[
2
*
n
]
=
lfe_re
;
dstlfe
[
2
*
n
+
1
]
=
lfe_im
;
dstls
[
2
*
n
]
=
ls_mag
*
cosf
(
l_phase
);
dstls
[
2
*
n
+
1
]
=
ls_mag
*
sinf
(
l_phase
);
dstrs
[
2
*
n
]
=
rs_mag
*
cosf
(
r_phase
);
dstrs
[
2
*
n
+
1
]
=
rs_mag
*
sinf
(
r_phase
);
}
static
void
upmix_7_0
(
AVFilterContext
*
ctx
,
static
void
upmix_7_0
(
AVFilterContext
*
ctx
,
float
l_phase
,
float
l_phase
,
float
r_phase
,
float
r_phase
,
...
@@ -577,6 +734,217 @@ static void upmix_7_1(AVFilterContext *ctx,
...
@@ -577,6 +734,217 @@ static void upmix_7_1(AVFilterContext *ctx,
dstrs
[
2
*
n
+
1
]
=
rs_mag
*
sinf
(
r_phase
);
dstrs
[
2
*
n
+
1
]
=
rs_mag
*
sinf
(
r_phase
);
}
}
static
void
upmix_7_1_5_1
(
AVFilterContext
*
ctx
,
float
c_re
,
float
c_im
,
float
lfe_re
,
float
lfe_im
,
float
mag_totall
,
float
mag_totalr
,
float
fl_phase
,
float
fr_phase
,
float
bl_phase
,
float
br_phase
,
float
sl_phase
,
float
sr_phase
,
float
xl
,
float
yl
,
float
xr
,
float
yr
,
int
n
)
{
float
fl_mag
,
fr_mag
,
ls_mag
,
rs_mag
,
lb_mag
,
rb_mag
;
float
*
dstc
,
*
dstl
,
*
dstr
,
*
dstls
,
*
dstrs
,
*
dstlb
,
*
dstrb
,
*
dstlfe
;
AudioSurroundContext
*
s
=
ctx
->
priv
;
dstl
=
(
float
*
)
s
->
output
->
extended_data
[
0
];
dstr
=
(
float
*
)
s
->
output
->
extended_data
[
1
];
dstc
=
(
float
*
)
s
->
output
->
extended_data
[
2
];
dstlfe
=
(
float
*
)
s
->
output
->
extended_data
[
3
];
dstlb
=
(
float
*
)
s
->
output
->
extended_data
[
4
];
dstrb
=
(
float
*
)
s
->
output
->
extended_data
[
5
];
dstls
=
(
float
*
)
s
->
output
->
extended_data
[
6
];
dstrs
=
(
float
*
)
s
->
output
->
extended_data
[
7
];
fl_mag
=
sqrtf
(.
5
f
*
(
xl
+
1
.
f
))
*
((
yl
+
1
.
f
)
*
.
5
f
)
*
mag_totall
;
fr_mag
=
sqrtf
(.
5
f
*
(
xr
+
1
.
f
))
*
((
yr
+
1
.
f
)
*
.
5
f
)
*
mag_totalr
;
lb_mag
=
sqrtf
(.
5
f
*
(
-
xl
+
1
.
f
))
*
((
yl
+
1
.
f
)
*
.
5
f
)
*
mag_totall
;
rb_mag
=
sqrtf
(.
5
f
*
(
-
xr
+
1
.
f
))
*
((
yr
+
1
.
f
)
*
.
5
f
)
*
mag_totalr
;
ls_mag
=
sqrtf
(
1
.
f
-
fabsf
(
xl
))
*
((
yl
+
1
.
f
)
*
.
5
f
)
*
mag_totall
;
rs_mag
=
sqrtf
(
1
.
f
-
fabsf
(
xr
))
*
((
yr
+
1
.
f
)
*
.
5
f
)
*
mag_totalr
;
dstl
[
2
*
n
]
=
fl_mag
*
cosf
(
fl_phase
);
dstl
[
2
*
n
+
1
]
=
fl_mag
*
sinf
(
fl_phase
);
dstr
[
2
*
n
]
=
fr_mag
*
cosf
(
fr_phase
);
dstr
[
2
*
n
+
1
]
=
fr_mag
*
sinf
(
fr_phase
);
dstc
[
2
*
n
]
=
c_re
;
dstc
[
2
*
n
+
1
]
=
c_im
;
dstlfe
[
2
*
n
]
=
lfe_re
;
dstlfe
[
2
*
n
+
1
]
=
lfe_im
;
dstlb
[
2
*
n
]
=
lb_mag
*
cosf
(
bl_phase
);
dstlb
[
2
*
n
+
1
]
=
lb_mag
*
sinf
(
bl_phase
);
dstrb
[
2
*
n
]
=
rb_mag
*
cosf
(
br_phase
);
dstrb
[
2
*
n
+
1
]
=
rb_mag
*
sinf
(
br_phase
);
dstls
[
2
*
n
]
=
ls_mag
*
cosf
(
sl_phase
);
dstls
[
2
*
n
+
1
]
=
ls_mag
*
sinf
(
sl_phase
);
dstrs
[
2
*
n
]
=
rs_mag
*
cosf
(
sr_phase
);
dstrs
[
2
*
n
+
1
]
=
rs_mag
*
sinf
(
sr_phase
);
}
static
void
filter_stereo
(
AVFilterContext
*
ctx
)
{
AudioSurroundContext
*
s
=
ctx
->
priv
;
float
*
srcl
,
*
srcr
;
int
n
;
srcl
=
(
float
*
)
s
->
input
->
extended_data
[
0
];
srcr
=
(
float
*
)
s
->
input
->
extended_data
[
1
];
for
(
n
=
0
;
n
<
s
->
buf_size
;
n
++
)
{
float
l_re
=
srcl
[
2
*
n
],
r_re
=
srcr
[
2
*
n
];
float
l_im
=
srcl
[
2
*
n
+
1
],
r_im
=
srcr
[
2
*
n
+
1
];
float
c_phase
=
atan2f
(
l_im
+
r_im
,
l_re
+
r_re
);
float
l_mag
=
hypotf
(
l_re
,
l_im
);
float
r_mag
=
hypotf
(
r_re
,
r_im
);
float
l_phase
=
atan2f
(
l_im
,
l_re
);
float
r_phase
=
atan2f
(
r_im
,
r_re
);
float
phase_dif
=
fabsf
(
l_phase
-
r_phase
);
float
mag_dif
=
(
l_mag
-
r_mag
)
/
(
l_mag
+
r_mag
);
float
mag_total
=
hypotf
(
l_mag
,
r_mag
);
float
x
,
y
;
if
(
phase_dif
>
M_PI
)
phase_dif
=
2
*
M_PI
-
phase_dif
;
stereo_position
(
mag_dif
,
phase_dif
,
&
x
,
&
y
);
s
->
upmix_stereo
(
ctx
,
l_phase
,
r_phase
,
c_phase
,
mag_total
,
x
,
y
,
n
);
}
}
static
void
filter_surround
(
AVFilterContext
*
ctx
)
{
AudioSurroundContext
*
s
=
ctx
->
priv
;
float
*
srcl
,
*
srcr
,
*
srcc
;
int
n
;
srcl
=
(
float
*
)
s
->
input
->
extended_data
[
0
];
srcr
=
(
float
*
)
s
->
input
->
extended_data
[
1
];
srcc
=
(
float
*
)
s
->
input
->
extended_data
[
2
];
for
(
n
=
0
;
n
<
s
->
buf_size
;
n
++
)
{
float
l_re
=
srcl
[
2
*
n
],
r_re
=
srcr
[
2
*
n
];
float
l_im
=
srcl
[
2
*
n
+
1
],
r_im
=
srcr
[
2
*
n
+
1
];
float
c_re
=
srcc
[
2
*
n
],
c_im
=
srcc
[
2
*
n
+
1
];
float
c_mag
=
hypotf
(
c_re
,
c_im
);
float
c_phase
=
atan2f
(
c_im
,
c_re
);
float
l_mag
=
hypotf
(
l_re
,
l_im
);
float
r_mag
=
hypotf
(
r_re
,
r_im
);
float
l_phase
=
atan2f
(
l_im
,
l_re
);
float
r_phase
=
atan2f
(
r_im
,
r_re
);
float
phase_dif
=
fabsf
(
l_phase
-
r_phase
);
float
mag_dif
=
(
l_mag
-
r_mag
)
/
(
l_mag
+
r_mag
);
float
mag_total
=
hypotf
(
l_mag
,
r_mag
);
float
x
,
y
;
if
(
phase_dif
>
M_PI
)
phase_dif
=
2
*
M_PI
-
phase_dif
;
stereo_position
(
mag_dif
,
phase_dif
,
&
x
,
&
y
);
s
->
upmix_3_0
(
ctx
,
l_phase
,
r_phase
,
c_phase
,
c_mag
,
mag_total
,
x
,
y
,
n
);
}
}
static
void
filter_2_1
(
AVFilterContext
*
ctx
)
{
AudioSurroundContext
*
s
=
ctx
->
priv
;
float
*
srcl
,
*
srcr
,
*
srclfe
;
int
n
;
srcl
=
(
float
*
)
s
->
input
->
extended_data
[
0
];
srcr
=
(
float
*
)
s
->
input
->
extended_data
[
1
];
srclfe
=
(
float
*
)
s
->
input
->
extended_data
[
2
];
for
(
n
=
0
;
n
<
s
->
buf_size
;
n
++
)
{
float
l_re
=
srcl
[
2
*
n
],
r_re
=
srcr
[
2
*
n
];
float
l_im
=
srcl
[
2
*
n
+
1
],
r_im
=
srcr
[
2
*
n
+
1
];
float
lfe_re
=
srclfe
[
2
*
n
],
lfe_im
=
srclfe
[
2
*
n
+
1
];
float
c_phase
=
atan2f
(
l_im
+
r_im
,
l_re
+
r_re
);
float
l_mag
=
hypotf
(
l_re
,
l_im
);
float
r_mag
=
hypotf
(
r_re
,
r_im
);
float
l_phase
=
atan2f
(
l_im
,
l_re
);
float
r_phase
=
atan2f
(
r_im
,
r_re
);
float
phase_dif
=
fabsf
(
l_phase
-
r_phase
);
float
mag_dif
=
(
l_mag
-
r_mag
)
/
(
l_mag
+
r_mag
);
float
mag_total
=
hypotf
(
l_mag
,
r_mag
);
float
x
,
y
;
if
(
phase_dif
>
M_PI
)
phase_dif
=
2
*
M_PI
-
phase_dif
;
stereo_position
(
mag_dif
,
phase_dif
,
&
x
,
&
y
);
s
->
upmix_2_1
(
ctx
,
l_phase
,
r_phase
,
c_phase
,
mag_total
,
lfe_re
,
lfe_im
,
x
,
y
,
n
);
}
}
static
void
filter_5_1_back
(
AVFilterContext
*
ctx
)
{
AudioSurroundContext
*
s
=
ctx
->
priv
;
float
*
srcl
,
*
srcr
,
*
srcc
,
*
srclfe
,
*
srcbl
,
*
srcbr
;
int
n
;
srcl
=
(
float
*
)
s
->
input
->
extended_data
[
0
];
srcr
=
(
float
*
)
s
->
input
->
extended_data
[
1
];
srcc
=
(
float
*
)
s
->
input
->
extended_data
[
2
];
srclfe
=
(
float
*
)
s
->
input
->
extended_data
[
3
];
srcbl
=
(
float
*
)
s
->
input
->
extended_data
[
4
];
srcbr
=
(
float
*
)
s
->
input
->
extended_data
[
5
];
for
(
n
=
0
;
n
<
s
->
buf_size
;
n
++
)
{
float
fl_re
=
srcl
[
2
*
n
],
fr_re
=
srcr
[
2
*
n
];
float
fl_im
=
srcl
[
2
*
n
+
1
],
fr_im
=
srcr
[
2
*
n
+
1
];
float
c_re
=
srcc
[
2
*
n
],
c_im
=
srcc
[
2
*
n
+
1
];
float
lfe_re
=
srclfe
[
2
*
n
],
lfe_im
=
srclfe
[
2
*
n
+
1
];
float
bl_re
=
srcbl
[
2
*
n
],
bl_im
=
srcbl
[
2
*
n
+
1
];
float
br_re
=
srcbr
[
2
*
n
],
br_im
=
srcbr
[
2
*
n
+
1
];
float
fl_mag
=
hypotf
(
fl_re
,
fl_im
);
float
fr_mag
=
hypotf
(
fr_re
,
fr_im
);
float
fl_phase
=
atan2f
(
fl_im
,
fl_re
);
float
fr_phase
=
atan2f
(
fr_im
,
fr_re
);
float
bl_mag
=
hypotf
(
bl_re
,
bl_im
);
float
br_mag
=
hypotf
(
br_re
,
br_im
);
float
bl_phase
=
atan2f
(
bl_im
,
bl_re
);
float
br_phase
=
atan2f
(
br_im
,
br_re
);
float
phase_difl
=
fabsf
(
fl_phase
-
bl_phase
);
float
phase_difr
=
fabsf
(
fr_phase
-
br_phase
);
float
mag_difl
=
(
fl_mag
-
bl_mag
)
/
(
fl_mag
+
bl_mag
);
float
mag_difr
=
(
fr_mag
-
br_mag
)
/
(
fr_mag
+
br_mag
);
float
mag_totall
=
hypotf
(
fl_mag
,
bl_mag
);
float
mag_totalr
=
hypotf
(
fr_mag
,
br_mag
);
float
sl_phase
=
atan2f
(
fl_im
+
bl_im
,
fl_re
+
bl_re
);
float
sr_phase
=
atan2f
(
fr_im
+
br_im
,
fr_re
+
br_re
);
float
xl
,
yl
;
float
xr
,
yr
;
if
(
phase_difl
>
M_PI
)
phase_difl
=
2
*
M_PI
-
phase_difl
;
if
(
phase_difr
>
M_PI
)
phase_difr
=
2
*
M_PI
-
phase_difr
;
stereo_position
(
mag_difl
,
phase_difl
,
&
xl
,
&
yl
);
stereo_position
(
mag_difr
,
phase_difr
,
&
xr
,
&
yr
);
s
->
upmix_5_1
(
ctx
,
c_re
,
c_im
,
lfe_re
,
lfe_im
,
mag_totall
,
mag_totalr
,
fl_phase
,
fr_phase
,
bl_phase
,
br_phase
,
sl_phase
,
sr_phase
,
xl
,
yl
,
xr
,
yr
,
n
);
}
}
static
int
init
(
AVFilterContext
*
ctx
)
static
int
init
(
AVFilterContext
*
ctx
)
{
{
AudioSurroundContext
*
s
=
ctx
->
priv
;
AudioSurroundContext
*
s
=
ctx
->
priv
;
...
@@ -584,54 +952,101 @@ static int init(AVFilterContext *ctx)
...
@@ -584,54 +952,101 @@ static int init(AVFilterContext *ctx)
int
i
;
int
i
;
if
(
!
(
s
->
out_channel_layout
=
av_get_channel_layout
(
s
->
out_channel_layout_str
)))
{
if
(
!
(
s
->
out_channel_layout
=
av_get_channel_layout
(
s
->
out_channel_layout_str
)))
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error parsing channel layout '%s'.
\n
"
,
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error parsing
output
channel layout '%s'.
\n
"
,
s
->
out_channel_layout_str
);
s
->
out_channel_layout_str
);
return
AVERROR
(
EINVAL
);
return
AVERROR
(
EINVAL
);
}
}
if
(
!
(
s
->
in_channel_layout
=
av_get_channel_layout
(
s
->
in_channel_layout_str
)))
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Error parsing input channel layout '%s'.
\n
"
,
s
->
in_channel_layout_str
);
return
AVERROR
(
EINVAL
);
}
if
(
s
->
lowcutf
>=
s
->
highcutf
)
{
if
(
s
->
lowcutf
>=
s
->
highcutf
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Low cut-off '%d' should be less than high cut-off '%d'.
\n
"
,
av_log
(
ctx
,
AV_LOG_ERROR
,
"Low cut-off '%d' should be less than high cut-off '%d'.
\n
"
,
s
->
lowcutf
,
s
->
highcutf
);
s
->
lowcutf
,
s
->
highcutf
);
return
AVERROR
(
EINVAL
);
return
AVERROR
(
EINVAL
);
}
}
switch
(
s
->
out_channel_layout
)
{
switch
(
s
->
in_channel_layout
)
{
case
AV_CH_LAYOUT_MONO
:
s
->
upmix
=
upmix_1_0
;
break
;
case
AV_CH_LAYOUT_STEREO
:
case
AV_CH_LAYOUT_STEREO
:
s
->
upmix
=
upmix_stereo
;
s
->
filter
=
filter_stereo
;
switch
(
s
->
out_channel_layout
)
{
case
AV_CH_LAYOUT_MONO
:
s
->
upmix_stereo
=
upmix_1_0
;
break
;
case
AV_CH_LAYOUT_STEREO
:
s
->
upmix_stereo
=
upmix_stereo
;
break
;
case
AV_CH_LAYOUT_2POINT1
:
s
->
upmix_stereo
=
upmix_2_1
;
break
;
case
AV_CH_LAYOUT_SURROUND
:
s
->
upmix_stereo
=
upmix_3_0
;
break
;
case
AV_CH_LAYOUT_3POINT1
:
s
->
upmix_stereo
=
upmix_3_1
;
break
;
case
AV_CH_LAYOUT_4POINT0
:
s
->
upmix_stereo
=
upmix_4_0
;
break
;
case
AV_CH_LAYOUT_4POINT1
:
s
->
upmix_stereo
=
upmix_4_1
;
break
;
case
AV_CH_LAYOUT_5POINT0_BACK
:
s
->
upmix_stereo
=
upmix_5_0_back
;
break
;
case
AV_CH_LAYOUT_5POINT1_BACK
:
s
->
upmix_stereo
=
upmix_5_1_back
;
break
;
case
AV_CH_LAYOUT_7POINT0
:
s
->
upmix_stereo
=
upmix_7_0
;
break
;
case
AV_CH_LAYOUT_7POINT1
:
s
->
upmix_stereo
=
upmix_7_1
;
break
;
default:
goto
fail
;
}
break
;
break
;
case
AV_CH_LAYOUT_2POINT1
:
case
AV_CH_LAYOUT_2POINT1
:
s
->
upmix
=
upmix_2_1
;
s
->
filter
=
filter_2_1
;
switch
(
s
->
out_channel_layout
)
{
case
AV_CH_LAYOUT_5POINT1_BACK
:
s
->
upmix_2_1
=
upmix_5_1_back_2_1
;
break
;
default:
goto
fail
;
}
break
;
break
;
case
AV_CH_LAYOUT_SURROUND
:
case
AV_CH_LAYOUT_SURROUND
:
s
->
upmix
=
upmix_3_0
;
s
->
filter
=
filter_surround
;
break
;
switch
(
s
->
out_channel_layout
)
{
case
AV_CH_LAYOUT_3POINT1
:
case
AV_CH_LAYOUT_3POINT1
:
s
->
upmix
=
upmix_3_1
;
s
->
upmix_3_0
=
upmix_3_1_surround
;
break
;
break
;
case
AV_CH_LAYOUT_4POINT0
:
case
AV_CH_LAYOUT_5POINT1_BACK
:
s
->
upmix
=
upmix_4_0
;
s
->
upmix_3_0
=
upmix_5_1_back_surround
;
break
;
break
;
case
AV_CH_LAYOUT_4POINT1
:
default:
s
->
upmix
=
upmix_4_1
;
goto
fail
;
break
;
}
case
AV_CH_LAYOUT_5POINT0_BACK
:
s
->
upmix
=
upmix_5_0_back
;
break
;
break
;
case
AV_CH_LAYOUT_5POINT1_BACK
:
case
AV_CH_LAYOUT_5POINT1_BACK
:
s
->
upmix
=
upmix_5_1_back
;
s
->
filter
=
filter_5_1_back
;
break
;
switch
(
s
->
out_channel_layout
)
{
case
AV_CH_LAYOUT_7POINT0
:
case
AV_CH_LAYOUT_7POINT1
:
s
->
upmix
=
upmix_7_0
;
s
->
upmix_5_1
=
upmix_7_1_5_1
;
break
;
break
;
case
AV_CH_LAYOUT_7POINT1
:
default:
s
->
upmix
=
upmix_7_1
;
goto
fail
;
}
break
;
break
;
default:
default:
av_log
(
ctx
,
AV_LOG_ERROR
,
"Unsupported output channel layout '%s'.
\n
"
,
fail:
s
->
out_channel_layout_str
);
av_log
(
ctx
,
AV_LOG_ERROR
,
"Unsupported upmix: '%s' -> '%s'.
\n
"
,
s
->
in_channel_layout_str
,
s
->
out_channel_layout_str
);
return
AVERROR
(
EINVAL
);
return
AVERROR
(
EINVAL
);
}
}
...
@@ -714,9 +1129,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
...
@@ -714,9 +1129,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
av_frame_free
(
&
in
);
av_frame_free
(
&
in
);
while
(
av_audio_fifo_size
(
s
->
fifo
)
>=
s
->
buf_size
)
{
while
(
av_audio_fifo_size
(
s
->
fifo
)
>=
s
->
buf_size
)
{
float
*
srcl
,
*
srcr
;
AVFrame
*
out
;
AVFrame
*
out
;
int
n
,
ret
;
int
ret
;
ret
=
av_audio_fifo_peek
(
s
->
fifo
,
(
void
**
)
s
->
input
->
extended_data
,
s
->
buf_size
);
ret
=
av_audio_fifo_peek
(
s
->
fifo
,
(
void
**
)
s
->
input
->
extended_data
,
s
->
buf_size
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
@@ -724,29 +1138,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
...
@@ -724,29 +1138,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
ctx
->
internal
->
execute
(
ctx
,
fft_channel
,
NULL
,
NULL
,
inlink
->
channels
);
ctx
->
internal
->
execute
(
ctx
,
fft_channel
,
NULL
,
NULL
,
inlink
->
channels
);
srcl
=
(
float
*
)
s
->
input
->
extended_data
[
0
];
s
->
filter
(
ctx
);
srcr
=
(
float
*
)
s
->
input
->
extended_data
[
1
];
for
(
n
=
0
;
n
<
s
->
buf_size
;
n
++
)
{
float
l_re
=
srcl
[
2
*
n
],
r_re
=
srcr
[
2
*
n
];
float
l_im
=
srcl
[
2
*
n
+
1
],
r_im
=
srcr
[
2
*
n
+
1
];
float
c_phase
=
atan2f
(
l_im
+
r_im
,
l_re
+
r_re
);
float
l_mag
=
hypotf
(
l_re
,
l_im
);
float
r_mag
=
hypotf
(
r_re
,
r_im
);
float
l_phase
=
atan2f
(
l_im
,
l_re
);
float
r_phase
=
atan2f
(
r_im
,
r_re
);
float
phase_dif
=
fabsf
(
l_phase
-
r_phase
);
float
mag_dif
=
(
l_mag
-
r_mag
)
/
(
l_mag
+
r_mag
);
float
mag_total
=
hypotf
(
l_mag
,
r_mag
);
float
x
,
y
;
if
(
phase_dif
>
M_PI
)
phase_dif
=
2
*
M_PI
-
phase_dif
;
stereo_position
(
mag_dif
,
phase_dif
,
&
x
,
&
y
);
s
->
upmix
(
ctx
,
l_phase
,
r_phase
,
c_phase
,
mag_total
,
x
,
y
,
n
);
}
out
=
ff_get_audio_buffer
(
outlink
,
s
->
hop_size
);
out
=
ff_get_audio_buffer
(
outlink
,
s
->
hop_size
);
if
(
!
out
)
if
(
!
out
)
...
@@ -792,6 +1184,7 @@ static av_cold void uninit(AVFilterContext *ctx)
...
@@ -792,6 +1184,7 @@ static av_cold void uninit(AVFilterContext *ctx)
static
const
AVOption
surround_options
[]
=
{
static
const
AVOption
surround_options
[]
=
{
{
"chl_out"
,
"set output channel layout"
,
OFFSET
(
out_channel_layout_str
),
AV_OPT_TYPE_STRING
,
{.
str
=
"5.1"
},
0
,
0
,
FLAGS
},
{
"chl_out"
,
"set output channel layout"
,
OFFSET
(
out_channel_layout_str
),
AV_OPT_TYPE_STRING
,
{.
str
=
"5.1"
},
0
,
0
,
FLAGS
},
{
"chl_in"
,
"set input channel layout"
,
OFFSET
(
in_channel_layout_str
),
AV_OPT_TYPE_STRING
,
{.
str
=
"stereo"
},
0
,
0
,
FLAGS
},
{
"level_in"
,
"set input level"
,
OFFSET
(
level_in
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
1
},
0
,
10
,
FLAGS
},
{
"level_in"
,
"set input level"
,
OFFSET
(
level_in
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
1
},
0
,
10
,
FLAGS
},
{
"level_out"
,
"set output level"
,
OFFSET
(
level_out
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
1
},
0
,
10
,
FLAGS
},
{
"level_out"
,
"set output level"
,
OFFSET
(
level_out
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
1
},
0
,
10
,
FLAGS
},
{
"lfe"
,
"output LFE"
,
OFFSET
(
output_lfe
),
AV_OPT_TYPE_BOOL
,
{.
i64
=
1
},
0
,
1
,
FLAGS
},
{
"lfe"
,
"output LFE"
,
OFFSET
(
output_lfe
),
AV_OPT_TYPE_BOOL
,
{.
i64
=
1
},
0
,
1
,
FLAGS
},
...
...
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