2 * Copyright (C) 2002 Anders Johansson ajh@watri.uwa.edu.au
4 * This file is part of MPlayer.
6 * MPlayer is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * MPlayer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 /* This filter adds a sub-woofer channels to the audio stream by
22 averaging the left and right channel and low-pass filter them. The
23 low-pass filter is implemented as a 4th order IIR Butterworth
24 filter, with a variable cutoff frequency between 10 and 300 Hz. The
25 filter gives 24dB/octave attenuation. There are two runtime
26 controls one for setting which channel to insert the sub-audio into
27 called AF_CONTROL_SUB_CH and one for setting the cutoff frequency
28 called AF_CONTROL_SUB_FC.
38 // Q value for low-pass filter
41 // Analog domain biquad section
43 float a
[3]; // Numerator coefficients
44 float b
[3]; // Denominator coefficients
47 // S-parameters for designing 4th order Butterworth filter
48 static biquad_t sp
[2] = {{{1.0,0.0,0.0},{1.0,0.765367,1.0}},
49 {{1.0,0.0,0.0},{1.0,1.847759,1.0}}};
51 // Data for specific instances of this filter
52 typedef struct af_sub_s
54 float w
[2][4]; // Filter taps for low-pass filter
55 float q
[2][2]; // Circular queues
56 float fc
; // Cutoff frequency [Hz] for low-pass filter
57 float k
; // Filter gain;
58 int ch
; // Channel number which to insert the filtered data
62 // Initialization and runtime control
63 static int control(struct af_instance_s
* af
, int cmd
, void* arg
)
65 af_sub_t
* s
= af
->setup
;
68 case AF_CONTROL_REINIT
:{
70 if(!arg
) return AF_ERROR
;
72 af
->data
->rate
= ((af_data_t
*)arg
)->rate
;
73 af
->data
->nch
= max(s
->ch
+1,((af_data_t
*)arg
)->nch
);
74 af
->data
->format
= AF_FORMAT_FLOAT_NE
;
77 // Design low-pass filter
79 if((-1 == af_filter_szxform(sp
[0].a
, sp
[0].b
, Q
, s
->fc
,
80 (float)af
->data
->rate
, &s
->k
, s
->w
[0])) ||
81 (-1 == af_filter_szxform(sp
[1].a
, sp
[1].b
, Q
, s
->fc
,
82 (float)af
->data
->rate
, &s
->k
, s
->w
[1])))
84 return af_test_output(af
,(af_data_t
*)arg
);
86 case AF_CONTROL_COMMAND_LINE
:{
89 sscanf(arg
,"%f:%i", &fc
, &ch
);
90 if(AF_OK
!= control(af
,AF_CONTROL_SUB_CH
| AF_CONTROL_SET
, &ch
))
92 return control(af
,AF_CONTROL_SUB_FC
| AF_CONTROL_SET
, &fc
);
94 case AF_CONTROL_SUB_CH
| AF_CONTROL_SET
: // Requires reinit
96 if((*(int*)arg
>= AF_NCH
) || (*(int*)arg
< 0)){
97 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "[sub] Subwoofer channel number must be between "
98 " 0 and %i current value is %i\n", AF_NCH
-1, *(int*)arg
);
103 case AF_CONTROL_SUB_CH
| AF_CONTROL_GET
:
106 case AF_CONTROL_SUB_FC
| AF_CONTROL_SET
: // Requires reinit
108 if((*(float*)arg
> 300) || (*(float*)arg
< 20)){
109 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "[sub] Cutoff frequency must be between 20Hz and"
110 " 300Hz current value is %0.2f",*(float*)arg
);
113 // Set cutoff frequency
114 s
->fc
= *(float*)arg
;
116 case AF_CONTROL_SUB_FC
| AF_CONTROL_GET
:
117 *(float*)arg
= s
->fc
;
124 static void uninit(struct af_instance_s
* af
)
133 #define IIR(in,w,q,out) { \
136 float hn = (in) - h0 * (w)[0] - h1 * (w)[1]; \
137 out = hn + h0 * (w)[2] + h1 * (w)[3]; \
143 // Filter data through filter
144 static af_data_t
* play(struct af_instance_s
* af
, af_data_t
* data
)
146 af_data_t
* c
= data
; // Current working data
147 af_sub_t
* s
= af
->setup
; // Setup for this instance
148 float* a
= c
->audio
; // Audio data
149 int len
= c
->len
/4; // Number of samples in current audio block
150 int nch
= c
->nch
; // Number of channels
151 int ch
= s
->ch
; // Channel in which to insert the sub audio
155 for(i
=0;i
<len
;i
+=nch
){
156 // Average left and right
157 register float x
= 0.5 * (a
[i
] + a
[i
+1]);
158 IIR(x
* s
->k
, s
->w
[0], s
->q
[0], x
);
159 IIR(x
, s
->w
[1], s
->q
[1], a
[i
+ch
]);
165 // Allocate memory and set function pointers
166 static int af_open(af_instance_t
* af
){
172 af
->data
=calloc(1,sizeof(af_data_t
));
173 af
->setup
=s
=calloc(1,sizeof(af_sub_t
));
174 if(af
->data
== NULL
|| af
->setup
== NULL
)
176 // Set default values
177 s
->ch
= 5; // Channel nr 6
178 s
->fc
= 60; // Cutoff frequency 60Hz
182 // Description of this filter
183 af_info_t af_info_sub
= {
184 "Audio filter for adding a sub-base channel",
188 AF_FLAGS_NOT_REENTRANT
,