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@atri.curtin.edu.au
8 //=============================================================================
11 /* This audio filter changes the volume of the sound, and can be used
12 when the mixer doesn't support the PCM channel. It can handle
13 between 1 and 6 channels. The volume can be adjusted between -60dB
14 to +20dB and is set on a per channels basis. The is accessed through
15 AF_CONTROL_VOLUME_LEVEL.
17 The filter has support for soft-clipping, it is enabled by
18 AF_CONTROL_VOLUME_SOFTCLIPP. It has also a probing feature which
19 can be used to measure the power in the audio stream, both an
20 instantaneous value and the maximum value can be probed. The
21 probing is enable by AF_CONTROL_VOLUME_PROBE_ON_OFF and is done on a
22 per channel basis. The result from the probing is obtained using
23 AF_CONTROL_VOLUME_PROBE_GET and AF_CONTROL_VOLUME_PROBE_GET_MAX. The
24 probed values are calculated in dB.
37 // Data for specific instances of this filter
38 typedef struct af_volume_s
40 int enable
[AF_NCH
]; // Enable/disable / channel
41 float pow
[AF_NCH
]; // Estimated power level [dB]
42 float max
[AF_NCH
]; // Max Power level [dB]
43 float level
[AF_NCH
]; // Gain level for each channel
44 float time
; // Forgetting factor for power estimate
45 int soft
; // Enable/disable soft clipping
46 int fast
; // Use fix-point volume control
49 // Initialization and runtime control
50 static int control(struct af_instance_s
* af
, int cmd
, void* arg
)
52 af_volume_t
* s
= (af_volume_t
*)af
->setup
;
55 case AF_CONTROL_REINIT
:
57 if(!arg
) return AF_ERROR
;
59 af
->data
->rate
= ((af_data_t
*)arg
)->rate
;
60 af
->data
->nch
= ((af_data_t
*)arg
)->nch
;
62 if(s
->fast
&& (((af_data_t
*)arg
)->format
!= (AF_FORMAT_FLOAT_NE
))){
63 af
->data
->format
= AF_FORMAT_S16_NE
;
67 // Cutoff set to 10Hz for forgetting factor
68 float x
= 2.0*M_PI
*15.0/(float)af
->data
->rate
;
70 s
->time
= 1.0 - (t
- sqrt(t
*t
- 1));
71 af_msg(AF_MSG_DEBUG0
,"[volume] Forgetting factor = %0.5f\n",s
->time
);
72 af
->data
->format
= AF_FORMAT_FLOAT_NE
;
75 return af_test_output(af
,(af_data_t
*)arg
);
76 case AF_CONTROL_COMMAND_LINE
:{
80 sscanf((char*)arg
,"%f:%i", &v
, &s
->soft
);
81 for(i
=0;i
<AF_NCH
;i
++) vol
[i
]=v
;
82 return control(af
,AF_CONTROL_VOLUME_LEVEL
| AF_CONTROL_SET
, vol
);
84 case AF_CONTROL_POST_CREATE
:
85 s
->fast
= ((((af_cfg_t
*)arg
)->force
& AF_INIT_FORMAT_MASK
) ==
86 AF_INIT_FLOAT
) ? 0 : 1;
88 case AF_CONTROL_VOLUME_ON_OFF
| AF_CONTROL_SET
:
89 memcpy(s
->enable
,(int*)arg
,AF_NCH
*sizeof(int));
91 case AF_CONTROL_VOLUME_ON_OFF
| AF_CONTROL_GET
:
92 memcpy((int*)arg
,s
->enable
,AF_NCH
*sizeof(int));
94 case AF_CONTROL_VOLUME_SOFTCLIP
| AF_CONTROL_SET
:
97 case AF_CONTROL_VOLUME_SOFTCLIP
| AF_CONTROL_GET
:
100 case AF_CONTROL_VOLUME_LEVEL
| AF_CONTROL_SET
:
101 return af_from_dB(AF_NCH
,(float*)arg
,s
->level
,20.0,-200.0,60.0);
102 case AF_CONTROL_VOLUME_LEVEL
| AF_CONTROL_GET
:
103 return af_to_dB(AF_NCH
,s
->level
,(float*)arg
,20.0);
104 case AF_CONTROL_VOLUME_PROBE
| AF_CONTROL_GET
:
105 return af_to_dB(AF_NCH
,s
->pow
,(float*)arg
,10.0);
106 case AF_CONTROL_VOLUME_PROBE_MAX
| AF_CONTROL_GET
:
107 return af_to_dB(AF_NCH
,s
->max
,(float*)arg
,10.0);
108 case AF_CONTROL_PRE_DESTROY
:{
112 for(i
=0;i
<AF_NCH
;i
++)
114 af_to_dB(1, &m
, &m
, 10.0);
115 af_msg(AF_MSG_INFO
,"[volume] The maximum volume was %0.2fdB \n", m
);
124 static void uninit(struct af_instance_s
* af
)
132 // Filter data through filter
133 static af_data_t
* play(struct af_instance_s
* af
, af_data_t
* data
)
135 af_data_t
* c
= data
; // Current working data
136 af_volume_t
* s
= (af_volume_t
*)af
->setup
; // Setup for this instance
137 int ch
= 0; // Channel counter
138 register int nch
= c
->nch
; // Number of channels
141 // Basic operation volume control only (used on slow machines)
142 if(af
->data
->format
== (AF_FORMAT_S16_NE
)){
143 int16_t* a
= (int16_t*)c
->audio
; // Audio data
144 int len
= c
->len
/2; // Number of samples
145 for(ch
= 0; ch
< nch
; ch
++){
147 register int vol
= (int)(255.0 * s
->level
[ch
]);
148 for(i
=ch
;i
<len
;i
+=nch
){
149 register int x
= (a
[i
] * vol
) >> 8;
150 a
[i
]=clamp(x
,SHRT_MIN
,SHRT_MAX
);
155 // Machine is fast and data is floating point
156 else if(af
->data
->format
== (AF_FORMAT_FLOAT_NE
)){
157 float* a
= (float*)c
->audio
; // Audio data
158 int len
= c
->len
/4; // Number of samples
159 for(ch
= 0; ch
< nch
; ch
++){
160 // Volume control (fader)
162 float t
= 1.0 - s
->time
;
163 for(i
=ch
;i
<len
;i
+=nch
){
164 register float x
= a
[i
];
165 register float pow
= x
*x
;
166 // Check maximum power value
176 s
->pow
[ch
] = t
*s
->pow
[ch
] + pow
*s
->time
; // LP filter
177 /* Soft clipping, the sound of a dream, thanks to Jon Wattes
178 post to Musicdsp.org */
192 // Allocate memory and set function pointers
193 static int af_open(af_instance_t
* af
){
199 af
->data
=calloc(1,sizeof(af_data_t
));
200 af
->setup
=calloc(1,sizeof(af_volume_t
));
201 if(af
->data
== NULL
|| af
->setup
== NULL
)
203 // Enable volume control and set initial volume to 0dB.
204 for(i
=0;i
<AF_NCH
;i
++){
205 ((af_volume_t
*)af
->setup
)->enable
[i
] = 1;
206 ((af_volume_t
*)af
->setup
)->level
[i
] = 1.0;
211 // Description of this filter
212 af_info_t af_info_volume
= {
213 "Volume control audio filter",
217 AF_FLAGS_NOT_REENTRANT
,