Mercurial > mplayer.hg
annotate libao2/pl_volnorm.c @ 4956:84f465d2ff16
KEY_ENTER->quit binding. why doesn't 'pt_step 1' exits if no more file left?
author | arpi |
---|---|
date | Wed, 06 Mar 2002 21:59:24 +0000 |
parents | 511e8d8117e9 |
children | 6d8971d55e40 |
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 * | |
10 * Sources: some ideas from volnorm for xmms | |
11 * | |
12 * */ | |
13 | |
14 #define PLUGIN | |
15 | |
16 #include <stdio.h> | |
17 #include <stdlib.h> | |
18 #include <inttypes.h> | |
19 #include <math.h> // for sqrt() | |
20 | |
21 #include "audio_out.h" | |
22 #include "audio_plugin.h" | |
23 #include "audio_plugin_internal.h" | |
24 #include "afmt.h" | |
25 | |
26 static ao_info_t info = { | |
27 "Volume normalizer", | |
28 "volnorm", | |
29 "pl <p_l@gmx.fr>", | |
30 "" | |
31 }; | |
32 | |
33 LIBAO_PLUGIN_EXTERN(volnorm) | |
34 | |
35 // mul is the value by which the samples are scaled | |
36 // and has to be in [MUL_MIN, MUL_MAX] | |
37 #define MUL_INIT 1.0 | |
38 #define MUL_MIN 0.1 | |
39 #define MUL_MAX 15.0 | |
40 static float mul; | |
41 | |
42 // "history" value of the filter | |
43 static float lastavg; | |
44 | |
45 // SMOOTH_* must be in ]0.0, 1.0[ | |
46 // The new value accounts for SMOOTH_MUL in the value and history | |
47 #define SMOOTH_MUL 0.06 | |
48 #define SMOOTH_LASTAVG 0.06 | |
49 | |
4943
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
50 // Some limits |
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
51 #define MIN_S16 -32768 |
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
52 #define MAX_S16 32767 |
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
53 |
4941 | 54 // ideal average level |
4943
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
55 #define MID_S16 (MAX_S16 * 0.25) |
4941 | 56 |
57 // silence level | |
4943
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
58 #define SIL_S16 (MAX_S16 * 0.02) |
4941 | 59 |
60 // local data | |
61 static struct { | |
62 int inuse; // This plugin is in use TRUE, FALSE | |
63 int format; // sample fomat | |
64 } pl_volnorm = {0, 0}; | |
65 | |
66 | |
67 // minimal interface | |
68 static int control(int cmd,int arg){ | |
69 switch(cmd){ | |
70 case AOCONTROL_PLUGIN_SET_LEN: | |
71 return CONTROL_OK; | |
72 } | |
73 return CONTROL_UNKNOWN; | |
74 } | |
75 | |
76 // minimal interface | |
77 // open & setup audio device | |
78 // return: 1=success 0=fail | |
79 static int init(){ | |
80 switch(ao_plugin_data.format){ | |
81 case(AFMT_S16_LE): | |
82 break; | |
83 default: | |
84 fprintf(stderr,"[pl_volnorm] Audio format not yet supported.\n"); | |
85 return 0; | |
86 } | |
87 | |
88 pl_volnorm.format = ao_plugin_data.format; | |
89 pl_volnorm.inuse = 1; | |
90 | |
91 reset(); | |
92 | |
93 printf("[pl_volnorm] Normalizer plugin in use.\n"); | |
94 return 1; | |
95 } | |
96 | |
97 // close plugin | |
98 static void uninit(){ | |
99 pl_volnorm.inuse=0; | |
100 } | |
101 | |
102 // empty buffers | |
103 static void reset(){ | |
104 mul = MUL_INIT; | |
105 switch(ao_plugin_data.format) { | |
106 case(AFMT_S16_LE): | |
107 lastavg = MID_S16; | |
108 break; | |
109 default: | |
110 fprintf(stderr,"[pl_volnorm] internal inconsistency - please bugreport.\n"); | |
111 *(char *) 0 = 0; | |
112 } | |
113 } | |
114 | |
115 // processes 'ao_plugin_data.len' bytes of 'data' | |
116 // called for every block of data | |
117 static int play(){ | |
118 | |
119 switch(pl_volnorm.format){ | |
120 case(AFMT_S16_LE): { | |
121 | |
122 #define CLAMP(x,m,M) do { if ((x)<(m)) (x) = (m); else if ((x)>(M)) (x) = (M); } while(0) | |
123 | |
124 int16_t* data=(int16_t*)ao_plugin_data.data; | |
125 int len=ao_plugin_data.len / 2; // 16 bits samples | |
126 | |
127 int32_t i; | |
128 register int32_t tmp; | |
129 register float curavg; | |
130 float newavg; | |
131 float neededmul; | |
132 | |
133 // average of the current samples | |
134 curavg = 0.0; | |
135 for (i = 0; i < len ; ++i) { | |
136 tmp = data[i]; | |
137 curavg += tmp * tmp; | |
138 } | |
139 curavg = sqrt(curavg / (float) len); | |
140 | |
141 if (curavg > SIL_S16) { | |
142 neededmul = MID_S16 / ( curavg * mul); | |
143 mul = (1.0 - SMOOTH_MUL) * mul + SMOOTH_MUL * neededmul; | |
144 | |
145 // Clamp the mul coefficient | |
146 CLAMP(mul, MUL_MIN, MUL_MAX); | |
147 } | |
148 | |
149 // Scale & clamp the samples | |
150 for (i=0; i < len ; ++i) { | |
151 tmp = data[i] * mul; | |
4943
511e8d8117e9
proper bsd fix & preventive fix for other archs w/o INT_MAX
pl
parents:
4942
diff
changeset
|
152 CLAMP(tmp, MIN_S16, MAX_S16); |
4941 | 153 data[i] = tmp; |
154 } | |
155 | |
156 // Evaluation of newavg (not 100% accurate because of values clamping) | |
157 newavg = mul * curavg; | |
158 | |
159 #if 0 | |
160 printf("time = %d len = %d curavg = %6.0f lastavg = %6.0f newavg = %6.0f\n" | |
161 " needed_m = %2.2f m = %2.2f\n\n", | |
162 time(NULL), len, curavg, lastavg, newavg, neededmul, mul); | |
163 #endif | |
164 | |
165 lastavg = (1.0 - SMOOTH_LASTAVG) * lastavg + SMOOTH_LASTAVG * newavg; | |
166 | |
167 break; | |
168 } | |
169 default: | |
170 return 0; | |
171 } | |
172 return 1; | |
173 | |
174 } | |
175 |