Mercurial > mplayer.hg
annotate libao2/pl_volnorm.c @ 6110:7bea806b9c5f
Improvment for spu subtitles.
Removed the integreted spudec in vobsub.
Various cleanup/bugfix in vobsub (no more auto palette when a true one is
here)
HW spu rendering moved in spudec because we first need to reassable the
packet before sending them to the hw.
Spudec is now created only if nedded.
author | albeu |
---|---|
date | Fri, 17 May 2002 23:47:27 +0000 |
parents | 6d8971d55e40 |
children | 48deec5d2050 |
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){ | |
119 case(AFMT_S16_LE): | |
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) { | |
145 case(AFMT_S16_LE): | |
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){ | |
168 case(AFMT_S16_LE): { | |
169 | |
170 #define CLAMP(x,m,M) do { if ((x)<(m)) (x) = (m); else if ((x)>(M)) (x) = (M); } while(0) | |
171 | |
172 int16_t* data=(int16_t*)ao_plugin_data.data; | |
173 int len=ao_plugin_data.len / 2; // 16 bits samples | |
174 | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
175 int32_t i, tmp; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
176 float curavg, newavg; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
177 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
178 #if AVG==1 |
4941 | 179 float neededmul; |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
180 #elif AVG==2 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
181 float avg; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
182 int32_t totallen; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
183 #endif |
4941 | 184 |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
185 // Evaluate current samples average level |
4941 | 186 curavg = 0.0; |
187 for (i = 0; i < len ; ++i) { | |
188 tmp = data[i]; | |
189 curavg += tmp * tmp; | |
190 } | |
191 curavg = sqrt(curavg / (float) len); | |
192 | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
193 // 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
|
194 // samples level, etc |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
195 #if AVG==1 |
4941 | 196 if (curavg > SIL_S16) { |
197 neededmul = MID_S16 / ( curavg * mul); | |
198 mul = (1.0 - SMOOTH_MUL) * mul + SMOOTH_MUL * neededmul; | |
199 | |
200 // Clamp the mul coefficient | |
201 CLAMP(mul, MUL_MIN, MUL_MAX); | |
202 } | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
203 #elif AVG==2 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
204 avg = 0.0; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
205 totallen = 0; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
206 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
207 for (i = 0; i < NSAMPLES; ++i) { |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
208 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
|
209 totallen += mem[i].len; |
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 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
212 if (totallen > MIN_SAMPLE_SIZE) { |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
213 avg /= (float) totallen; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
214 if (avg >= SIL_S16) { |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
215 mul = (float) MID_S16 / avg; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
216 CLAMP(mul, MUL_MIN, MUL_MAX); |
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 } |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
219 #endif |
4941 | 220 |
221 // Scale & clamp the samples | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
222 for (i = 0; i < len ; ++i) { |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
223 tmp = mul * data[i]; |
4943
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
224 CLAMP(tmp, MIN_S16, MAX_S16); |
4941 | 225 data[i] = tmp; |
226 } | |
227 | |
228 // Evaluation of newavg (not 100% accurate because of values clamping) | |
229 newavg = mul * curavg; | |
230 | |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
231 // Stores computed values for future smoothing |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
232 #if AVG==1 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
233 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
|
234 //printf("\rmul=%02.1f ", mul); |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
235 #elif AVG==2 |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
236 mem[idx].len = len; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
237 mem[idx].avg = newavg; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
238 idx = (idx + 1) % NSAMPLES; |
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
239 //printf("\rmul=%02.1f (%04dKiB) ", mul, totallen/1024); |
4941 | 240 #endif |
5025
6d8971d55e40
new smoothing method ('#define AVG 2' to enable'n'test it)
pl
parents:
4943
diff
changeset
|
241 //fflush(stdout); |
4941 | 242 |
243 break; | |
244 } | |
245 default: | |
246 return 0; | |
247 } | |
248 return 1; | |
249 | |
250 } | |
251 |