Mercurial > mplayer.hg
annotate libaf/af_volume.c @ 17588:79081ba52e00
Move the v{Y,C}CoeffsBank vectors into the SwsContext, filling them in just
once when the scaler is initialized, instead of building them and freeing
them over and over. This gives massive performance improvements.
patch by Alan Curry, pacman*at*TheWorld*dot*com
author | diego |
---|---|
date | Sat, 11 Feb 2006 14:16:10 +0000 |
parents | 108fcc2e5d01 |
children | fd6f824ef894 |
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 <unistd.h> |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
32 #include <inttypes.h> |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
33 #include <math.h> |
8607 | 34 #include <limits.h> |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
35 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
36 #include "af.h" |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
37 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
38 // Data for specific instances of this filter |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
39 typedef struct af_volume_s |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
40 { |
8607 | 41 int enable[AF_NCH]; // Enable/disable / channel |
42 float pow[AF_NCH]; // Estimated power level [dB] | |
43 float max[AF_NCH]; // Max Power level [dB] | |
44 float level[AF_NCH]; // Gain level for each channel | |
45 float time; // Forgetting factor for power estimate | |
46 int soft; // Enable/disable soft clipping | |
47 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
|
48 }af_volume_t; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
49 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
50 // Initialization and runtime control |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
51 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
|
52 { |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
53 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
|
54 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
55 switch(cmd){ |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
56 case AF_CONTROL_REINIT: |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
57 // Sanity check |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
58 if(!arg) return AF_ERROR; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
59 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
60 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
|
61 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
|
62 |
14245 | 63 if(s->fast && (((af_data_t*)arg)->format != (AF_FORMAT_FLOAT_NE))){ |
64 af->data->format = AF_FORMAT_S16_NE; | |
8607 | 65 af->data->bps = 2; |
66 } | |
67 else{ | |
68 // Cutoff set to 10Hz for forgetting factor | |
69 float x = 2.0*M_PI*15.0/(float)af->data->rate; | |
70 float t = 2.0-cos(x); | |
71 s->time = 1.0 - (t - sqrt(t*t - 1)); | |
72 af_msg(AF_MSG_DEBUG0,"[volume] Forgetting factor = %0.5f\n",s->time); | |
14245 | 73 af->data->format = AF_FORMAT_FLOAT_NE; |
8607 | 74 af->data->bps = 4; |
75 } | |
76 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
|
77 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
|
78 float v=0.0; |
8607 | 79 float vol[AF_NCH]; |
80 int i; | |
81 sscanf((char*)arg,"%f:%i", &v, &s->soft); | |
82 for(i=0;i<AF_NCH;i++) vol[i]=v; | |
83 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
|
84 } |
8607 | 85 case AF_CONTROL_POST_CREATE: |
8868
398e3fb7c103
10l bug for float conversion control + feature fix in volume control
anders
parents:
8867
diff
changeset
|
86 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
|
87 AF_INIT_FLOAT) ? 0 : 1; |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
88 return AF_OK; |
8607 | 89 case AF_CONTROL_VOLUME_ON_OFF | AF_CONTROL_SET: |
90 memcpy(s->enable,(int*)arg,AF_NCH*sizeof(int)); | |
91 return AF_OK; | |
92 case AF_CONTROL_VOLUME_ON_OFF | AF_CONTROL_GET: | |
93 memcpy((int*)arg,s->enable,AF_NCH*sizeof(int)); | |
94 return AF_OK; | |
95 case AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_SET: | |
96 s->soft = *(int*)arg; | |
97 return AF_OK; | |
98 case AF_CONTROL_VOLUME_SOFTCLIP | AF_CONTROL_GET: | |
99 *(int*)arg = s->soft; | |
100 return AF_OK; | |
101 case AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET: | |
102 return af_from_dB(AF_NCH,(float*)arg,s->level,20.0,-200.0,60.0); | |
103 case AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_GET: | |
104 return af_to_dB(AF_NCH,s->level,(float*)arg,20.0); | |
105 case AF_CONTROL_VOLUME_PROBE | AF_CONTROL_GET: | |
106 return af_to_dB(AF_NCH,s->pow,(float*)arg,10.0); | |
107 case AF_CONTROL_VOLUME_PROBE_MAX | AF_CONTROL_GET: | |
108 return af_to_dB(AF_NCH,s->max,(float*)arg,10.0); | |
8186 | 109 case AF_CONTROL_PRE_DESTROY:{ |
110 float m = 0.0; | |
111 int i; | |
8868
398e3fb7c103
10l bug for float conversion control + feature fix in volume control
anders
parents:
8867
diff
changeset
|
112 if(!s->fast){ |
398e3fb7c103
10l bug for float conversion control + feature fix in volume control
anders
parents:
8867
diff
changeset
|
113 for(i=0;i<AF_NCH;i++) |
398e3fb7c103
10l bug for float conversion control + feature fix in volume control
anders
parents:
8867
diff
changeset
|
114 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
|
115 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
|
116 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
|
117 } |
8186 | 118 return AF_OK; |
119 } | |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
120 } |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
121 return AF_UNKNOWN; |
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 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
124 // Deallocate memory |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
125 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
|
126 { |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
127 if(af->data) |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
128 free(af->data); |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
129 if(af->setup) |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
130 free(af->setup); |
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 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
133 // Filter data through filter |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
134 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
|
135 { |
8607 | 136 af_data_t* c = data; // Current working data |
137 af_volume_t* s = (af_volume_t*)af->setup; // Setup for this instance | |
138 int ch = 0; // Channel counter | |
139 register int nch = c->nch; // Number of channels | |
140 register int i = 0; | |
141 | |
142 // Basic operation volume control only (used on slow machines) | |
14245 | 143 if(af->data->format == (AF_FORMAT_S16_NE)){ |
8607 | 144 int16_t* a = (int16_t*)c->audio; // Audio data |
145 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
|
146 for(ch = 0; ch < nch ; ch++){ |
8607 | 147 if(s->enable[ch]){ |
148 register int vol = (int)(255.0 * s->level[ch]); | |
149 for(i=ch;i<len;i+=nch){ | |
150 register int x = (a[i] * vol) >> 8; | |
151 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
|
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 } |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
155 } |
8607 | 156 // Machine is fast and data is floating point |
14245 | 157 else if(af->data->format == (AF_FORMAT_FLOAT_NE)){ |
8607 | 158 float* a = (float*)c->audio; // Audio data |
159 int len = c->len/4; // Number of samples | |
160 for(ch = 0; ch < nch ; ch++){ | |
161 // Volume control (fader) | |
162 if(s->enable[ch]){ | |
163 float t = 1.0 - s->time; | |
164 for(i=ch;i<len;i+=nch){ | |
165 register float x = a[i]; | |
166 register float pow = x*x; | |
167 // Check maximum power value | |
168 if(pow > s->max[ch]) | |
169 s->max[ch] = pow; | |
170 // Set volume | |
171 x *= s->level[ch]; | |
172 // Peak meter | |
173 pow = x*x; | |
174 if(pow > s->pow[ch]) | |
175 s->pow[ch] = pow; | |
176 else | |
177 s->pow[ch] = t*s->pow[ch] + pow*s->time; // LP filter | |
178 /* Soft clipping, the sound of a dream, thanks to Jon Wattes | |
179 post to Musicdsp.org */ | |
14623 | 180 if(s->soft) |
181 x=af_softclip(x); | |
8607 | 182 // Hard clipping |
183 else | |
184 x=clamp(x,-1.0,1.0); | |
185 a[i] = x; | |
186 } | |
187 } | |
188 } | |
189 } | |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
190 return c; |
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 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
193 // Allocate memory and set function pointers |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
194 static int open(af_instance_t* af){ |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
195 int i = 0; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
196 af->control=control; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
197 af->uninit=uninit; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
198 af->play=play; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
199 af->mul.n=1; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
200 af->mul.d=1; |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
201 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
|
202 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
|
203 if(af->data == NULL || af->setup == NULL) |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
204 return AF_ERROR; |
9043
1d75a7ecf3b8
Changing initial volume level to 0dB after loud intensive complaints
anders
parents:
8868
diff
changeset
|
205 // Enable volume control and set initial volume to 0dB. |
8607 | 206 for(i=0;i<AF_NCH;i++){ |
207 ((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
|
208 ((af_volume_t*)af->setup)->level[i] = 1.0; |
8607 | 209 } |
7745
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
210 return AF_OK; |
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 |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
213 // Description of this filter |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
214 af_info_t af_info_volume = { |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
215 "Volume control audio filter", |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
216 "volume", |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
217 "Anders", |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
218 "", |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
219 AF_FLAGS_NOT_REENTRANT, |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
220 open |
1d3a3dc1f488
Adding volume control and moving control() call parameters to a seperate file
anders
parents:
diff
changeset
|
221 }; |