# Copyright (C) 1996 - 2001 Tim Witham # Copyright (C) 2015 Brent Baccala # (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__ {}