1 /*=============================================================================
3 // This software has been released under the terms of the GNU General Public
4 // license. See http://www.gnu.org/copyleft/gpl.html for details.
6 // Copyright 2002 Anders Johansson ajh@watri.uwa.edu.au
8 //=============================================================================
11 /* This filter adds a sub-woofer channels to the audio stream by
12 averaging the left and right channel and low-pass filter them. The
13 low-pass filter is implemented as a 4th order IIR Butterworth
14 filter, with a variable cutoff frequency between 10 and 300 Hz. The
15 filter gives 24dB/octave attenuation. There are two runtime
16 controls one for setting which channel to insert the sub-audio into
17 called AF_CONTROL_SUB_CH and one for setting the cutoff frequency
18 called AF_CONTROL_SUB_FC.
28 // Q value for low-pass filter
31 // Analog domain biquad section
33 float a
[3]; // Numerator coefficients
34 float b
[3]; // Denominator coefficients
37 // S-parameters for designing 4th order Butterworth filter
38 static biquad_t sp
[2] = {{{1.0,0.0,0.0},{1.0,0.765367,1.0}},
39 {{1.0,0.0,0.0},{1.0,1.847759,1.0}}};
41 // Data for specific instances of this filter
42 typedef struct af_sub_s
44 float w
[2][4]; // Filter taps for low-pass filter
45 float q
[2][2]; // Circular queues
46 float fc
; // Cutoff frequency [Hz] for low-pass filter
47 float k
; // Filter gain;
48 int ch
; // Channel number which to insert the filtered data
52 // Initialization and runtime control
53 static int control(struct af_instance_s
* af
, int cmd
, void* arg
)
55 af_sub_t
* s
= af
->setup
;
58 case AF_CONTROL_REINIT
:{
60 if(!arg
) return AF_ERROR
;
62 af
->data
->rate
= ((af_data_t
*)arg
)->rate
;
63 af
->data
->nch
= max(s
->ch
+1,((af_data_t
*)arg
)->nch
);
64 af
->data
->format
= AF_FORMAT_FLOAT_NE
;
67 // Design low-pass filter
69 if((-1 == af_filter_szxform(sp
[0].a
, sp
[0].b
, Q
, s
->fc
,
70 (float)af
->data
->rate
, &s
->k
, s
->w
[0])) ||
71 (-1 == af_filter_szxform(sp
[1].a
, sp
[1].b
, Q
, s
->fc
,
72 (float)af
->data
->rate
, &s
->k
, s
->w
[1])))
74 return af_test_output(af
,(af_data_t
*)arg
);
76 case AF_CONTROL_COMMAND_LINE
:{
79 sscanf(arg
,"%f:%i", &fc
, &ch
);
80 if(AF_OK
!= control(af
,AF_CONTROL_SUB_CH
| AF_CONTROL_SET
, &ch
))
82 return control(af
,AF_CONTROL_SUB_FC
| AF_CONTROL_SET
, &fc
);
84 case AF_CONTROL_SUB_CH
| AF_CONTROL_SET
: // Requires reinit
86 if((*(int*)arg
>= AF_NCH
) || (*(int*)arg
< 0)){
87 af_msg(AF_MSG_ERROR
,"[sub] Subwoofer channel number must be between "
88 " 0 and %i current value is %i\n", AF_NCH
-1, *(int*)arg
);
93 case AF_CONTROL_SUB_CH
| AF_CONTROL_GET
:
96 case AF_CONTROL_SUB_FC
| AF_CONTROL_SET
: // Requires reinit
98 if((*(float*)arg
> 300) || (*(float*)arg
< 20)){
99 af_msg(AF_MSG_ERROR
,"[sub] Cutoff frequency must be between 20Hz and"
100 " 300Hz current value is %0.2f",*(float*)arg
);
103 // Set cutoff frequency
104 s
->fc
= *(float*)arg
;
106 case AF_CONTROL_SUB_FC
| AF_CONTROL_GET
:
107 *(float*)arg
= s
->fc
;
114 static void uninit(struct af_instance_s
* af
)
123 #define IIR(in,w,q,out) { \
126 float hn = (in) - h0 * (w)[0] - h1 * (w)[1]; \
127 out = hn + h0 * (w)[2] + h1 * (w)[3]; \
133 // Filter data through filter
134 static af_data_t
* play(struct af_instance_s
* af
, af_data_t
* data
)
136 af_data_t
* c
= data
; // Current working data
137 af_sub_t
* s
= af
->setup
; // Setup for this instance
138 float* a
= c
->audio
; // Audio data
139 int len
= c
->len
/4; // Number of samples in current audio block
140 int nch
= c
->nch
; // Number of channels
141 int ch
= s
->ch
; // Channel in which to insert the sub audio
145 for(i
=0;i
<len
;i
+=nch
){
146 // Average left and right
147 register float x
= 0.5 * (a
[i
] + a
[i
+1]);
148 IIR(x
* s
->k
, s
->w
[0], s
->q
[0], x
);
149 IIR(x
, s
->w
[1], s
->q
[1], a
[i
+ch
]);
155 // Allocate memory and set function pointers
156 static int open(af_instance_t
* af
){
163 af
->data
=calloc(1,sizeof(af_data_t
));
164 af
->setup
=s
=calloc(1,sizeof(af_sub_t
));
165 if(af
->data
== NULL
|| af
->setup
== NULL
)
167 // Set default values
168 s
->ch
= 5; // Channel nr 6
169 s
->fc
= 60; // Cutoff frequency 60Hz
173 // Description of this filter
174 af_info_t af_info_sub
= {
175 "Audio filter for adding a sub-base channel",
179 AF_FLAGS_NOT_REENTRANT
,