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
static
int
config_input
(
AVFilterLink
*inlink)
95
{
96
if
(inlink->
sample_rate
!= 44100) {
97
av_log
(inlink->
dst
,
AV_LOG_ERROR
,
98
"The earwax filter only works for 44.1kHz audio. Insert "
99
"a resample filter before this\n"
);
100
return
AVERROR
(EINVAL);
101
}
102
return
0;
103
}
104
105
//FIXME: replace with DSPContext.scalarproduct_int16
106
static
inline
int16_t *
scalarproduct
(
const
int16_t *in,
const
int16_t *endin, int16_t *out)
107
{
108
int32_t
sample
;
109
int16_t j;
110
111
while
(in < endin) {
112
sample = 32;
113
for
(j = 0; j <
NUMTAPS
; j++)
114
sample += in[j] *
filt
[j];
115
*out = sample >> 6;
116
out++;
117
in++;
118
}
119
120
return
out;
121
}
122
123
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFilterBufferRef
*insamples)
124
{
125
AVFilterLink
*outlink = inlink->
dst
->
outputs
[0];
126
int16_t *taps, *endin, *in, *out;
127
AVFilterBufferRef
*outsamples =
128
ff_get_audio_buffer
(inlink,
AV_PERM_WRITE
,
129
insamples->
audio
->
nb_samples
);
130
int
ret;
131
132
if
(!outsamples)
133
return
AVERROR
(ENOMEM);
134
avfilter_copy_buffer_ref_props
(outsamples, insamples);
135
136
taps = ((
EarwaxContext
*)inlink->
dst
->
priv
)->taps;
137
out = (int16_t *)outsamples->
data
[0];
138
in = (int16_t *)insamples ->
data
[0];
139
140
// copy part of new input and process with saved input
141
memcpy(taps+
NUMTAPS
, in,
NUMTAPS
*
sizeof
(*taps));
142
out =
scalarproduct
(taps, taps +
NUMTAPS
, out);
143
144
// process current input
145
endin = in + insamples->
audio
->
nb_samples
* 2 -
NUMTAPS
;
146
scalarproduct
(in, endin, out);
147
148
// save part of input for next round
149
memcpy(taps, endin,
NUMTAPS
*
sizeof
(*taps));
150
151
ret =
ff_filter_frame
(outlink, outsamples);
152
avfilter_unref_buffer
(insamples);
153
return
ret;
154
}
155
156
static
const
AVFilterPad
earwax_inputs
[] = {
157
{
158
.
name
=
"default"
,
159
.type =
AVMEDIA_TYPE_AUDIO
,
160
.filter_frame =
filter_frame
,
161
.config_props =
config_input
,
162
.min_perms =
AV_PERM_READ
,
163
},
164
{
NULL
}
165
};
166
167
static
const
AVFilterPad
earwax_outputs
[] = {
168
{
169
.
name
=
"default"
,
170
.type =
AVMEDIA_TYPE_AUDIO
,
171
},
172
{
NULL
}
173
};
174
175
AVFilter
avfilter_af_earwax
= {
176
.
name
=
"earwax"
,
177
.description =
NULL_IF_CONFIG_SMALL
(
"Widen the stereo image."
),
178
.query_formats =
query_formats
,
179
.priv_size =
sizeof
(
EarwaxContext
),
180
.
inputs
= earwax_inputs,
181
.
outputs
= earwax_outputs,
182
};
Generated on Sat May 25 2013 03:58:44 for FFmpeg by
1.8.2