« MacOS X: Virtual MIDI sources | Main | Meetings »

Plot data in realtime with GNU graph

I'm trying to diagnose the MIDI output of my velocity poi base station. This base station receives normalized velocity telemetry via RF on two channels (418MHz and 433 MHz) and outputs MIDI data. In this case, I'm trying to examine the Control Change MIDI message (a number in the interval [0, 127]). Because there's noise in the system, I'm written hardware smoothing functions, and I wanted to understand the effect these smoothing functions have on my MIDI output---in real time. I wanted an "oscilloscope" for digital data.

And of course I discovered that the software I wanted already exists...

The GNU Graph program, part of the venerable plotutils package, can act as a "real-time filter" of data. I used darwinports to install plotutils and began poking around in GNU Graph. I discovered the following things from the documentation: in order to plot in real-time, the -x and -y (bounds) arguments must be specified, and data to graph is read from stdin.

My first naive attempt to plot data in real-time failed because pipes are inherently page buffered. In order to connect a program which is producing time-dependent data to graph via a pipe, this buffering must first be inhibited. But how?

One solution is to use the "unbuffer" program bundled with Expect. The other way (and the way I did it) is to use the Expect perl module. The important part here is to stty the terminal to raw (using Expect here seemed to be the easiest way to stty the terminal.)

The following code, then, plots data output by the Perl script in realtime:

#!/usr/bin/perl
use Expect;
use Time::HiRes qw(gettimeofday sleep);

use constant {
DURATION => 30,
INCREMENT => 0.25,
};

my $start = gettimeofday();
my $end = DURATION;

my $exp = new Expect->new();
$exp->slave->stty(qw(raw));

my $graph = $exp->spawn("graph -T X -x 0 $end -y 0 127");
open my $graph, "|graph -T X -x 0 $end -y 0 127");
for (my $i=0; $i<(DURATION*(1/INCREMENT)); $i++) {
my $val = rand(127);
print $graph gettimeofday()-$start ." $val\n";
sleep(0.25);
flush
}

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)