Mercurial > mplayer.hg
annotate libao2/pl_volnorm.c @ 9278:caea8ed36b48
The reason why mplayer crashes (in some cases) when using x11
output and -wid (>0) parameter is this:
Mplayer by default creates a colormap using DirectColor visual. If the
window given to mplayer uses TrueColor visual there will be an error
when mplayer sets the colormap for the window. This patch
modifies mplayer to use TrueColor visual if the window given to mplayer
uses TrueColor. Another solution is to make sure that the window given to
mplayer is created using DirectColor visual if it is supported by the
display.
Jouni Tulkki <jitulkki@cc.hut.fi>
author | arpi |
---|---|
date | Tue, 04 Feb 2003 18:31:44 +0000 |
parents | 46d21c0f36aa |
children | 12b1790038b0 |
rev | line source |
---|---|
4941 | 1 /* Normalizer plugin |
2 * | |
3 * Limitations: | |
4 * - only AFMT_S16_LE supported | |
5 * - no parameters yet => tweak the values by editing the #defines | |
6 * | |
7 * License: GPLv2 | |
8 * Author: pl <p_l@gmx.fr> (c) 2002 and beyond... | |
9 * | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
10 * Sources: some ideas from volnorm plugin for xmms |
4941 | 11 * |
12 * */ | |
13 | |
14 #define PLUGIN | |
15 | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
16 /* Values for AVG: |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
17 * 1: uses a 1 value memory and coefficients new=a*old+b*cur (with a+b=1) |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
18 * |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
19 * 2: uses several samples to smooth the variations (standard weighted mean |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
20 * on past samples) |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
21 * |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
22 * */ |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
23 #define AVG 1 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
24 |
4941 | 25 #include <stdio.h> |
26 #include <stdlib.h> | |
27 #include <inttypes.h> | |
28 #include <math.h> // for sqrt() | |
29 | |
30 #include "audio_out.h" | |
31 #include "audio_plugin.h" | |
32 #include "audio_plugin_internal.h" | |
33 #include "afmt.h" | |
34 | |
35 static ao_info_t info = { | |
36 "Volume normalizer", | |
37 "volnorm", | |
38 "pl <p_l@gmx.fr>", | |
39 "" | |
40 }; | |
41 | |
42 LIBAO_PLUGIN_EXTERN(volnorm) | |
43 | |
44 // mul is the value by which the samples are scaled | |
45 // and has to be in [MUL_MIN, MUL_MAX] | |
46 #define MUL_INIT 1.0 | |
47 #define MUL_MIN 0.1 | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
48 #define MUL_MAX 5.0 |
4941 | 49 static float mul; |
50 | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
51 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
52 #if AVG==1 |
4941 | 53 // "history" value of the filter |
54 static float lastavg; | |
55 | |
56 // SMOOTH_* must be in ]0.0, 1.0[ | |
57 // The new value accounts for SMOOTH_MUL in the value and history | |
58 #define SMOOTH_MUL 0.06 | |
59 #define SMOOTH_LASTAVG 0.06 | |
60 | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
61 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
62 #elif AVG==2 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
63 // Size of the memory array |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
64 // FIXME: should depend on the frequency of the data (should be a few seconds) |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
65 #define NSAMPLES 128 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
66 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
67 // Indicates where to write (in 0..NSAMPLES-1) |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
68 static int idx; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
69 // The array |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
70 static struct { |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
71 float avg; // average level of the sample |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
72 int32_t len; // sample size (weight) |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
73 } mem[NSAMPLES]; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
74 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
75 // If summing all the mem[].len is lower than MIN_SAMPLE_SIZE bytes, then we |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
76 // choose to ignore the computed value as it's not significant enough |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
77 // FIXME: should depend on the frequency of the data (0.5s maybe) |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
78 #define MIN_SAMPLE_SIZE 32000 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
79 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
80 #else |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
81 // Kab00m ! |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
82 #error "Unknown AVG" |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
83 #endif |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
84 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
85 |
4943
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
86 // Some limits |
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
87 #define MIN_S16 -32768 |
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
88 #define MAX_S16 32767 |
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
89 |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
90 // "Ideal" level |
4943
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
91 #define MID_S16 (MAX_S16 * 0.25) |
4941 | 92 |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
93 // Silence level |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
94 // FIXME: should be relative to the level of the samples |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
95 #define SIL_S16 (MAX_S16 * 0.01) |
4941 | 96 |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
97 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
98 // Local data |
4941 | 99 static struct { |
100 int inuse; // This plugin is in use TRUE, FALSE | |
101 int format; // sample fomat | |
102 } pl_volnorm = {0, 0}; | |
103 | |
104 | |
105 // minimal interface | |
106 static int control(int cmd,int arg){ | |
107 switch(cmd){ | |
108 case AOCONTROL_PLUGIN_SET_LEN: | |
109 return CONTROL_OK; | |
110 } | |
111 return CONTROL_UNKNOWN; | |
112 } | |
113 | |
114 // minimal interface | |
115 // open & setup audio device | |
116 // return: 1=success 0=fail | |
117 static int init(){ | |
118 switch(ao_plugin_data.format){ | |
8741
46d21c0f36aa
(nicer) endianness fix for every plugin except pl_format
colin
parents:
8218
diff
changeset
|
119 case(AFMT_S16_NE): |
4941 | 120 break; |
121 default: | |
122 fprintf(stderr,"[pl_volnorm] Audio format not yet supported.\n"); | |
123 return 0; | |
124 } | |
125 | |
126 pl_volnorm.format = ao_plugin_data.format; | |
127 pl_volnorm.inuse = 1; | |
128 | |
129 reset(); | |
130 | |
131 printf("[pl_volnorm] Normalizer plugin in use.\n"); | |
132 return 1; | |
133 } | |
134 | |
135 // close plugin | |
136 static void uninit(){ | |
137 pl_volnorm.inuse=0; | |
138 } | |
139 | |
140 // empty buffers | |
141 static void reset(){ | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
142 int i; |
4941 | 143 mul = MUL_INIT; |
144 switch(ao_plugin_data.format) { | |
8741
46d21c0f36aa
(nicer) endianness fix for every plugin except pl_format
colin
parents:
8218
diff
changeset
|
145 case(AFMT_S16_NE): |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
146 #if AVG==1 |
4941 | 147 lastavg = MID_S16; |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
148 #elif AVG==2 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
149 for(i=0; i < NSAMPLES; ++i) { |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
150 mem[i].len = 0; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
151 mem[i].avg = 0; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
152 } |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
153 idx = 0; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
154 #endif |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
155 |
4941 | 156 break; |
157 default: | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
158 fprintf(stderr,"[pl_volnorm] internal inconsistency - bugreport !\n"); |
4941 | 159 *(char *) 0 = 0; |
160 } | |
161 } | |
162 | |
163 // processes 'ao_plugin_data.len' bytes of 'data' | |
164 // called for every block of data | |
165 static int play(){ | |
166 | |
167 switch(pl_volnorm.format){ | |
8741
46d21c0f36aa
(nicer) endianness fix for every plugin except pl_format
colin
parents:
8218
diff
changeset
|
168 case(AFMT_S16_NE): { |
4941 | 169 #define CLAMP(x,m,M) do { if ((x)<(m)) (x) = (m); else if ((x)>(M)) (x) = (M); } while(0) |
170 | |
171 int16_t* data=(int16_t*)ao_plugin_data.data; | |
172 int len=ao_plugin_data.len / 2; // 16 bits samples | |
173 | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
174 int32_t i, tmp; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
175 float curavg, newavg; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
176 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
177 #if AVG==1 |
4941 | 178 float neededmul; |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
179 #elif AVG==2 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
180 float avg; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
181 int32_t totallen; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
182 #endif |
4941 | 183 |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
184 // Evaluate current samples average level |
4941 | 185 curavg = 0.0; |
186 for (i = 0; i < len ; ++i) { | |
187 tmp = data[i]; | |
188 curavg += tmp * tmp; | |
189 } | |
190 curavg = sqrt(curavg / (float) len); | |
191 | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
192 // Evaluate an adequate 'mul' coefficient based on previous state, current |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
193 // samples level, etc |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
194 #if AVG==1 |
4941 | 195 if (curavg > SIL_S16) { |
196 neededmul = MID_S16 / ( curavg * mul); | |
197 mul = (1.0 - SMOOTH_MUL) * mul + SMOOTH_MUL * neededmul; | |
198 | |
199 // Clamp the mul coefficient | |
200 CLAMP(mul, MUL_MIN, MUL_MAX); | |
201 } | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
202 #elif AVG==2 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
203 avg = 0.0; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
204 totallen = 0; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
205 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
206 for (i = 0; i < NSAMPLES; ++i) { |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
207 avg += mem[i].avg * (float) mem[i].len; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
208 totallen += mem[i].len; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
209 } |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
210 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
211 if (totallen > MIN_SAMPLE_SIZE) { |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
212 avg /= (float) totallen; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
213 if (avg >= SIL_S16) { |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
214 mul = (float) MID_S16 / avg; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
215 CLAMP(mul, MUL_MIN, MUL_MAX); |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
216 } |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
217 } |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
218 #endif |
4941 | 219 |
220 // Scale & clamp the samples | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
221 for (i = 0; i < len ; ++i) { |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
222 tmp = mul * data[i]; |
4943
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
223 CLAMP(tmp, MIN_S16, MAX_S16); |
4941 | 224 data[i] = tmp; |
225 } | |
226 | |
227 // Evaluation of newavg (not 100% accurate because of values clamping) | |
228 newavg = mul * curavg; | |
229 | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
230 // Stores computed values for future smoothing |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
231 #if AVG==1 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
232 lastavg = (1.0 - SMOOTH_LASTAVG) * lastavg + SMOOTH_LASTAVG * newavg; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
233 //printf("\rmul=%02.1f ", mul); |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
234 #elif AVG==2 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
235 mem[idx].len = len; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
236 mem[idx].avg = newavg; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
237 idx = (idx + 1) % NSAMPLES; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
238 //printf("\rmul=%02.1f (%04dKiB) ", mul, totallen/1024); |
4941 | 239 #endif |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
240 //fflush(stdout); |
4941 | 241 |
242 break; | |
243 } | |
244 default: | |
245 return 0; | |
246 } | |
247 return 1; | |
248 | |
249 } | |
250 |