sox-devel@lists.sourceforge.net unofficial mirror
 help / color / mirror / code / Atom feed
From: Thor Andreassen <ta@toggle.be>
To: sox-devel@lists.sourceforge.net
Subject: Re: spectrogram values
Date: Wed, 20 Jan 2016 03:37:36 +0100	[thread overview]
Message-ID: <20160120023736.GA31540@toggle.be> (raw)
In-Reply-To: <1452263478.4357.16.camel@shahbaz-bhatti.xgelb.de>

[-- Attachment #1: Type: text/plain, Size: 2037 bytes --]

On Fri, Jan 08, 2016 at 03:31:18PM +0100, Markus Glugla wrote:
> Hi,

Hi Markus
 
> I read the spectrogram threads and affiliate a request. I'm using
> sometimes sox spectrogram to get an spectral overview of various
> measurement datas. But i want to plot the spectrogram with other tools
> e.g. gnuplot.
> 
> I would be very grateful if it were possible to output the spectrogram
> data as plotable values in a file or stream. Does anybody have the
> same intention and more experience than me to produce a patch?

I have been planning to implement an amplitude and water-fall output,
that can be sent to Gnuplot. I will need these in the coming months, so
perhaps it will get done.

A crude way of getting the raw numbers could be to use the color values
from the generated png file, e.g. with Imagemagick:

    sox -n -n synth 1 synth 1k:5k spectrogram -r -o - |
    convert png:- txt:-                 |
    
    # translate into Gnuplot compatible input
    awk -v FS='[,:() ]+' 'NR > 2               { print $1, $2, ($3+$4+$5)/3 }'  |
    awk                  'NR > 2 && $2 != prev { printf "\n" } { prev = $2 } 1' \
    > spectrogram.dat

Note the use of the `-r` option to sox, which omits all decorations. See
`sox --help-effect spectrogram` for more.

Now plot the data file with Gnuplot:

    echo 'splot "spectrogram.dat" with pm3d' | gnuplot --persist

If you want to get at the raw spectrogram, you need to patch
spectrogram.c. The attached patch works best with single channel files.
Use the new `-O filename` switch to save the binary data.

The default output is a sequence of floats which are 4 bytes long. This
is also Gnuplots default for binary input. This means you can plot the
output like this:

    echo 'plot "<sox -n -n synth 1 sine 1k:5k spectrogram -O -" \
            binary array=(513,800) flipy rotation=90d with image' |
    gnuplot --persist

Note that if your output from sox is short, the spectrogram dimensions
will be different from 800x513 and Gnuplot will barf.

-- 
best regards
Thor Andreassen

[-- Attachment #2: add_output_raw_spectrogram_option.patch --]
[-- Type: text/plain, Size: 4420 bytes --]

diff --git a/src/spectrogram.c b/src/spectrogram.c
index afb0b0e..0fdbd4a 100644
--- a/src/spectrogram.c
+++ b/src/spectrogram.c
@@ -58,9 +58,10 @@ typedef struct {
   sox_bool   monochrome, light_background, high_colour, slack_overlap, no_axes;
   sox_bool   raw, alt_palette, truncate;
   win_type_t win_type;
-  char const * out_name, * title, * comment;
+  char const * out_name, * title, * comment, * out_name_raw;
   char const *duration_str, *start_time_str;
   sox_bool   using_stdout; /* output image to stdout */
+  sox_bool   using_stdout_raw; /* output raw spectrogram to stdout */
 
   /* Shared work area */
   double     * shared, * * shared_ptr;
@@ -107,10 +108,11 @@ static int getopts(sox_effect_t * effp, int argc, char **argv)
   char const * next;
   int c;
   lsx_getopt_t optstate;
-  lsx_getopt_init(argc, argv, "+S:d:x:X:y:Y:z:Z:q:p:W:w:st:c:AarmlhTo:", NULL, lsx_getopt_flag_none, 1, &optstate);
+  lsx_getopt_init(argc, argv, "+S:d:x:X:y:Y:z:Z:q:p:W:w:st:c:AarmlhTo:O:", NULL, lsx_getopt_flag_none, 1, &optstate);
 
   p->dB_range = 120, p->spectrum_points = 249, p->perm = 1; /* Non-0 defaults */
   p->out_name = "spectrogram.png", p->comment = "Created by SoX";
+  p->out_name_raw = NULL;
 
   while ((c = lsx_getopt(&optstate)) != -1) switch (c) {
     GETOPT_NUMERIC(optstate, 'x', x_size0       , 100, MAX_X_SIZE)
@@ -134,6 +136,7 @@ static int getopts(sox_effect_t * effp, int argc, char **argv)
     case 't': p->title            = optstate.arg; break;
     case 'c': p->comment          = optstate.arg; break;
     case 'o': p->out_name         = optstate.arg; break;
+    case 'O': p->out_name_raw     = optstate.arg; break;
     case 'S': next = lsx_parseposition(0., optstate.arg, NULL, (uint64_t)0, (uint64_t)0, '=');
       if (next && !*next) {p->start_time_str = lsx_strdup(optstate.arg); break;}
       return lsx_usage(effp);
@@ -164,6 +167,14 @@ static int getopts(sox_effect_t * effp, int argc, char **argv)
     effp->global_info->global_info->stdout_in_use_by = effp->handler.name;
     p->using_stdout = sox_true;
   }
+  if (p->out_name_raw != NULL && !strcmp(p->out_name_raw, "-")) {
+    if (effp->global_info->global_info->stdout_in_use_by) {
+      lsx_fail("stdout already in use by `%s'", effp->global_info->global_info->stdout_in_use_by);
+      return SOX_EOF;
+    }
+    effp->global_info->global_info->stdout_in_use_by = effp->handler.name;
+    p->using_stdout_raw = sox_true;
+  }
   return optstate.ind !=argc || p->win_type == INT_MAX? lsx_usage(effp) : SOX_SUCCESS;
 }
 
@@ -530,7 +541,7 @@ static int axis(double to, int max_steps, double * limit, char * * prefix)
 static int stop(sox_effect_t * effp) /* only called, by end(), on flow 0 */
 {
   priv_t *    p        = (priv_t *) effp->priv;
-  FILE *      file;
+  FILE *      file, * file_raw;
   uLong       font_len = 96 * font_y;
   int         chans    = effp->in_signal.channels;
   int         c_rows   = p->rows * chans + chans - 1;
@@ -556,6 +567,18 @@ static int stop(sox_effect_t * effp) /* only called, by end(), on flow 0 */
       goto error;
     }
   }
+  if(p->out_name_raw != NULL) {
+    if (p->using_stdout_raw) {
+      SET_BINARY_MODE(stdout);
+      file_raw = stdout;
+    } else {
+      file_raw = fopen(p->out_name_raw, "wb");
+      if (!file_raw) {
+        lsx_fail("failed to create `%s': %s", p->out_name_raw, strerror(errno));
+        goto error;
+      }
+    }
+  }
   lsx_debug("signal-max=%g", p->max);
   font = lsx_malloc(font_len);
   assert(uncompress(font, &font_len, fixed, sizeof(fixed)-1) == Z_OK);
@@ -642,6 +665,11 @@ static int stop(sox_effect_t * effp) /* only called, by end(), on flow 0 */
       print_at(cols - right + 1, base + y + 5, Labels, text);
     }
   }
+
+  /* Write raw spectrogram data */
+  if(p->out_name_raw != NULL)
+    fwrite(p->dBfs, (size_t) p->cols * p->rows, sizeof(*p->dBfs), file_raw);
+
   free(font);
   png_set_rows(png, png_info, png_rows);
   png_write_png(png, png_info, PNG_TRANSFORM_IDENTITY, NULL);
@@ -689,6 +717,7 @@ sox_effect_handler_t const * lsx_spectrogram_effect_fn(void)
     "\t-t text\tTitle text",
     "\t-c text\tComment text",
     "\t-o text\tOutput file name; default `spectrogram.png'",
+    "\t-O text\tOutput file name with raw spectrogram data",
     "\t-d time\tAudio duration to fit to X-axis; e.g. 1:00, 48",
     "\t-S position\tStart the spectrogram at the given input position",
   };

[-- Attachment #3: Type: text/plain, Size: 413 bytes --]

------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140

[-- Attachment #4: Type: text/plain, Size: 158 bytes --]

_______________________________________________
SoX-devel mailing list
SoX-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sox-devel

  reply	other threads:[~2016-01-20  2:37 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-08 14:31 spectrogram values Markus Glugla
2016-01-20  2:37 ` Thor Andreassen [this message]
2016-01-21 15:33   ` Pander
2016-01-22 23:54     ` Thor Andreassen
2016-01-26 12:24       ` Pander
2016-01-22 17:38   ` Thor Andreassen
2016-01-28 12:51   ` Markus Glugla
2016-01-28 13:00     ` Pander
2016-01-28 14:47       ` Markus Glugla
2016-01-28 16:17         ` Pander

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://lists.sourceforge.net/lists/listinfo/sox-devel

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160120023736.GA31540@toggle.be \
    --to=sox-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/sox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).