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
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",
};
------------------------------------------------------------------------------
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
_______________________________________________
SoX-devel mailing list
SoX-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sox-devel