chromecast: lower vorbis encoding quality
[vlc.git] / modules / audio_filter / param_eq.c
blob9b984bec87c895908d999374ced8e552ef925865
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 struct filter_sys_t
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;
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 free( p_filter->p_sys->p_state );
159 free( p_filter->p_sys );
162 /*****************************************************************************
163 * DoWork: process samples buffer
164 *****************************************************************************
166 *****************************************************************************/
167 static block_t *DoWork( filter_t * p_filter, block_t * p_in_buf )
169 ProcessEQ( (float*)p_in_buf->p_buffer, (float*)p_in_buf->p_buffer,
170 p_filter->p_sys->p_state,
171 p_filter->fmt_in.audio.i_channels, p_in_buf->i_nb_samples,
172 p_filter->p_sys->coeffs, 5 );
173 return p_in_buf;
177 * Calculate direct form IIR coefficients for peaking EQ
178 * coeffs[0] = b0
179 * coeffs[1] = b1
180 * coeffs[2] = b2
181 * coeffs[3] = a1
182 * coeffs[4] = a2
184 * Equations taken from RBJ audio EQ cookbook
185 * (http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt)
187 static void CalcPeakEQCoeffs( float f0, float Q, float gainDB, float Fs,
188 float *coeffs )
190 float A;
191 float w0;
192 float alpha;
193 float b0, b1, b2;
194 float a0, a1, a2;
196 // Provide sane limits to avoid overflow
197 if (Q < 0.1f) Q = 0.1f;
198 if (Q > 100) Q = 100;
199 if (f0 > Fs/2*0.95f) f0 = Fs/2*0.95f;
200 if (gainDB < -40) gainDB = -40;
201 if (gainDB > 40) gainDB = 40;
203 A = powf(10, gainDB/40);
204 w0 = 2*((float)M_PI)*f0/Fs;
205 alpha = sinf(w0)/(2*Q);
207 b0 = 1 + alpha*A;
208 b1 = -2*cosf(w0);
209 b2 = 1 - alpha*A;
210 a0 = 1 + alpha/A;
211 a1 = -2*cosf(w0);
212 a2 = 1 - alpha/A;
214 // Store values to coeffs and normalize by 1/a0
215 coeffs[0] = b0/a0;
216 coeffs[1] = b1/a0;
217 coeffs[2] = b2/a0;
218 coeffs[3] = a1/a0;
219 coeffs[4] = a2/a0;
223 * Calculate direct form IIR coefficients for low/high shelf EQ
224 * coeffs[0] = b0
225 * coeffs[1] = b1
226 * coeffs[2] = b2
227 * coeffs[3] = a1
228 * coeffs[4] = a2
230 * Equations taken from RBJ audio EQ cookbook
231 * (http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt)
233 static void CalcShelfEQCoeffs( float f0, float slope, float gainDB, int high,
234 float Fs, float *coeffs )
236 float A;
237 float w0;
238 float alpha;
239 float b0, b1, b2;
240 float a0, a1, a2;
242 // Provide sane limits to avoid overflow
243 if (f0 > Fs/2*0.95f) f0 = Fs/2*0.95f;
244 if (gainDB < -40) gainDB = -40;
245 if (gainDB > 40) gainDB = 40;
247 A = powf(10, gainDB/40);
248 w0 = 2*3.141593f*f0/Fs;
249 alpha = sinf(w0)/2 * sqrtf( (A + 1/A)*(1/slope - 1) + 2 );
251 if (high)
253 b0 = A*( (A+1) + (A-1)*cosf(w0) + 2*sqrtf(A)*alpha );
254 b1 = -2*A*( (A-1) + (A+1)*cosf(w0) );
255 b2 = A*( (A+1) + (A-1)*cosf(w0) - 2*sqrtf(A)*alpha );
256 a0 = (A+1) - (A-1)*cosf(w0) + 2*sqrtf(A)*alpha;
257 a1 = 2*( (A-1) - (A+1)*cosf(w0) );
258 a2 = (A+1) - (A-1)*cosf(w0) - 2*sqrtf(A)*alpha;
260 else
262 b0 = A*( (A+1) - (A-1)*cosf(w0) + 2*sqrtf(A)*alpha );
263 b1 = 2*A*( (A-1) - (A+1)*cosf(w0));
264 b2 = A*( (A+1) - (A-1)*cosf(w0) - 2*sqrtf(A)*alpha );
265 a0 = (A+1) + (A-1)*cosf(w0) + 2*sqrtf(A)*alpha;
266 a1 = -2*( (A-1) + (A+1)*cosf(w0));
267 a2 = (A+1) + (A-1)*cosf(w0) - 2*sqrtf(A)*alpha;
269 // Store values to coeffs and normalize by 1/a0
270 coeffs[0] = b0/a0;
271 coeffs[1] = b1/a0;
272 coeffs[2] = b2/a0;
273 coeffs[3] = a1/a0;
274 coeffs[4] = a2/a0;
278 src is assumed to be interleaved
279 dest is assumed to be interleaved
280 size of state is 4*channels*eqCount
281 samples is not premultiplied by channels
282 size of coeffs is 5*eqCount
284 void ProcessEQ( const float *src, float *dest, float *state,
285 unsigned channels, unsigned samples, const float *coeffs,
286 unsigned eqCount )
288 unsigned i, chn, eq;
289 float b0, b1, b2, a1, a2;
290 float x, y = 0;
291 const float *src1 = src;
292 float *dest1 = dest;
294 for (i = 0; i < samples; i++)
296 float *state1 = state;
297 for (chn = 0; chn < channels; chn++)
299 const float *coeffs1 = coeffs;
300 x = *src1++;
301 /* Direct form 1 IIRs */
302 for (eq = 0; eq < eqCount; eq++)
304 b0 = coeffs1[0];
305 b1 = coeffs1[1];
306 b2 = coeffs1[2];
307 a1 = coeffs1[3];
308 a2 = coeffs1[4];
309 coeffs1 += 5;
310 y = x*b0 + state1[0]*b1 + state1[1]*b2 - state1[2]*a1 - state1[3]*a2;
311 state1[1] = state1[0];
312 state1[0] = x;
313 state1[3] = state1[2];
314 state1[2] = y;
315 x = y;
316 state1 += 4;
318 *dest1++ = y;