1 /* libSoX effect: stats (c) 2009 robs@users.sourceforge.net
3 * This library is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as published by
5 * the Free Software Foundation; either version 2.1 of the License, or (at
6 * your option) any later version.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11 * General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 int scale_bits
, hex_bits
;
24 double time_constant
, scale
;
26 double last
, sigma_x
, sigma_x2
, avg_sigma_x2
, min_sigma_x2
, max_sigma_x2
;
27 double min
, max
, mult
, min_run
, min_runs
, max_run
, max_runs
;
28 off_t num_samples
, tc_samples
, min_count
, max_count
;
32 static int getopts(sox_effect_t
* effp
, int argc
, char **argv
)
34 priv_t
* p
= (priv_t
*)effp
->priv
;
36 lsx_getopt_t optstate
;
37 lsx_getopt_init(argc
, argv
, "+x:b:w:s:", NULL
, lsx_getopt_flag_none
, 1, &optstate
);
39 p
->time_constant
= .05;
41 while ((c
= lsx_getopt(&optstate
)) != -1) switch (c
) {
42 GETOPT_NUMERIC(optstate
, 'x', hex_bits
, 2 , 32)
43 GETOPT_NUMERIC(optstate
, 'b', scale_bits
, 2 , 32)
44 GETOPT_NUMERIC(optstate
, 'w', time_constant
, .01 , 10)
45 GETOPT_NUMERIC(optstate
, 's', scale
, -99, 99)
46 default: lsx_fail("invalid option `-%c'", optstate
.opt
); return lsx_usage(effp
);
49 p
->scale_bits
= p
->hex_bits
;
50 return optstate
.ind
!= argc
? lsx_usage(effp
) : SOX_SUCCESS
;
53 static int start(sox_effect_t
* effp
)
55 priv_t
* p
= (priv_t
*)effp
->priv
;
58 p
->mult
= exp((-1 / p
->time_constant
/ effp
->in_signal
.rate
));
59 p
->tc_samples
= 5 * p
->time_constant
* effp
->in_signal
.rate
+ .5;
60 p
->sigma_x
= p
->sigma_x2
= p
->avg_sigma_x2
= p
->max_sigma_x2
= 0;
61 p
->min
= p
->min_sigma_x2
= 2;
68 static int flow(sox_effect_t
* effp
, const sox_sample_t
* ibuf
,
69 sox_sample_t
* obuf
, size_t * ilen
, size_t * olen
)
71 priv_t
* p
= (priv_t
*)effp
->priv
;
72 size_t len
= *ilen
= *olen
= min(*ilen
, *olen
);
73 memcpy(obuf
, ibuf
, len
* sizeof(*obuf
));
75 for (; len
--; ++ibuf
, ++p
->num_samples
) {
76 double d
= SOX_SAMPLE_TO_FLOAT_64BIT(*ibuf
,);
79 p
->min
= d
, p
->min_count
= 1, p
->min_run
= 1, p
->min_runs
= 0;
80 else if (d
== p
->min
) {
82 p
->min_run
= d
== p
->last
? p
->min_run
+ 1 : 1;
84 else if (p
->last
== p
->min
)
85 p
->min_runs
+= sqr(p
->min_run
);
88 p
->max
= d
, p
->max_count
= 1, p
->max_run
= 1, p
->max_runs
= 0;
89 else if (d
== p
->max
) {
91 p
->max_run
= d
== p
->last
? p
->max_run
+ 1 : 1;
93 else if (p
->last
== p
->max
)
94 p
->max_runs
+= sqr(p
->max_run
);
97 p
->sigma_x2
+= sqr(d
);
98 p
->avg_sigma_x2
= p
->avg_sigma_x2
* p
->mult
+ (1 - p
->mult
) * sqr(d
);
100 if (p
->num_samples
>= p
->tc_samples
) {
101 if (p
->avg_sigma_x2
> p
->max_sigma_x2
)
102 p
->max_sigma_x2
= p
->avg_sigma_x2
;
103 if (p
->avg_sigma_x2
< p
->min_sigma_x2
)
104 p
->min_sigma_x2
= p
->avg_sigma_x2
;
112 static int drain(sox_effect_t
* effp
, sox_sample_t
* obuf
, size_t * olen
)
114 priv_t
* p
= (priv_t
*)effp
->priv
;
116 if (p
->last
== p
->min
)
117 p
->min_runs
+= sqr(p
->min_run
);
118 if (p
->last
== p
->max
)
119 p
->max_runs
+= sqr(p
->max_run
);
121 (void)obuf
, *olen
= 0;
125 static unsigned bit_depth(uint32_t mask
, double min
, double max
, unsigned * x
)
128 unsigned result
= 32, dummy
= 0;
130 for (; result
&& !(mask
& 1); --result
, mask
>>= 1);
133 min
= -fmax(fabs(min
), fabs(max
));
134 mask
= SOX_FLOAT_64BIT_TO_SAMPLE(min
, dummy
) << 1;
135 for (; result
&& (mask
& SOX_SAMPLE_MIN
); --result
, mask
<<= 1);
139 static void output(priv_t
const * p
, double x
)
142 unsigned mult
= 1 << (p
->scale_bits
- 1);
144 x
= floor(x
* mult
+ .5);
145 i
= min(x
, mult
- 1.);
149 sprintf(buf
, "%x", -i
);
150 fprintf(stderr
, " %*c%s", 9 - (int)strlen(buf
), '-', buf
);
152 else fprintf(stderr
, " %9x", i
);
153 else fprintf(stderr
, " %9i", i
);
155 else fprintf(stderr
, " %9.*f", fabs(p
->scale
) < 10 ? 6 : 5, p
->scale
* x
);
158 static int stop(sox_effect_t
* effp
)
160 priv_t
* p
= (priv_t
*)effp
->priv
;
163 double min_runs
= 0, max_count
= 0, min
= 2, max
= -2, max_sigma_x
= 0, sigma_x
= 0, sigma_x2
= 0, min_sigma_x2
= 2, max_sigma_x2
= 0, avg_peak
= 0;
164 off_t num_samples
= 0, min_count
= 0, max_runs
= 0;
166 unsigned b1
, b2
, i
, n
= effp
->flows
> 1 ? effp
->flows
: 0;
168 for (i
= 0; i
< effp
->flows
; ++i
) {
169 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
170 min
= min(min
, q
->min
);
171 max
= max(max
, q
->max
);
172 if (q
->num_samples
< q
->tc_samples
)
173 q
->min_sigma_x2
= q
->max_sigma_x2
= q
->sigma_x2
/ q
->num_samples
;
174 min_sigma_x2
= min(min_sigma_x2
, q
->min_sigma_x2
);
175 max_sigma_x2
= max(max_sigma_x2
, q
->max_sigma_x2
);
176 sigma_x
+= q
->sigma_x
;
177 sigma_x2
+= q
->sigma_x2
;
178 num_samples
+= q
->num_samples
;
180 if (fabs(q
->sigma_x
) > fabs(max_sigma_x
))
181 max_sigma_x
= q
->sigma_x
;
182 min_count
+= q
->min_count
;
183 min_runs
+= q
->min_runs
;
184 max_count
+= q
->max_count
;
185 max_runs
+= q
->max_runs
;
186 avg_peak
+= max(-q
->min
, q
->max
);
188 avg_peak
/= effp
->flows
;
191 lsx_warn("no audio");
196 fprintf(stderr
, " Overall Left Right\n");
198 fprintf(stderr
, " Overall");
199 for (i
= 0; i
< n
; ++i
)
200 fprintf(stderr
, " Ch%-3i", i
+ 1);
201 fprintf(stderr
, "\n");
204 fprintf(stderr
, "DC offset ");
205 output(p
, max_sigma_x
/ p
->num_samples
);
206 for (i
= 0; i
< n
; ++i
) {
207 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
208 output(p
, q
->sigma_x
/ q
->num_samples
);
211 fprintf(stderr
, "\nMin level ");
213 for (i
= 0; i
< n
; ++i
) {
214 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
218 fprintf(stderr
, "\nMax level ");
220 for (i
= 0; i
< n
; ++i
) {
221 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
225 fprintf(stderr
, "\nPk lev dB %10.2f", linear_to_dB(max(-min
, max
)));
226 for (i
= 0; i
< n
; ++i
) {
227 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
228 fprintf(stderr
, "%10.2f", linear_to_dB(max(-q
->min
, q
->max
)));
231 fprintf(stderr
, "\nRMS lev dB%10.2f", linear_to_dB(sqrt(sigma_x2
/ num_samples
)));
232 for (i
= 0; i
< n
; ++i
) {
233 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
234 fprintf(stderr
, "%10.2f", linear_to_dB(sqrt(q
->sigma_x2
/ q
->num_samples
)));
237 fprintf(stderr
, "\nRMS Pk dB %10.2f", linear_to_dB(sqrt(max_sigma_x2
)));
238 for (i
= 0; i
< n
; ++i
) {
239 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
240 fprintf(stderr
, "%10.2f", linear_to_dB(sqrt(q
->max_sigma_x2
)));
243 fprintf(stderr
, "\nRMS Tr dB ");
244 if (min_sigma_x2
!= 1)
245 fprintf(stderr
, "%10.2f", linear_to_dB(sqrt(min_sigma_x2
)));
246 else fprintf(stderr
, " -");
247 for (i
= 0; i
< n
; ++i
) {
248 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
249 if (q
->min_sigma_x2
!= 1)
250 fprintf(stderr
, "%10.2f", linear_to_dB(sqrt(q
->min_sigma_x2
)));
251 else fprintf(stderr
, " -");
255 fprintf(stderr
, "\nCrest factor -");
256 else fprintf(stderr
, "\nCrest factor %7.2f", sigma_x2
? avg_peak
/ sqrt(sigma_x2
/ num_samples
) : 1);
257 for (i
= 0; i
< n
; ++i
) {
258 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
259 fprintf(stderr
, "%10.2f", q
->sigma_x2
? max(-q
->min
, q
->max
) / sqrt(q
->sigma_x2
/ q
->num_samples
) : 1);
262 fprintf(stderr
, "\nFlat factor%9.2f", linear_to_dB((min_runs
+ max_runs
) / (min_count
+ max_count
)));
263 for (i
= 0; i
< n
; ++i
) {
264 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
265 fprintf(stderr
, " %9.2f", linear_to_dB((q
->min_runs
+ q
->max_runs
) / (q
->min_count
+ q
->max_count
)));
268 fprintf(stderr
, "\nPk count %9s", lsx_sigfigs3((min_count
+ max_count
) / effp
->flows
));
269 for (i
= 0; i
< n
; ++i
) {
270 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
271 fprintf(stderr
, " %9s", lsx_sigfigs3((double)(q
->min_count
+ q
->max_count
)));
274 b1
= bit_depth(mask
, min
, max
, &b2
);
275 fprintf(stderr
, "\nBit-depth %2u/%-2u", b1
, b2
);
276 for (i
= 0; i
< n
; ++i
) {
277 priv_t
* q
= (priv_t
*)(effp
- effp
->flow
+ i
)->priv
;
278 b1
= bit_depth(q
->mask
, q
->min
, q
->max
, &b2
);
279 fprintf(stderr
, " %2u/%-2u", b1
, b2
);
282 fprintf(stderr
, "\nNum samples%9s", lsx_sigfigs3((double)p
->num_samples
));
283 fprintf(stderr
, "\nLength s %9.3f", p
->num_samples
/ effp
->in_signal
.rate
);
284 fprintf(stderr
, "\nScale max ");
286 fprintf(stderr
, "\nWindow s %9.3f", p
->time_constant
);
287 fprintf(stderr
, "\n");
292 sox_effect_handler_t
const * lsx_stats_effect_fn(void)
294 static sox_effect_handler_t handler
= {
295 "stats", "[-b bits|-x bits|-s scale] [-w window-time]", SOX_EFF_MODIFY
,
296 getopts
, start
, flow
, drain
, stop
, NULL
, sizeof(priv_t
)};