1 /* libSoX statistics "effect" file.
3 * Compute various statistics on file and print them.
5 * Output is unmodified from input.
8 * Copyright 1991 Lance Norskog And Sundry Contributors
9 * This source code is freely redistributable and may be used for
10 * any purpose. This copyright notice must be maintained.
11 * Lance Norskog And Sundry Contributors are not responsible for
12 * the consequences of using this software.
19 /* Private data for stat effect */
23 double sum1
, sum2
; /* amplitudes */
25 double dsum1
, dsum2
; /* deltas */
26 double scale
; /* scale-factor */
27 double last
; /* previous sample */
28 uint64_t read
; /* samples processed */
35 unsigned long fft_size
;
36 unsigned long fft_offset
;
43 static int sox_stat_getopts(sox_effect_t
* effp
, int argc
, char **argv
)
45 priv_t
* stat
= (priv_t
*) effp
->priv
;
47 stat
->scale
= SOX_SAMPLE_MAX
;
53 for (; argc
> 0; argc
--, argv
++) {
54 if (!(strcmp(*argv
, "-v")))
56 else if (!(strcmp(*argv
, "-s"))) {
58 lsx_fail("-s option: invalid argument");
61 argc
--, argv
++; /* Move to next argument. */
62 if (!sscanf(*argv
, "%lf", &stat
->scale
)) {
63 lsx_fail("-s option: invalid argument");
66 } else if (!(strcmp(*argv
, "-rms")))
68 else if (!(strcmp(*argv
, "-freq")))
70 else if (!(strcmp(*argv
, "-d")))
73 lsx_fail("Summary effect: unknown option");
84 static int sox_stat_start(sox_effect_t
* effp
)
86 priv_t
* stat
= (priv_t
*) effp
->priv
;
89 stat
->min
= stat
->max
= stat
->mid
= 0;
91 stat
->sum1
= stat
->sum2
= 0;
93 stat
->dmin
= stat
->dmax
= 0;
94 stat
->dsum1
= stat
->dsum2
= 0;
99 for (i
= 0; i
< 4; i
++)
102 stat
->fft_size
= 4096;
103 stat
->re_in
= stat
->re_out
= NULL
;
106 stat
->fft_offset
= 0;
107 stat
->re_in
= lsx_malloc(sizeof(float) * stat
->fft_size
);
108 stat
->re_out
= lsx_malloc(sizeof(float) * (stat
->fft_size
/ 2 + 1));
115 * Print power spectrum to given stream
117 static void print_power_spectrum(unsigned samples
, double rate
, float *re_in
, float *re_out
)
119 float ffa
= rate
/ samples
;
122 lsx_power_spectrum_f((int)samples
, re_in
, re_out
);
123 for (i
= 0; i
< samples
/ 2; i
++) /* FIXME: should be <= samples / 2 */
124 fprintf(stderr
, "%f %f\n", ffa
* i
, re_out
[i
]);
128 * Processed signed long samples from ibuf to obuf.
129 * Return number of samples processed.
131 static int sox_stat_flow(sox_effect_t
* effp
, const sox_sample_t
*ibuf
, sox_sample_t
*obuf
,
132 size_t *isamp
, size_t *osamp
)
134 priv_t
* stat
= (priv_t
*) effp
->priv
;
135 int done
, x
, len
= min(*isamp
, *osamp
);
139 if (stat
->read
== 0) /* 1st sample */
140 stat
->min
= stat
->max
= stat
->mid
= stat
->last
= (*ibuf
)/stat
->scale
;
143 for (x
= 0; x
< len
; x
++) {
145 stat
->re_in
[stat
->fft_offset
++] = SOX_SAMPLE_TO_FLOAT_32BIT(ibuf
[x
], effp
->clips
);
147 if (stat
->fft_offset
>= stat
->fft_size
) {
148 stat
->fft_offset
= 0;
149 print_power_spectrum((unsigned) stat
->fft_size
, effp
->in_signal
.rate
, stat
->re_in
, stat
->re_out
);
155 for (done
= 0; done
< len
; done
++) {
156 long lsamp
= *ibuf
++;
157 double delta
, samp
= (double)lsamp
/ stat
->scale
;
158 /* work in scaled levels for both sample and delta */
159 stat
->bin
[(lsamp
>> 30) + 2]++;
162 if (stat
->volume
== 2) {
163 fprintf(stderr
,"%08lx ",lsamp
);
165 fprintf(stderr
,"\n");
171 if (stat
->min
> samp
)
173 else if (stat
->max
< samp
)
175 stat
->mid
= stat
->min
/ 2 + stat
->max
/ 2;
178 stat
->sum2
+= samp
*samp
;
179 stat
->asum
+= fabs(samp
);
181 delta
= fabs(samp
- stat
->last
);
182 if (delta
< stat
->dmin
)
184 else if (delta
> stat
->dmax
)
187 stat
->dsum1
+= delta
;
188 stat
->dsum2
+= delta
*delta
;
195 *isamp
= *osamp
= len
;
196 /* Process all samples */
202 * Process tail of input samples.
204 static int sox_stat_drain(sox_effect_t
* effp
, sox_sample_t
*obuf UNUSED
, size_t *osamp
)
206 priv_t
* stat
= (priv_t
*) effp
->priv
;
208 /* When we run out of samples, then we need to pad buffer with
209 * zeros and then run FFT one last time to process any unprocessed
212 if (stat
->fft
&& stat
->fft_offset
) {
215 for (x
= stat
->fft_offset
; x
< stat
->fft_size
; x
++)
218 print_power_spectrum((unsigned) stat
->fft_size
, effp
->in_signal
.rate
, stat
->re_in
, stat
->re_out
);
226 * Do anything required when you stop reading samples.
227 * Don't close input file!
229 static int sox_stat_stop(sox_effect_t
* effp
)
231 priv_t
* stat
= (priv_t
*) effp
->priv
;
232 double amp
, scale
, rms
= 0, freq
;
237 if (stat
->srms
) { /* adjust results to units of rms */
239 rms
= sqrt(stat
->sum2
/ct
);
260 /* Just print the volume adjustment */
261 if (stat
->volume
== 1 && amp
> 0) {
262 fprintf(stderr
, "%.3f\n", SOX_SAMPLE_MAX
/(amp
*scale
));
265 if (stat
->volume
== 2)
266 fprintf(stderr
, "\n\n");
267 /* print out the info */
268 fprintf(stderr
, "Samples read: %12" PRIu64
"\n", stat
->read
);
269 fprintf(stderr
, "Length (seconds): %12.6f\n", (double)stat
->read
/effp
->in_signal
.rate
/effp
->in_signal
.channels
);
271 fprintf(stderr
, "Scaled by rms: %12.6f\n", rms
);
273 fprintf(stderr
, "Scaled by: %12.1f\n", scale
);
274 fprintf(stderr
, "Maximum amplitude: %12.6f\n", stat
->max
);
275 fprintf(stderr
, "Minimum amplitude: %12.6f\n", stat
->min
);
276 fprintf(stderr
, "Midline amplitude: %12.6f\n", stat
->mid
);
277 fprintf(stderr
, "Mean norm: %12.6f\n", stat
->asum
/ct
);
278 fprintf(stderr
, "Mean amplitude: %12.6f\n", stat
->sum1
/ct
);
279 fprintf(stderr
, "RMS amplitude: %12.6f\n", sqrt(stat
->sum2
/ct
));
281 fprintf(stderr
, "Maximum delta: %12.6f\n", stat
->dmax
);
282 fprintf(stderr
, "Minimum delta: %12.6f\n", stat
->dmin
);
283 fprintf(stderr
, "Mean delta: %12.6f\n", stat
->dsum1
/(ct
-1));
284 fprintf(stderr
, "RMS delta: %12.6f\n", sqrt(stat
->dsum2
/(ct
-1)));
285 freq
= sqrt(stat
->dsum2
/stat
->sum2
)*effp
->in_signal
.rate
/(M_PI
*2);
286 fprintf(stderr
, "Rough frequency: %12d\n", (int)freq
);
289 fprintf(stderr
, "Volume adjustment: %12.3f\n", SOX_SAMPLE_MAX
/(amp
*scale
));
291 if (stat
->bin
[2] == 0 && stat
->bin
[3] == 0)
292 fprintf(stderr
, "\nProbably text, not sound\n");
295 x
= (float)(stat
->bin
[0] + stat
->bin
[3]) / (float)(stat
->bin
[1] + stat
->bin
[2]);
297 if (x
>= 3.0) { /* use opposite encoding */
298 if (effp
->in_encoding
->encoding
== SOX_ENCODING_UNSIGNED
)
299 fprintf(stderr
,"\nTry: -t raw -e signed-integer -b 8 \n");
301 fprintf(stderr
,"\nTry: -t raw -e unsigned-integer -b 8 \n");
302 } else if (x
<= 1.0 / 3.0)
303 ; /* correctly decoded */
304 else if (x
>= 0.5 && x
<= 2.0) { /* use ULAW */
305 if (effp
->in_encoding
->encoding
== SOX_ENCODING_ULAW
)
306 fprintf(stderr
,"\nTry: -t raw -e unsigned-integer -b 8 \n");
308 fprintf(stderr
,"\nTry: -t raw -e mu-law -b 8 \n");
310 fprintf(stderr
, "\nCan't guess the type\n");
313 /* Release FFT memory */
321 static sox_effect_handler_t sox_stat_effect
= {
323 "[ -s N ] [ -rms ] [-freq] [ -v ] [ -d ]",
324 SOX_EFF_MCHAN
| SOX_EFF_MODIFY
,
333 const sox_effect_handler_t
*lsx_stat_effect_fn(void)
335 return &sox_stat_effect
;