Mercurial > mplayer.hg
comparison libao2/pl_volnorm.c @ 4941:9a468a190c4c
volume normalizer plugin support
author | pl |
---|---|
date | Tue, 05 Mar 2002 09:17:36 +0000 |
parents | |
children | acdff5b36ea9 |
comparison
equal
deleted
inserted
replaced
4940:098970f06dc2 | 4941:9a468a190c4c |
---|---|
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 | |
50 // ideal average level | |
51 #define MID_S16 (INT16_MAX * 0.25) | |
52 | |
53 // silence level | |
54 #define SIL_S16 (INT16_MAX * 0.02) | |
55 | |
56 // local data | |
57 static struct { | |
58 int inuse; // This plugin is in use TRUE, FALSE | |
59 int format; // sample fomat | |
60 } pl_volnorm = {0, 0}; | |
61 | |
62 | |
63 // minimal interface | |
64 static int control(int cmd,int arg){ | |
65 switch(cmd){ | |
66 case AOCONTROL_PLUGIN_SET_LEN: | |
67 return CONTROL_OK; | |
68 } | |
69 return CONTROL_UNKNOWN; | |
70 } | |
71 | |
72 // minimal interface | |
73 // open & setup audio device | |
74 // return: 1=success 0=fail | |
75 static int init(){ | |
76 switch(ao_plugin_data.format){ | |
77 case(AFMT_S16_LE): | |
78 break; | |
79 default: | |
80 fprintf(stderr,"[pl_volnorm] Audio format not yet supported.\n"); | |
81 return 0; | |
82 } | |
83 | |
84 pl_volnorm.format = ao_plugin_data.format; | |
85 pl_volnorm.inuse = 1; | |
86 | |
87 reset(); | |
88 | |
89 printf("[pl_volnorm] Normalizer plugin in use.\n"); | |
90 return 1; | |
91 } | |
92 | |
93 // close plugin | |
94 static void uninit(){ | |
95 pl_volnorm.inuse=0; | |
96 } | |
97 | |
98 // empty buffers | |
99 static void reset(){ | |
100 mul = MUL_INIT; | |
101 switch(ao_plugin_data.format) { | |
102 case(AFMT_S16_LE): | |
103 lastavg = MID_S16; | |
104 break; | |
105 default: | |
106 fprintf(stderr,"[pl_volnorm] internal inconsistency - please bugreport.\n"); | |
107 *(char *) 0 = 0; | |
108 } | |
109 } | |
110 | |
111 // processes 'ao_plugin_data.len' bytes of 'data' | |
112 // called for every block of data | |
113 static int play(){ | |
114 | |
115 switch(pl_volnorm.format){ | |
116 case(AFMT_S16_LE): { | |
117 | |
118 #define CLAMP(x,m,M) do { if ((x)<(m)) (x) = (m); else if ((x)>(M)) (x) = (M); } while(0) | |
119 | |
120 int16_t* data=(int16_t*)ao_plugin_data.data; | |
121 int len=ao_plugin_data.len / 2; // 16 bits samples | |
122 | |
123 int32_t i; | |
124 register int32_t tmp; | |
125 register float curavg; | |
126 float newavg; | |
127 float neededmul; | |
128 | |
129 // average of the current samples | |
130 curavg = 0.0; | |
131 for (i = 0; i < len ; ++i) { | |
132 tmp = data[i]; | |
133 curavg += tmp * tmp; | |
134 } | |
135 curavg = sqrt(curavg / (float) len); | |
136 | |
137 if (curavg > SIL_S16) { | |
138 neededmul = MID_S16 / ( curavg * mul); | |
139 mul = (1.0 - SMOOTH_MUL) * mul + SMOOTH_MUL * neededmul; | |
140 | |
141 // Clamp the mul coefficient | |
142 CLAMP(mul, MUL_MIN, MUL_MAX); | |
143 } | |
144 | |
145 // Scale & clamp the samples | |
146 for (i=0; i < len ; ++i) { | |
147 tmp = data[i] * mul; | |
148 CLAMP(tmp, INT16_MIN, INT16_MAX); | |
149 data[i] = tmp; | |
150 } | |
151 | |
152 // Evaluation of newavg (not 100% accurate because of values clamping) | |
153 newavg = mul * curavg; | |
154 | |
155 #if 0 | |
156 printf("time = %d len = %d curavg = %6.0f lastavg = %6.0f newavg = %6.0f\n" | |
157 " needed_m = %2.2f m = %2.2f\n\n", | |
158 time(NULL), len, curavg, lastavg, newavg, neededmul, mul); | |
159 #endif | |
160 | |
161 lastavg = (1.0 - SMOOTH_LASTAVG) * lastavg + SMOOTH_LASTAVG * newavg; | |
162 | |
163 break; | |
164 } | |
165 default: | |
166 return 0; | |
167 } | |
168 return 1; | |
169 | |
170 } | |
171 |