Sigrid Solveig Haflínudóttirfix warnings6bc6a9b3 years agoHistory
337 lines · 8.8 KB · C
RawDownload
/* libSoX statistics "effect" file. * * Compute various statistics on file and print them. * * Output is unmodified from input. * * July 5, 1991 * Copyright 1991 Lance Norskog And Sundry Contributors * This source code is freely redistributable and may be used for * any purpose.  This copyright notice must be maintained. * Lance Norskog And Sundry Contributors are not responsible for * the consequences of using this software. */ #include "sox_i.h" #include <string.h> /* Private data for stat effect */typedef struct {  double min, max, mid;  double asum;  double sum1, sum2;            /* amplitudes */  double dmin, dmax;  double dsum1, dsum2;          /* deltas */  double scale;                 /* scale-factor */  double last;                  /* previous sample */  uint64_t read;               /* samples processed */  int volume;  int srms;  int fft;  unsigned long bin[4];  float *re_in;  float *re_out;  unsigned long fft_size;  unsigned long fft_offset;} priv_t;  /* * Process options */static int sox_stat_getopts(sox_effect_t * effp, int argc, char **argv){  priv_t * stat = (priv_t *) effp->priv;   stat->scale = SOX_SAMPLE_MAX;  stat->volume = 0;  stat->srms = 0;  stat->fft = 0;   --argc, ++argv;  for (; argc > 0; argc--, argv++) {    if (!(strcmp(*argv, "-v")))      stat->volume = 1;    else if (!(strcmp(*argv, "-s"))) {      if (argc <= 1) {        lsx_fail("-s option: invalid argument");        return SOX_EOF;      }      argc--, argv++;              /* Move to next argument. */      if (!sscanf(*argv, "%lf", &stat->scale)) {        lsx_fail("-s option: invalid argument");        return SOX_EOF;      }    } else if (!(strcmp(*argv, "-rms")))      stat->srms = 1;    else if (!(strcmp(*argv, "-freq")))      stat->fft = 1;    else if (!(strcmp(*argv, "-d")))      stat->volume = 2;    else {      lsx_fail("Summary effect: unknown option");      return SOX_EOF;    }  }   return SOX_SUCCESS;} /* * Prepare processing. */static int sox_stat_start(sox_effect_t * effp){  priv_t * stat = (priv_t *) effp->priv;  int i;   stat->min = stat->max = stat->mid = 0;  stat->asum = 0;  stat->sum1 = stat->sum2 = 0;   stat->dmin = stat->dmax = 0;  stat->dsum1 = stat->dsum2 = 0;   stat->last = 0;  stat->read = 0;   for (i = 0; i < 4; i++)    stat->bin[i] = 0;   stat->fft_size = 4096;  stat->re_in = stat->re_out = NULL;   if (stat->fft) {    stat->fft_offset = 0;    stat->re_in = lsx_malloc(sizeof(float) * stat->fft_size);    stat->re_out = lsx_malloc(sizeof(float) * (stat->fft_size / 2 + 1));  }   return SOX_SUCCESS;} /* * Print power spectrum to given stream */static void print_power_spectrum(unsigned samples, double rate, float *re_in, float *re_out){  float ffa = rate / samples;  unsigned i;   lsx_power_spectrum_f((int)samples, re_in, re_out);  for (i = 0; i < samples / 2; i++) /* FIXME: should be <= samples / 2 */    fprintf(stderr, "%f  %f\n", ffa * i, re_out[i]);} /* * Processed signed long samples from ibuf to obuf. * Return number of samples processed. */static int sox_stat_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,                        size_t *isamp, size_t *osamp){  priv_t * stat = (priv_t *) effp->priv;  int done, x, len = min(*isamp, *osamp);  short count = 0;   if (len) {    if (stat->read == 0)          /* 1st sample */      stat->min = stat->max = stat->mid = stat->last = (*ibuf)/stat->scale;     if (stat->fft) {      for (x = 0; x < len; x++) {        SOX_SAMPLE_LOCALS;        stat->re_in[stat->fft_offset++] = SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[x], effp->clips);         if (stat->fft_offset >= stat->fft_size) {          stat->fft_offset = 0;          print_power_spectrum((unsigned) stat->fft_size, effp->in_signal.rate, stat->re_in, stat->re_out);        }       }    }     for (done = 0; done < len; done++) {      long lsamp = *ibuf++;      double delta, samp = (double)lsamp / stat->scale;      /* work in scaled levels for both sample and delta */      stat->bin[(lsamp >> 30) + 2]++;      *obuf++ = lsamp;       if (stat->volume == 2) {          fprintf(stderr,"%08lx ",lsamp);          if (count++ == 5) {              fprintf(stderr,"\n");              count = 0;          }      }       /* update min/max */      if (stat->min > samp)        stat->min = samp;      else if (stat->max < samp)        stat->max = samp;      stat->mid = stat->min / 2 + stat->max / 2;       stat->sum1 += samp;      stat->sum2 += samp*samp;      stat->asum += fabs(samp);       delta = fabs(samp - stat->last);      if (delta < stat->dmin)        stat->dmin = delta;      else if (delta > stat->dmax)        stat->dmax = delta;       stat->dsum1 += delta;      stat->dsum2 += delta*delta;       stat->last = samp;    }    stat->read += len;  }   *isamp = *osamp = len;  /* Process all samples */   return SOX_SUCCESS;} /* * Process tail of input samples. */static int sox_stat_drain(sox_effect_t * effp, sox_sample_t *obuf UNUSED, size_t *osamp){  priv_t * stat = (priv_t *) effp->priv;   USED(obuf);  /* When we run out of samples, then we need to pad buffer with   * zeros and then run FFT one last time to process any unprocessed   * samples.   */  if (stat->fft && stat->fft_offset) {    unsigned int x;     for (x = stat->fft_offset; x < stat->fft_size; x++)      stat->re_in[x] = 0;     print_power_spectrum((unsigned) stat->fft_size, effp->in_signal.rate, stat->re_in, stat->re_out);  }   *osamp = 0;  return SOX_EOF;} /* * Do anything required when you stop reading samples. * Don't close input file! */static int sox_stat_stop(sox_effect_t * effp){  priv_t * stat = (priv_t *) effp->priv;  double amp, scale, rms = 0, freq;  double x, ct;   ct = stat->read;   if (stat->srms) {  /* adjust results to units of rms */    double f;    rms = sqrt(stat->sum2/ct);    f = 1.0/rms;    stat->max *= f;    stat->min *= f;    stat->mid *= f;    stat->asum *= f;    stat->sum1 *= f;    stat->sum2 *= f*f;    stat->dmax *= f;    stat->dmin *= f;    stat->dsum1 *= f;    stat->dsum2 *= f*f;    stat->scale *= rms;  }   scale = stat->scale;   amp = -stat->min;  if (amp < stat->max)    amp = stat->max;   /* Just print the volume adjustment */  if (stat->volume == 1 && amp > 0) {    fprintf(stderr, "%.3f\n", SOX_SAMPLE_MAX/(amp*scale));    return SOX_SUCCESS;  }  if (stat->volume == 2)    fprintf(stderr, "\n\n");  /* print out the info */  fprintf(stderr, "Samples read:      %12" PRIu64 "\n", stat->read);  fprintf(stderr, "Length (seconds):  %12.6f\n", (double)stat->read/effp->in_signal.rate/effp->in_signal.channels);  if (stat->srms)    fprintf(stderr, "Scaled by rms:     %12.6f\n", rms);  else    fprintf(stderr, "Scaled by:         %12.1f\n", scale);  fprintf(stderr, "Maximum amplitude: %12.6f\n", stat->max);  fprintf(stderr, "Minimum amplitude: %12.6f\n", stat->min);  fprintf(stderr, "Midline amplitude: %12.6f\n", stat->mid);  fprintf(stderr, "Mean    norm:      %12.6f\n", stat->asum/ct);  fprintf(stderr, "Mean    amplitude: %12.6f\n", stat->sum1/ct);  fprintf(stderr, "RMS     amplitude: %12.6f\n", sqrt(stat->sum2/ct));   fprintf(stderr, "Maximum delta:     %12.6f\n", stat->dmax);  fprintf(stderr, "Minimum delta:     %12.6f\n", stat->dmin);  fprintf(stderr, "Mean    delta:     %12.6f\n", stat->dsum1/(ct-1));  fprintf(stderr, "RMS     delta:     %12.6f\n", sqrt(stat->dsum2/(ct-1)));  freq = sqrt(stat->dsum2/stat->sum2)*effp->in_signal.rate/(M_PI*2);  fprintf(stderr, "Rough   frequency: %12d\n", (int)freq);   if (amp>0)    fprintf(stderr, "Volume adjustment: %12.3f\n", SOX_SAMPLE_MAX/(amp*scale));   if (stat->bin[2] == 0 && stat->bin[3] == 0)    fprintf(stderr, "\nProbably text, not sound\n");  else {     x = (float)(stat->bin[0] + stat->bin[3]) / (float)(stat->bin[1] + stat->bin[2]);     if (x >= 3.0) {             /* use opposite encoding */      if (effp->in_encoding->encoding == SOX_ENCODING_UNSIGNED)        fprintf(stderr,"\nTry: -t raw -e signed-integer -b 8 \n");      else        fprintf(stderr,"\nTry: -t raw -e unsigned-integer -b 8 \n");    } else if (x <= 1.0 / 3.0) {      /* correctly decoded */    } else if (x >= 0.5 && x <= 2.0) { /* use ULAW */      if (effp->in_encoding->encoding == SOX_ENCODING_ULAW)        fprintf(stderr,"\nTry: -t raw -e unsigned-integer -b 8 \n");      else        fprintf(stderr,"\nTry: -t raw -e mu-law -b 8 \n");    } else      fprintf(stderr, "\nCan't guess the type\n");  }   /* Release FFT memory */  free(stat->re_in);  free(stat->re_out);   return SOX_SUCCESS; } static sox_effect_handler_t sox_stat_effect = {  "stat",  "[ -s N ] [ -rms ] [-freq] [ -v ] [ -d ]",  SOX_EFF_MCHAN | SOX_EFF_MODIFY,  sox_stat_getopts,  sox_stat_start,  sox_stat_flow,  sox_stat_drain,  sox_stat_stop,  NULL, sizeof(priv_t)}; const sox_effect_handler_t *lsx_stat_effect_fn(void){  return &sox_stat_effect;}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t