Merge svn changes up to r28204
[mplayer/glamo.git] / libaf / af_volume.c
blobc06b6710a6abe2874bff44d311ace2df976af54c
1 /*=============================================================================
2 //
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.
5 //
6 // Copyright 2002 Anders Johansson ajh@atri.curtin.edu.au
7 //
8 //=============================================================================
9 */
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.
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
31 #include <inttypes.h>
32 #include <math.h>
33 #include <limits.h>
35 #include "af.h"
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
47 }af_volume_t;
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;
54 switch(cmd){
55 case AF_CONTROL_REINIT:
56 // Sanity check
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;
64 af->data->bps = 2;
66 else{
67 // Cutoff set to 10Hz for forgetting factor
68 float x = 2.0*M_PI*15.0/(float)af->data->rate;
69 float t = 2.0-cos(x);
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;
73 af->data->bps = 4;
75 return af_test_output(af,(af_data_t*)arg);
76 case AF_CONTROL_COMMAND_LINE:{
77 float v=0.0;
78 float vol[AF_NCH];
79 int i;
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;
87 return AF_OK;
88 case AF_CONTROL_VOLUME_ON_OFF | AF_CONTROL_SET:
89 memcpy(s->enable,(int*)arg,AF_NCH*sizeof(int));
90 return AF_OK;
91 case AF_CONTROL_VOLUME_ON_OFF | AF_CONTROL_GET:
92 memcpy((int*)arg,s->enable,AF_NCH*sizeof(int));
93 return AF_OK;
94 case AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_SET:
95 s->soft = *(int*)arg;
96 return AF_OK;
97 case AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_GET:
98 *(int*)arg = s->soft;
99 return AF_OK;
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:{
109 float m = 0.0;
110 int i;
111 if(!s->fast){
112 for(i=0;i<AF_NCH;i++)
113 m=max(m,s->max[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);
117 return AF_OK;
120 return AF_UNKNOWN;
123 // Deallocate memory
124 static void uninit(struct af_instance_s* af)
126 if(af->data)
127 free(af->data);
128 if(af->setup)
129 free(af->setup);
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
139 register int i = 0;
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++){
146 if(s->enable[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)
161 if(s->enable[ch]){
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
167 if(pow > s->max[ch])
168 s->max[ch] = pow;
169 // Set volume
170 x *= s->level[ch];
171 // Peak meter
172 pow = x*x;
173 if(pow > s->pow[ch])
174 s->pow[ch] = pow;
175 else
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 */
179 if(s->soft)
180 x=af_softclip(x);
181 // Hard clipping
182 else
183 x=clamp(x,-1.0,1.0);
184 a[i] = x;
189 return c;
192 // Allocate memory and set function pointers
193 static int af_open(af_instance_t* af){
194 int i = 0;
195 af->control=control;
196 af->uninit=uninit;
197 af->play=play;
198 af->mul=1;
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)
202 return AF_ERROR;
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;
208 return AF_OK;
211 // Description of this filter
212 af_info_t af_info_volume = {
213 "Volume control audio filter",
214 "volume",
215 "Anders",
217 AF_FLAGS_NOT_REENTRANT,
218 af_open