sout: transcode: check linear format using macro
[vlc.git] / modules / audio_filter / param_eq.c
blobc01cabf3b030996ce4a74a1f5ff721f9d1d3ec90
1 /*****************************************************************************
2 * param_eq.c:
3 *****************************************************************************
4 * Copyright © 2006 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Antti Huovilainen
8 * Sigmund A. Helberg <dnumgis@videolan.org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
26 * Preamble
27 *****************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
33 #include <math.h>
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_aout.h>
38 #include <vlc_filter.h>
40 /*****************************************************************************
41 * Module descriptor
42 *****************************************************************************/
43 static int Open ( vlc_object_t * );
44 static void Close( vlc_object_t * );
45 static void CalcPeakEQCoeffs( float, float, float, float, float * );
46 static void CalcShelfEQCoeffs( float, float, float, int, float, float * );
47 static void ProcessEQ( const float *, float *, float *, unsigned, unsigned,
48 const float *, unsigned );
49 static block_t *DoWork( filter_t *, block_t * );
51 vlc_module_begin ()
52 set_description( N_("Parametric Equalizer") )
53 set_shortname( N_("Parametric Equalizer" ) )
54 set_capability( "audio filter", 0 )
55 set_category( CAT_AUDIO )
56 set_subcategory( SUBCAT_AUDIO_AFILTER )
58 add_float( "param-eq-lowf", 100, N_("Low freq (Hz)"),NULL, false )
59 add_float_with_range( "param-eq-lowgain", 0, -20.0, 20.0,
60 N_("Low freq gain (dB)"), NULL,false )
61 add_float( "param-eq-highf", 10000, N_("High freq (Hz)"),NULL, false )
62 add_float_with_range( "param-eq-highgain", 0, -20.0, 20.0,
63 N_("High freq gain (dB)"),NULL,false )
64 add_float( "param-eq-f1", 300, N_("Freq 1 (Hz)"),NULL, false )
65 add_float_with_range( "param-eq-gain1", 0, -20.0, 20.0,
66 N_("Freq 1 gain (dB)"), NULL,false )
67 add_float_with_range( "param-eq-q1", 3, 0.1, 100.0,
68 N_("Freq 1 Q"), NULL,false )
69 add_float( "param-eq-f2", 1000, N_("Freq 2 (Hz)"),NULL, false )
70 add_float_with_range( "param-eq-gain2", 0, -20.0, 20.0,
71 N_("Freq 2 gain (dB)"),NULL,false )
72 add_float_with_range( "param-eq-q2", 3, 0.1, 100.0,
73 N_("Freq 2 Q"),NULL,false )
74 add_float( "param-eq-f3", 3000, N_("Freq 3 (Hz)"),NULL, false )
75 add_float_with_range( "param-eq-gain3", 0, -20.0, 20.0,
76 N_("Freq 3 gain (dB)"),NULL,false )
77 add_float_with_range( "param-eq-q3", 3, 0.1, 100.0,
78 N_("Freq 3 Q"),NULL,false )
80 set_callbacks( Open, Close )
81 vlc_module_end ()
83 /*****************************************************************************
84 * Local prototypes
85 *****************************************************************************/
86 typedef struct
88 /* Filter static config */
89 float f_lowf, f_lowgain;
90 float f_f1, f_Q1, f_gain1;
91 float f_f2, f_Q2, f_gain2;
92 float f_f3, f_Q3, f_gain3;
93 float f_highf, f_highgain;
94 /* Filter computed coeffs */
95 float coeffs[5*5];
96 /* State */
97 float *p_state;
98 } filter_sys_t;
103 /*****************************************************************************
104 * Open:
105 *****************************************************************************/
106 static int Open( vlc_object_t *p_this )
108 filter_t *p_filter = (filter_t *)p_this;
109 unsigned i_samplerate;
111 /* Allocate structure */
112 filter_sys_t *p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) );
113 if( !p_sys )
114 return VLC_EGENERIC;
116 p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
117 p_filter->fmt_out.audio = p_filter->fmt_in.audio;
118 p_filter->pf_audio_filter = DoWork;
120 p_sys->f_lowf = var_InheritFloat( p_this, "param-eq-lowf");
121 p_sys->f_lowgain = var_InheritFloat( p_this, "param-eq-lowgain");
122 p_sys->f_highf = var_InheritFloat( p_this, "param-eq-highf");
123 p_sys->f_highgain = var_InheritFloat( p_this, "param-eq-highgain");
125 p_sys->f_f1 = var_InheritFloat( p_this, "param-eq-f1");
126 p_sys->f_Q1 = var_InheritFloat( p_this, "param-eq-q1");
127 p_sys->f_gain1 = var_InheritFloat( p_this, "param-eq-gain1");
129 p_sys->f_f2 = var_InheritFloat( p_this, "param-eq-f2");
130 p_sys->f_Q2 = var_InheritFloat( p_this, "param-eq-q2");
131 p_sys->f_gain2 = var_InheritFloat( p_this, "param-eq-gain2");
133 p_sys->f_f3 = var_InheritFloat( p_this, "param-eq-f3");
134 p_sys->f_Q3 = var_InheritFloat( p_this, "param-eq-q3");
135 p_sys->f_gain3 = var_InheritFloat( p_this, "param-eq-gain3");
138 i_samplerate = p_filter->fmt_in.audio.i_rate;
139 CalcPeakEQCoeffs(p_sys->f_f1, p_sys->f_Q1, p_sys->f_gain1,
140 i_samplerate, p_sys->coeffs+0*5);
141 CalcPeakEQCoeffs(p_sys->f_f2, p_sys->f_Q2, p_sys->f_gain2,
142 i_samplerate, p_sys->coeffs+1*5);
143 CalcPeakEQCoeffs(p_sys->f_f3, p_sys->f_Q3, p_sys->f_gain3,
144 i_samplerate, p_sys->coeffs+2*5);
145 CalcShelfEQCoeffs(p_sys->f_lowf, 1, p_sys->f_lowgain, 0,
146 i_samplerate, p_sys->coeffs+3*5);
147 CalcShelfEQCoeffs(p_sys->f_highf, 1, p_sys->f_highgain, 0,
148 i_samplerate, p_sys->coeffs+4*5);
149 p_sys->p_state = (float*)calloc( p_filter->fmt_in.audio.i_channels*5*4,
150 sizeof(float) );
152 return VLC_SUCCESS;
155 static void Close( vlc_object_t *p_this )
157 filter_t *p_filter = (filter_t *)p_this;
158 filter_sys_t *p_sys = p_filter->p_sys;
159 free( p_sys->p_state );
160 free( p_sys );
163 /*****************************************************************************
164 * DoWork: process samples buffer
165 *****************************************************************************
167 *****************************************************************************/
168 static block_t *DoWork( filter_t * p_filter, block_t * p_in_buf )
170 filter_sys_t *p_sys = p_filter->p_sys;
171 ProcessEQ( (float*)p_in_buf->p_buffer, (float*)p_in_buf->p_buffer,
172 p_sys->p_state,
173 p_filter->fmt_in.audio.i_channels, p_in_buf->i_nb_samples,
174 p_sys->coeffs, 5 );
175 return p_in_buf;
179 * Calculate direct form IIR coefficients for peaking EQ
180 * coeffs[0] = b0
181 * coeffs[1] = b1
182 * coeffs[2] = b2
183 * coeffs[3] = a1
184 * coeffs[4] = a2
186 * Equations taken from RBJ audio EQ cookbook
187 * (http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt)
189 static void CalcPeakEQCoeffs( float f0, float Q, float gainDB, float Fs,
190 float *coeffs )
192 float A;
193 float w0;
194 float alpha;
195 float b0, b1, b2;
196 float a0, a1, a2;
198 // Provide sane limits to avoid overflow
199 if (Q < 0.1f) Q = 0.1f;
200 if (Q > 100) Q = 100;
201 if (f0 > Fs/2*0.95f) f0 = Fs/2*0.95f;
202 if (gainDB < -40) gainDB = -40;
203 if (gainDB > 40) gainDB = 40;
205 A = powf(10, gainDB/40);
206 w0 = 2*((float)M_PI)*f0/Fs;
207 alpha = sinf(w0)/(2*Q);
209 b0 = 1 + alpha*A;
210 b1 = -2*cosf(w0);
211 b2 = 1 - alpha*A;
212 a0 = 1 + alpha/A;
213 a1 = -2*cosf(w0);
214 a2 = 1 - alpha/A;
216 // Store values to coeffs and normalize by 1/a0
217 coeffs[0] = b0/a0;
218 coeffs[1] = b1/a0;
219 coeffs[2] = b2/a0;
220 coeffs[3] = a1/a0;
221 coeffs[4] = a2/a0;
225 * Calculate direct form IIR coefficients for low/high shelf EQ
226 * coeffs[0] = b0
227 * coeffs[1] = b1
228 * coeffs[2] = b2
229 * coeffs[3] = a1
230 * coeffs[4] = a2
232 * Equations taken from RBJ audio EQ cookbook
233 * (http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt)
235 static void CalcShelfEQCoeffs( float f0, float slope, float gainDB, int high,
236 float Fs, float *coeffs )
238 float A;
239 float w0;
240 float alpha;
241 float b0, b1, b2;
242 float a0, a1, a2;
244 // Provide sane limits to avoid overflow
245 if (f0 > Fs/2*0.95f) f0 = Fs/2*0.95f;
246 if (gainDB < -40) gainDB = -40;
247 if (gainDB > 40) gainDB = 40;
249 A = powf(10, gainDB/40);
250 w0 = 2*3.141593f*f0/Fs;
251 alpha = sinf(w0)/2 * sqrtf( (A + 1/A)*(1/slope - 1) + 2 );
253 if (high)
255 b0 = A*( (A+1) + (A-1)*cosf(w0) + 2*sqrtf(A)*alpha );
256 b1 = -2*A*( (A-1) + (A+1)*cosf(w0) );
257 b2 = A*( (A+1) + (A-1)*cosf(w0) - 2*sqrtf(A)*alpha );
258 a0 = (A+1) - (A-1)*cosf(w0) + 2*sqrtf(A)*alpha;
259 a1 = 2*( (A-1) - (A+1)*cosf(w0) );
260 a2 = (A+1) - (A-1)*cosf(w0) - 2*sqrtf(A)*alpha;
262 else
264 b0 = A*( (A+1) - (A-1)*cosf(w0) + 2*sqrtf(A)*alpha );
265 b1 = 2*A*( (A-1) - (A+1)*cosf(w0));
266 b2 = A*( (A+1) - (A-1)*cosf(w0) - 2*sqrtf(A)*alpha );
267 a0 = (A+1) + (A-1)*cosf(w0) + 2*sqrtf(A)*alpha;
268 a1 = -2*( (A-1) + (A+1)*cosf(w0));
269 a2 = (A+1) + (A-1)*cosf(w0) - 2*sqrtf(A)*alpha;
271 // Store values to coeffs and normalize by 1/a0
272 coeffs[0] = b0/a0;
273 coeffs[1] = b1/a0;
274 coeffs[2] = b2/a0;
275 coeffs[3] = a1/a0;
276 coeffs[4] = a2/a0;
280 src is assumed to be interleaved
281 dest is assumed to be interleaved
282 size of state is 4*channels*eqCount
283 samples is not premultiplied by channels
284 size of coeffs is 5*eqCount
286 void ProcessEQ( const float *src, float *dest, float *state,
287 unsigned channels, unsigned samples, const float *coeffs,
288 unsigned eqCount )
290 unsigned i, chn, eq;
291 float b0, b1, b2, a1, a2;
292 float x, y = 0;
293 const float *src1 = src;
294 float *dest1 = dest;
296 for (i = 0; i < samples; i++)
298 float *state1 = state;
299 for (chn = 0; chn < channels; chn++)
301 const float *coeffs1 = coeffs;
302 x = *src1++;
303 /* Direct form 1 IIRs */
304 for (eq = 0; eq < eqCount; eq++)
306 b0 = coeffs1[0];
307 b1 = coeffs1[1];
308 b2 = coeffs1[2];
309 a1 = coeffs1[3];
310 a2 = coeffs1[4];
311 coeffs1 += 5;
312 y = x*b0 + state1[0]*b1 + state1[1]*b2 - state1[2]*a1 - state1[3]*a2;
313 state1[1] = state1[0];
314 state1[0] = x;
315 state1[3] = state1[2];
316 state1[2] = y;
317 x = y;
318 state1 += 4;
320 *dest1++ = y;