Mercurial > mplayer.hg
annotate libaf/af_volume.c @ 23028:57f56d8e182e
Add shift_[xy] (vector that is added to the glyph before transformation) to
bitmap glyph key. Result of rotation depends on them because of perspective
transformation. They are only set when some rotation take place.
author | eugeni |
---|---|
date | Fri, 20 Apr 2007 23:19:23 +0000 |
parents | 904e3f3f8bee |
children | b2402b4f0afa |
rev | line source |
---|---|
8607 | 1 /*============================================================================= |
2 // | |
13602
14090f7300a8
The full name of the GPL is GNU General Public License.
diego
parents:
12641
diff
changeset
|
3 // This software has been released under the terms of the GNU General Public |
8607 | 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 */ | |
10 | |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
11 /* This audio filter changes the volume of the sound, and can be used |
8607 | 12 when the mixer doesn't support the PCM channel. It can handle |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
13 between 1 and 6 channels. The volume can be adjusted between -60dB |
8607 | 14 to +20dB and is set on a per channels basis. The is accessed through |
15 AF_CONTROL_VOLUME_LEVEL. | |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
16 |
8607 | 17 The filter has support for soft-clipping, it is enabled by |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
18 AF_CONTROL_VOLUME_SOFTCLIPP. It has also a probing feature which |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
19 can be used to measure the power in the audio stream, both an |
8607 | 20 instantaneous value and the maximum value can be probed. The |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
21 probing is enable by AF_CONTROL_VOLUME_PROBE_ON_OFF and is done on a |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
22 per channel basis. The result from the probing is obtained using |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
23 AF_CONTROL_VOLUME_PROBE_GET and AF_CONTROL_VOLUME_PROBE_GET_MAX. The |
8607 | 24 probed values are calculated in dB. |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
25 */ |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
26 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
27 #include <stdio.h> |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
28 #include <stdlib.h> |
8623
440301fef3fe
Added/reordered #includes to silence warnings about "implicit declaration".
rathann
parents:
8607
diff
changeset
|
29 #include <string.h> |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
30 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
31 #include <inttypes.h> |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
32 #include <math.h> |
8607 | 33 #include <limits.h> |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
34 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
35 #include "af.h" |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
36 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
37 // Data for specific instances of this filter |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
38 typedef struct af_volume_s |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
39 { |
8607 | 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 | |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
47 }af_volume_t; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
48 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
49 // Initialization and runtime control |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
50 static int control(struct af_instance_s* af, int cmd, void* arg) |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
51 { |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
52 af_volume_t* s = (af_volume_t*)af->setup; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
53 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
54 switch(cmd){ |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
55 case AF_CONTROL_REINIT: |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
56 // Sanity check |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
57 if(!arg) return AF_ERROR; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
58 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
59 af->data->rate = ((af_data_t*)arg)->rate; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
60 af->data->nch = ((af_data_t*)arg)->nch; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
61 |
14245 | 62 if(s->fast && (((af_data_t*)arg)->format != (AF_FORMAT_FLOAT_NE))){ |
63 af->data->format = AF_FORMAT_S16_NE; | |
8607 | 64 af->data->bps = 2; |
65 } | |
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); | |
14245 | 72 af->data->format = AF_FORMAT_FLOAT_NE; |
8607 | 73 af->data->bps = 4; |
74 } | |
75 return af_test_output(af,(af_data_t*)arg); | |
7993
ea0680d87f3f
Changing the behavour of the commandline parameter -af to conform with -vop. Adding new commanline parameter -af-adv for advanced af options. Adding changes to volume control to support commandline parameters.
anders
parents:
7974
diff
changeset
|
76 case AF_CONTROL_COMMAND_LINE:{ |
14068
f1372a7d9ee9
very old 10l, discussed a long time ago but never fixed (default should be same vol, not -10 dB)
rfelker
parents:
13602
diff
changeset
|
77 float v=0.0; |
8607 | 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); | |
7993
ea0680d87f3f
Changing the behavour of the commandline parameter -af to conform with -vop. Adding new commanline parameter -af-adv for advanced af options. Adding changes to volume control to support commandline parameters.
anders
parents:
7974
diff
changeset
|
83 } |
8607 | 84 case AF_CONTROL_POST_CREATE: |
8868
398e3fb7c103
10l bug for float conversion control + feature fix in volume control
anders
parents:
8867
diff
changeset
|
85 s->fast = ((((af_cfg_t*)arg)->force & AF_INIT_FORMAT_MASK) == |
398e3fb7c103
10l bug for float conversion control + feature fix in volume control
anders
parents:
8867
diff
changeset
|
86 AF_INIT_FLOAT) ? 0 : 1; |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
87 return AF_OK; |
8607 | 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); | |
8186 | 108 case AF_CONTROL_PRE_DESTROY:{ |
109 float m = 0.0; | |
110 int i; | |
8868
398e3fb7c103
10l bug for float conversion control + feature fix in volume control
anders
parents:
8867
diff
changeset
|
111 if(!s->fast){ |
398e3fb7c103
10l bug for float conversion control + feature fix in volume control
anders
parents:
8867
diff
changeset
|
112 for(i=0;i<AF_NCH;i++) |
398e3fb7c103
10l bug for float conversion control + feature fix in volume control
anders
parents:
8867
diff
changeset
|
113 m=max(m,s->max[i]); |
12641
61f3fce1e933
remove the latest use of log10 in favor of the better af_to_dB helper function, patch by Reimar Doffinger
alex
parents:
9043
diff
changeset
|
114 af_to_dB(1, &m, &m, 10.0); |
61f3fce1e933
remove the latest use of log10 in favor of the better af_to_dB helper function, patch by Reimar Doffinger
alex
parents:
9043
diff
changeset
|
115 af_msg(AF_MSG_INFO,"[volume] The maximum volume was %0.2fdB \n", m); |
8868
398e3fb7c103
10l bug for float conversion control + feature fix in volume control
anders
parents:
8867
diff
changeset
|
116 } |
8186 | 117 return AF_OK; |
118 } | |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
119 } |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
120 return AF_UNKNOWN; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
121 } |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
122 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
123 // Deallocate memory |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
124 static void uninit(struct af_instance_s* af) |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
125 { |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
126 if(af->data) |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
127 free(af->data); |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
128 if(af->setup) |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
129 free(af->setup); |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
130 } |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
131 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
132 // Filter data through filter |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
133 static af_data_t* play(struct af_instance_s* af, af_data_t* data) |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
134 { |
8607 | 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; | |
140 | |
141 // Basic operation volume control only (used on slow machines) | |
14245 | 142 if(af->data->format == (AF_FORMAT_S16_NE)){ |
8607 | 143 int16_t* a = (int16_t*)c->audio; // Audio data |
144 int len = c->len/2; // Number of samples | |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
145 for(ch = 0; ch < nch ; ch++){ |
8607 | 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); | |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
151 } |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
152 } |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
153 } |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
154 } |
8607 | 155 // Machine is fast and data is floating point |
14245 | 156 else if(af->data->format == (AF_FORMAT_FLOAT_NE)){ |
8607 | 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 */ | |
14623 | 179 if(s->soft) |
180 x=af_softclip(x); | |
8607 | 181 // Hard clipping |
182 else | |
183 x=clamp(x,-1.0,1.0); | |
184 a[i] = x; | |
185 } | |
186 } | |
187 } | |
188 } | |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
189 return c; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
190 } |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
191 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
192 // Allocate memory and set function pointers |
22746
fd6f824ef894
Rename open to af_open so as not to conflict with a previous header definition.
diego
parents:
14623
diff
changeset
|
193 static int af_open(af_instance_t* af){ |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
194 int i = 0; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
195 af->control=control; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
196 af->uninit=uninit; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
197 af->play=play; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
198 af->mul.n=1; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
199 af->mul.d=1; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
200 af->data=calloc(1,sizeof(af_data_t)); |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
201 af->setup=calloc(1,sizeof(af_volume_t)); |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
202 if(af->data == NULL || af->setup == NULL) |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
203 return AF_ERROR; |
9043
1d75a7ecf3b8
Changing initial volume level to 0dB after loud intensive complaints
anders
parents:
8868
diff
changeset
|
204 // Enable volume control and set initial volume to 0dB. |
8607 | 205 for(i=0;i<AF_NCH;i++){ |
206 ((af_volume_t*)af->setup)->enable[i] = 1; | |
9043
1d75a7ecf3b8
Changing initial volume level to 0dB after loud intensive complaints
anders
parents:
8868
diff
changeset
|
207 ((af_volume_t*)af->setup)->level[i] = 1.0; |
8607 | 208 } |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
209 return AF_OK; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
210 } |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
211 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
212 // Description of this filter |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
213 af_info_t af_info_volume = { |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
214 "Volume control audio filter", |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
215 "volume", |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
216 "Anders", |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
217 "", |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
218 AF_FLAGS_NOT_REENTRANT, |
22746
fd6f824ef894
Rename open to af_open so as not to conflict with a previous header definition.
diego
parents:
14623
diff
changeset
|
219 af_open |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
220 }; |