1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
# Copyright (C) 1996 - 2001 Tim Witham <twitham@pcocd2.intel.com>
# Copyright (C) 2015 Brent Baccala <cosine@freesoft.org>
# (see the files README and COPYING for more details)
# xoscope external math filter command example in perl
# !!! Please see bottom of this file for instructions and examples !!!
$| = 1; # unbuffer stdout
$0 =~ s!.*/!!; # reduce to program basename
$func = $ENV{FUNC}; # get function to run from environment
$samples = $ARGV[1] || 640; # assume 640 total samples per screen
$func =~ s/\#.*$//; # toss comments
$func =~ s/^\s*(\$0\s*=)?\s*//; # and assumed leading/trailing stuff, if any
$func =~ s/\s*;*\s*$//;
die "usage: $0 'perl math function of \$t, \$ch1 and \$ch2' [sample length]\n"
unless $func; # oops
$func = "\$out = $func;"; # '$out=' and ';' are implied around function
open(IN, '<&3') # open non-standard input for reading
|| die "$0: Can't read input: $!\n";
open(OUT, '>-') # and stdout for writing
|| die "$0: Can't write stdout: $!\n";
$pi = 3.14159265359; # define pi for user's convenience
$t = 0; # sample position number (time)
for (1..$samples) { # initialize sample memory "shift registers"
push(@ch1, 0); # channel 1 (left)
push(@ch2, 0); # channel 2 (right)
push(@out, 0); # output back to software channel
}
# For efficiency, we now dynamically build a while loop around the
# user's function then evaluate (compile and run) it once.
# begin of loop: how to read the samples (two shorts) from stdin:
$begin = '
while(1) {
sysread(IN, $buff, 2) || exit;
$ch1 = unpack(\'s\', $buff);
sysread(IN, $buff, 2) || exit;
$ch2 = unpack(\'s\', $buff);
';
# end: how to increment time, remember the samples, and write result to stdout:
$end = '
$t = 0 if ++$t >= $samples;';
# sample history is expensive, so we only remember those the function needs:
$end .= '
pop(@ch1); unshift(@ch1, $ch1);' if $func =~ /\$ch1\[/;
$end .= '
pop(@ch2); unshift(@ch2, $ch2);' if $func =~ /\$ch2\[/;
$end .= '
pop(@out); unshift(@out, $out);' if $func =~ /\$out\[/;
$end .= '
syswrite(OUT, pack(\'s\', $out), 2) || exit;
}
';
# now put the loop around the user's function
eval $begin.$func.$end; # and finally run the loop forever
warn "$@\n" if $@; # show any user syntax errors on stderr
__END__
{}
|