summary refs log tree commit
diff options
context:
space:
mode:
authorPander <pander@users.sourceforge.net>2014-12-22 22:45:34 +0100
committerEric Wong <normalperson@yhbt.net>2015-12-19 10:45:55 +0000
commitae1ad56ca235defe9bb81c730d49a5e4345c23ba (patch)
treea9704442f416a6e53954172dc6a9787182944a71
parent7e74b254b2a7c963be0bfce751fc5911fe681c12 (diff)
downloadsox-pander/avg-pwr-spec.tar.gz
Added average power spectrum for stat -freq -a pander/avg-pwr-spec
references:
https://sourceforge.net/p/sox/mailman/message/33186778/
https://sourceforge.net/p/sox/mailman/message/33175940/
https://sourceforge.net/p/sox/mailman/message/33625255/

Reviewed-by: Eric Wong <normalperson@yhbt.net>

[ew: removed extraneous whitespace changes,
 squashed re_average initialization fix,
 removed unnecessary check before free(3) call
 (ref: <5498A2F9.2010500@free.fr>),
 converted fft_average to bool]
-rw-r--r--sox.16
-rw-r--r--src/stat.c27
2 files changed, 32 insertions, 1 deletions
diff --git a/sox.1 b/sox.1
index 2c4ca470..8d446537 100644
--- a/sox.1
+++ b/sox.1
@@ -3592,6 +3592,12 @@ audio in SoX's internal buffer.
 This is mainly used to help track down endian problems that
 sometimes occur in cross-platform versions of SoX.
 .SP
+The
+.B \-a
+option
+will output the average input's power spectrum instead of the default
+behavior in which the power spectrum is given for each 4096 point DFT.
+.SP
 See also the
 .B stats
 effect.
diff --git a/src/stat.c b/src/stat.c
index cdea27cc..0ca6c232 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -34,6 +34,7 @@ typedef struct {
   float *re_out;
   unsigned long fft_size;
   unsigned long fft_offset;
+  sox_bool fft_average;
 } priv_t;
 
 
@@ -69,6 +70,8 @@ static int sox_stat_getopts(sox_effect_t * effp, int argc, char **argv)
       stat->fft = 1;
     else if (!(strcmp(*argv, "-d")))
       stat->volume = 2;
+    else if (!(strcmp(*argv, "-a")))
+      stat->fft_average = sox_true;
     else {
       lsx_fail("Summary effect: unknown option");
       return SOX_EOF;
@@ -100,6 +103,7 @@ static int sox_stat_start(sox_effect_t * effp)
     stat->bin[i] = 0;
 
   stat->fft_size = 4096;
+  stat->fft_average = sox_false;
   stat->re_in = stat->re_out = NULL;
 
   if (stat->fft) {
@@ -134,6 +138,16 @@ static int sox_stat_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_samp
   priv_t * stat = (priv_t *) effp->priv;
   int done, x, len = min(*isamp, *osamp);
   short count = 0;
+  float *re_average = NULL;
+  unsigned samples = 0;
+  float ffa = 0.0;
+  unsigned i;
+
+  if (stat->fft_average) {
+      samples = (stat->fft_size / 2);
+      ffa = effp->in_signal.rate / samples;
+      re_average = lsx_malloc(sizeof(float) * (int)samples);
+  }
 
   if (len) {
     if (stat->read == 0)          /* 1st sample */
@@ -146,10 +160,20 @@ static int sox_stat_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_samp
 
         if (stat->fft_offset >= stat->fft_size) {
           stat->fft_offset = 0;
+          if (stat->fft_average) {
+              lsx_power_spectrum_f((int)samples, stat->re_in, stat->re_out);
+              for (i = 0; i < samples / 2; i++) /* FIXME: should be <= samples / 2 */
+                  re_average[i] += stat->re_out[i];
+          } else {
           print_power_spectrum((unsigned) stat->fft_size, effp->in_signal.rate, stat->re_in, stat->re_out);
+          }
         }
 
       }
+      if (stat->fft_average) {
+          for (i = 0; i < samples / 2; i++) /* FIXME: should be <= samples / 2 */
+              fprintf(stderr, " %f  %f\n", ffa * i, re_average[i] / len);
+      }
     }
 
     for (done = 0; done < len; done++) {
@@ -192,6 +216,7 @@ static int sox_stat_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_samp
     stat->read += len;
   }
 
+  free(re_average);
   *isamp = *osamp = len;
   /* Process all samples */
 
@@ -320,7 +345,7 @@ static int sox_stat_stop(sox_effect_t * effp)
 
 static sox_effect_handler_t sox_stat_effect = {
   "stat",
-  "[ -s N ] [ -rms ] [-freq] [ -v ] [ -d ]",
+  "[ -s N ] [ -rms ] [-freq] [ -v ] [ -d ] [ -a ]",
   SOX_EFF_MCHAN | SOX_EFF_MODIFY,
   sox_stat_getopts,
   sox_stat_start,