Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小白菜888
Ffmpeg
提交
a55c953e
F
Ffmpeg
项目概览
小白菜888
/
Ffmpeg
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
Ffmpeg
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a55c953e
编写于
3月 28, 2016
作者:
P
Paul B Mahol
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
avfilter/af_sofalizer: allow user to setup custom virtual speakers positions
Signed-off-by:
N
Paul B Mahol
<
onemda@gmail.com
>
上级
f3ec8ac0
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
87 addition
and
0 deletion
+87
-0
doc/filters.texi
doc/filters.texi
+10
-0
libavfilter/af_sofalizer.c
libavfilter/af_sofalizer.c
+77
-0
未找到文件。
doc/filters.texi
浏览文件 @
a55c953e
...
@@ -3220,6 +3220,16 @@ Set processing type. Can be @var{time} or @var{freq}. @var{time} is
...
@@ -3220,6 +3220,16 @@ Set processing type. Can be @var{time} or @var{freq}. @var{time} is
processing audio in time domain which is slow but gives high quality output.
processing audio in time domain which is slow but gives high quality output.
@var{freq} is processing audio in frequency domain which is fast but gives
@var{freq} is processing audio in frequency domain which is fast but gives
mediocre output. Default is @var{freq}.
mediocre output. Default is @var{freq}.
@item speakers
Set custom positions of virtual loudspeakers. Syntax for this option is:
<CH> <AZIM> <ELEV>[|<CH> <AZIM> <ELEV>|...].
Each virtual loudspeaker is described with short channel name following with
azimuth and elevation in degreees.
Each virtual loudspeaker description is separated by '|'.
For example to override front left and front right channel positions use:
'speakers=FL 45 15|FR 345 15'.
Descriptions with unrecognised channel names are ignored.
@end table
@end table
@section stereotools
@section stereotools
...
...
libavfilter/af_sofalizer.c
浏览文件 @
a55c953e
...
@@ -29,6 +29,8 @@
...
@@ -29,6 +29,8 @@
#include <netcdf.h>
#include <netcdf.h>
#include "libavcodec/avfft.h"
#include "libavcodec/avfft.h"
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
#include "libavutil/float_dsp.h"
#include "libavutil/float_dsp.h"
#include "libavutil/intmath.h"
#include "libavutil/intmath.h"
#include "libavutil/opt.h"
#include "libavutil/opt.h"
...
@@ -52,6 +54,12 @@ typedef struct NCSofa { /* contains data of one SOFA file */
...
@@ -52,6 +54,12 @@ typedef struct NCSofa { /* contains data of one SOFA file */
float
*
data_ir
;
/* IRs (time-domain) */
float
*
data_ir
;
/* IRs (time-domain) */
}
NCSofa
;
}
NCSofa
;
typedef
struct
VirtualSpeaker
{
uint8_t
set
;
float
azim
;
float
elev
;
}
VirtualSpeaker
;
typedef
struct
SOFAlizerContext
{
typedef
struct
SOFAlizerContext
{
const
AVClass
*
class
;
const
AVClass
*
class
;
...
@@ -61,6 +69,7 @@ typedef struct SOFAlizerContext {
...
@@ -61,6 +69,7 @@ typedef struct SOFAlizerContext {
int
sample_rate
;
/* sample rate from SOFA file */
int
sample_rate
;
/* sample rate from SOFA file */
float
*
speaker_azim
;
/* azimuth of the virtual loudspeakers */
float
*
speaker_azim
;
/* azimuth of the virtual loudspeakers */
float
*
speaker_elev
;
/* elevation of the virtual loudspeakers */
float
*
speaker_elev
;
/* elevation of the virtual loudspeakers */
char
*
speakers_pos
;
/* custom positions of the virtual loudspeakers */
float
gain_lfe
;
/* gain applied to LFE channel */
float
gain_lfe
;
/* gain applied to LFE channel */
int
lfe_channel
;
/* LFE channel position in channel layout */
int
lfe_channel
;
/* LFE channel position in channel layout */
...
@@ -89,6 +98,8 @@ typedef struct SOFAlizerContext {
...
@@ -89,6 +98,8 @@ typedef struct SOFAlizerContext {
float
radius
;
/* distance virtual loudspeakers to listener (in metres) */
float
radius
;
/* distance virtual loudspeakers to listener (in metres) */
int
type
;
/* processing type */
int
type
;
/* processing type */
VirtualSpeaker
vspkrpos
[
64
];
FFTContext
*
fft
[
2
],
*
ifft
[
2
];
FFTContext
*
fft
[
2
],
*
ifft
[
2
];
FFTComplex
*
data_hrtf
[
2
];
FFTComplex
*
data_hrtf
[
2
];
...
@@ -362,6 +373,62 @@ error:
...
@@ -362,6 +373,62 @@ error:
return
ret
;
return
ret
;
}
}
static
int
parse_channel_name
(
char
**
arg
,
int
*
rchannel
)
{
char
buf
[
8
];
int
len
,
i
,
channel_id
=
0
;
int64_t
layout
,
layout0
;
/* try to parse a channel name, e.g. "FL" */
if
(
sscanf
(
*
arg
,
"%7[A-Z]%n"
,
buf
,
&
len
))
{
layout0
=
layout
=
av_get_channel_layout
(
buf
);
/* channel_id <- first set bit in layout */
for
(
i
=
32
;
i
>
0
;
i
>>=
1
)
{
if
(
layout
>=
(
int64_t
)
1
<<
i
)
{
channel_id
+=
i
;
layout
>>=
i
;
}
}
/* reject layouts that are not a single channel */
if
(
channel_id
>=
64
||
layout0
!=
(
int64_t
)
1
<<
channel_id
)
return
AVERROR
(
EINVAL
);
*
rchannel
=
channel_id
;
*
arg
+=
len
;
return
0
;
}
return
AVERROR
(
EINVAL
);
}
static
void
parse_speaker_pos
(
AVFilterContext
*
ctx
,
int64_t
in_channel_layout
)
{
SOFAlizerContext
*
s
=
ctx
->
priv
;
char
*
arg
,
*
tokenizer
,
*
p
,
*
args
=
av_strdup
(
s
->
speakers_pos
);
if
(
!
args
)
return
;
p
=
args
;
while
((
arg
=
av_strtok
(
p
,
"|"
,
&
tokenizer
)))
{
float
azim
,
elev
;
int
out_ch_id
;
p
=
NULL
;
if
(
parse_channel_name
(
&
arg
,
&
out_ch_id
))
continue
;
if
(
sscanf
(
arg
,
"%f %f"
,
&
azim
,
&
elev
)
==
2
)
{
s
->
vspkrpos
[
out_ch_id
].
set
=
1
;
s
->
vspkrpos
[
out_ch_id
].
azim
=
azim
;
s
->
vspkrpos
[
out_ch_id
].
elev
=
elev
;
}
else
if
(
sscanf
(
arg
,
"%f"
,
&
azim
)
==
1
)
{
s
->
vspkrpos
[
out_ch_id
].
set
=
1
;
s
->
vspkrpos
[
out_ch_id
].
azim
=
azim
;
s
->
vspkrpos
[
out_ch_id
].
elev
=
0
;
}
}
av_free
(
args
);
}
static
int
get_speaker_pos
(
AVFilterContext
*
ctx
,
static
int
get_speaker_pos
(
AVFilterContext
*
ctx
,
float
*
speaker_azim
,
float
*
speaker_elev
)
float
*
speaker_azim
,
float
*
speaker_elev
)
{
{
...
@@ -376,6 +443,9 @@ static int get_speaker_pos(AVFilterContext *ctx,
...
@@ -376,6 +443,9 @@ static int get_speaker_pos(AVFilterContext *ctx,
s
->
lfe_channel
=
-
1
;
s
->
lfe_channel
=
-
1
;
if
(
s
->
speakers_pos
)
parse_speaker_pos
(
ctx
,
channels_layout
);
/* set speaker positions according to input channel configuration: */
/* set speaker positions according to input channel configuration: */
for
(
m
=
0
,
ch
=
0
;
ch
<
n_conv
&&
m
<
64
;
m
++
)
{
for
(
m
=
0
,
ch
=
0
;
ch
<
n_conv
&&
m
<
64
;
m
++
)
{
uint64_t
mask
=
channels_layout
&
(
1
<<
m
);
uint64_t
mask
=
channels_layout
&
(
1
<<
m
);
...
@@ -417,6 +487,12 @@ static int get_speaker_pos(AVFilterContext *ctx,
...
@@ -417,6 +487,12 @@ static int get_speaker_pos(AVFilterContext *ctx,
default:
default:
return
AVERROR
(
EINVAL
);
return
AVERROR
(
EINVAL
);
}
}
if
(
s
->
vspkrpos
[
m
].
set
)
{
azim
[
ch
]
=
s
->
vspkrpos
[
m
].
azim
;
elev
[
ch
]
=
s
->
vspkrpos
[
m
].
elev
;
}
if
(
mask
)
if
(
mask
)
ch
++
;
ch
++
;
}
}
...
@@ -1114,6 +1190,7 @@ static const AVOption sofalizer_options[] = {
...
@@ -1114,6 +1190,7 @@ static const AVOption sofalizer_options[] = {
{
"type"
,
"set processing"
,
OFFSET
(
type
),
AV_OPT_TYPE_INT
,
{.
i64
=
1
},
0
,
1
,
.
flags
=
FLAGS
,
"type"
},
{
"type"
,
"set processing"
,
OFFSET
(
type
),
AV_OPT_TYPE_INT
,
{.
i64
=
1
},
0
,
1
,
.
flags
=
FLAGS
,
"type"
},
{
"time"
,
"time domain"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
0
},
0
,
0
,
.
flags
=
FLAGS
,
"type"
},
{
"time"
,
"time domain"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
0
},
0
,
0
,
.
flags
=
FLAGS
,
"type"
},
{
"freq"
,
"frequency domain"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
1
},
0
,
0
,
.
flags
=
FLAGS
,
"type"
},
{
"freq"
,
"frequency domain"
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
1
},
0
,
0
,
.
flags
=
FLAGS
,
"type"
},
{
"speakers"
,
"set speaker custom positions"
,
OFFSET
(
speakers_pos
),
AV_OPT_TYPE_STRING
,
{.
str
=
0
},
0
,
0
,
.
flags
=
FLAGS
},
{
NULL
}
{
NULL
}
};
};
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录