FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
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 = 32;
102
for
(j = 0; j <
NUMTAPS
; j++)
103
sample += in[j] *
filt
[j];
104
*out = sample >> 6;
105
out++;
106
in++;
107
}
108
109
return
out
;
110
}
111
112
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFilterBufferRef
*insamples)
113
{
114
AVFilterLink
*outlink = inlink->
dst
->
outputs
[0];
115
int16_t *taps, *endin, *
in
, *
out
;
116
AVFilterBufferRef
*outsamples =
117
ff_get_audio_buffer
(inlink,
AV_PERM_WRITE
,
118
insamples->
audio
->
nb_samples
);
119
int
ret;
120
121
if
(!outsamples)
122
return
AVERROR
(ENOMEM);
123
avfilter_copy_buffer_ref_props
(outsamples, insamples);
124
125
taps = ((
EarwaxContext
*)inlink->
dst
->
priv
)->taps;
126
out = (int16_t *)outsamples->
data
[0];
127
in = (int16_t *)insamples ->
data
[0];
128
129
// copy part of new input and process with saved input
130
memcpy(taps+
NUMTAPS
, in,
NUMTAPS
*
sizeof
(*taps));
131
out =
scalarproduct
(taps, taps +
NUMTAPS
, out);
132
133
// process current input
134
endin = in + insamples->
audio
->
nb_samples
* 2 -
NUMTAPS
;
135
scalarproduct
(in, endin, out);
136
137
// save part of input for next round
138
memcpy(taps, endin,
NUMTAPS
*
sizeof
(*taps));
139
140
ret =
ff_filter_frame
(outlink, outsamples);
141
avfilter_unref_buffer
(insamples);
142
return
ret;
143
}
144
145
static
const
AVFilterPad
earwax_inputs
[] = {
146
{
147
.
name
=
"default"
,
148
.type =
AVMEDIA_TYPE_AUDIO
,
149
.filter_frame =
filter_frame
,
150
.min_perms =
AV_PERM_READ
,
151
},
152
{
NULL
}
153
};
154
155
static
const
AVFilterPad
earwax_outputs
[] = {
156
{
157
.
name
=
"default"
,
158
.type =
AVMEDIA_TYPE_AUDIO
,
159
},
160
{
NULL
}
161
};
162
163
AVFilter
avfilter_af_earwax
= {
164
.
name
=
"earwax"
,
165
.description =
NULL_IF_CONFIG_SMALL
(
"Widen the stereo image."
),
166
.query_formats =
query_formats
,
167
.priv_size =
sizeof
(
EarwaxContext
),
168
.
inputs
= earwax_inputs,
169
.
outputs
= earwax_outputs,
170
};
Generated on Sat May 25 2013 04:01:14 for FFmpeg by
1.8.2