FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavfilter
af_earwax.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2011 Mina Nagy Zaki
3
* Copyright (c) 2000 Edward Beingessner And Sundry Contributors.
4
* This source code is freely redistributable and may be used for any purpose.
5
* This copyright notice must be maintained. Edward Beingessner And Sundry
6
* Contributors are not responsible for the consequences of using this
7
* software.
8
*
9
* This file is part of FFmpeg.
10
*
11
* FFmpeg is free software; you can redistribute it and/or
12
* modify it under the terms of the GNU Lesser General Public
13
* License as published by the Free Software Foundation; either
14
* version 2.1 of the License, or (at your option) any later version.
15
*
16
* FFmpeg is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
* Lesser General Public License for more details.
20
*
21
* You should have received a copy of the GNU Lesser General Public
22
* License along with FFmpeg; if not, write to the Free Software
23
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24
*/
25
26
/**
27
* @file
28
* Stereo Widening Effect. Adds audio cues to move stereo image in
29
* front of the listener. Adapted from the libsox earwax effect.
30
*/
31
32
#include "
libavutil/channel_layout.h
"
33
#include "
avfilter.h
"
34
#include "
audio.h
"
35
#include "
formats.h
"
36
37
#define NUMTAPS 64
38
39
static
const
int8_t
filt
[
NUMTAPS
] = {
40
/* 30° 330° */
41
4, -6,
/* 32 tap stereo FIR filter. */
42
4, -11,
/* One side filters as if the */
43
-1, -5,
/* signal was from 30 degrees */
44
3, 3,
/* from the ear, the other as */
45
-2, 5,
/* if 330 degrees. */
46
-5, 0,
47
9, 1,
48
6, 3,
/* Input */
49
-4, -1,
/* Left Right */
50
-5, -3,
/* __________ __________ */
51
-2, -5,
/* | | | | */
52
-7, 1,
/* .---| Hh,0(f) | | Hh,0(f) |---. */
53
6, -7,
/* / |__________| |__________| \ */
54
30, -29,
/* / \ / \ */
55
12, -3,
/* / X \ */
56
-11, 4,
/* / / \ \ */
57
-3, 7,
/* ____V_____ __________V V__________ _____V____ */
58
-20, 23,
/* | | | | | | | | */
59
2, 0,
/* | Hh,30(f) | | Hh,330(f)| | Hh,330(f)| | Hh,30(f) | */
60
1, -6,
/* |__________| |__________| |__________| |__________| */
61
-14, -5,
/* \ ___ / \ ___ / */
62
15, -18,
/* \ / \ / _____ \ / \ / */
63
6, 7,
/* `->| + |<--' / \ `-->| + |<-' */
64
15, -10,
/* \___/ _/ \_ \___/ */
65
-14, 22,
/* \ / \ / \ / */
66
-7, -2,
/* `--->| | | |<---' */
67
-4, 9,
/* \_/ \_/ */
68
6, -12,
/* */
69
6, -6,
/* Headphones */
70
0, -11,
71
0, -5,
72
4, 0};
73
74
typedef
struct
{
75
int16_t taps[
NUMTAPS
* 2];
76
}
EarwaxContext
;
77
78
static
int
query_formats
(
AVFilterContext
*ctx)
79
{
80
static
const
int
sample_rates
[] = { 44100, -1 };
81
82
AVFilterFormats
*
formats
= NULL;
83
AVFilterChannelLayouts
*
layout
= NULL;
84
85
ff_add_format
(&formats,
AV_SAMPLE_FMT_S16
);
86
ff_set_common_formats
(ctx, formats);
87
ff_add_channel_layout
(&layout,
AV_CH_LAYOUT_STEREO
);
88
ff_set_common_channel_layouts
(ctx, layout);
89
ff_set_common_samplerates
(ctx,
ff_make_format_list
(sample_rates));
90
91
return
0;
92
}
93
94
//FIXME: replace with DSPContext.scalarproduct_int16
95
static
inline
int16_t *
scalarproduct
(
const
int16_t *
in
,
const
int16_t *endin, int16_t *
out
)
96
{
97
int32_t
sample
;
98
int16_t j;
99
100
while
(in < endin) {
101
sample = 0;
102
for
(j = 0; j <
NUMTAPS
; j++)
103
sample += in[j] *
filt
[j];
104
*out = av_clip_int16(sample >> 6);
105
out++;
106
in++;
107
}
108
109
return
out
;
110
}
111
112
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFrame
*insamples)
113
{
114
AVFilterLink
*outlink = inlink->
dst
->
outputs
[0];
115
int16_t *taps, *endin, *
in
, *
out
;
116
AVFrame
*outsamples =
ff_get_audio_buffer
(inlink, insamples->
nb_samples
);
117
118
if
(!outsamples) {
119
av_frame_free
(&insamples);
120
return
AVERROR
(ENOMEM);
121
}
122
av_frame_copy_props
(outsamples, insamples);
123
124
taps = ((
EarwaxContext
*)inlink->
dst
->
priv
)->taps;
125
out = (int16_t *)outsamples->
data
[0];
126
in = (int16_t *)insamples ->
data
[0];
127
128
// copy part of new input and process with saved input
129
memcpy(taps+
NUMTAPS
, in,
NUMTAPS
*
sizeof
(*taps));
130
out =
scalarproduct
(taps, taps +
NUMTAPS
, out);
131
132
// process current input
133
endin = in + insamples->
nb_samples
* 2 -
NUMTAPS
;
134
scalarproduct
(in, endin, out);
135
136
// save part of input for next round
137
memcpy(taps, endin,
NUMTAPS
*
sizeof
(*taps));
138
139
av_frame_free
(&insamples);
140
return
ff_filter_frame
(outlink, outsamples);
141
}
142
143
static
const
AVFilterPad
earwax_inputs
[] = {
144
{
145
.
name
=
"default"
,
146
.type =
AVMEDIA_TYPE_AUDIO
,
147
.filter_frame =
filter_frame
,
148
},
149
{ NULL }
150
};
151
152
static
const
AVFilterPad
earwax_outputs
[] = {
153
{
154
.
name
=
"default"
,
155
.type =
AVMEDIA_TYPE_AUDIO
,
156
},
157
{ NULL }
158
};
159
160
AVFilter
avfilter_af_earwax
= {
161
.
name
=
"earwax"
,
162
.description =
NULL_IF_CONFIG_SMALL
(
"Widen the stereo image."
),
163
.query_formats =
query_formats
,
164
.priv_size =
sizeof
(
EarwaxContext
),
165
.
inputs
= earwax_inputs,
166
.
outputs
= earwax_outputs,
167
};
Generated on Wed Jul 10 2013 23:48:09 for FFmpeg by
1.8.2