.TH "XFORM" 1carl CARL
.SH NAME
xform
- transform sample data streams
.SH SYNOPSIS
.B xform
[flags] [expressions] < sample_data > sample_data
.sp
.nf
flags:
.RS .5i
 -bN set begin time to N
 -eN set end time to N
 -iX set input format to X
 -oY set output format to Y
formats for X and Y:
.RS .5i
b arabic numbers are treated as amplitude in dB
d arabic decimal numbers
e expressions in expr() format (input only)
f arabic floating point numbers
o arabic octal numbers
pN set integer conversion scaling to N
s binary short integer (16-bit) numbers
x arabic hexidecimal numbers
(floatsams are read and written by default)
.RE
 -t index samples with time in seconds
 -RN set sampling rate to N
 -s index samples with sample numbers
 -h usage statement
 -# output debugging information
.RE
.fi
If input mode specifying 
.I floatsams 
or
.I shortsams
is set, input must be a file or pipe.  Otherwise, input may be a terminal.
.I Floatsams
are written if output is connected to file or pipe, unless if an
.I arabic 
or
.I shortsam
output format is specified.
.SH DESCRIPTION
.B xform
is a relatively general anything-to-anything converter for signals. 
It can:
.RS .5i
.nf
* read either floatsams, shortsams, or arabic numerals,
* write either floatsams, shortsams, or arabic numerals, 
* handle variable precision integer formats, and
* apply expressions to the sample stream;
* arabic numerals may be decimal, octal, hexidecimal or dB.
.fi
.RE
Its operation without flags simply copies 
sample data from its input to its output, subject to format conventions
described next.
.SH Output Format Conversion
.PP
If the standard output is a terminal, arabic (i.e., humanly readable)
floating point is written,
otherwise
when the output is a file or pipe,
.I floatsams
(32-bit binary floating point sample data)
are written.
This can be modified, to force output of 
.I shortsams
(16-bit binary short integers) or various arabic numeric formats
instead of
.I floatsams,
even if the output is a file or pipe.
.PP
The various arabic formats are specified
by providing output flags of the form
.I -oY
where
.I Y
is one of the characters 
.I b
(dB)
.I d
(decimal)
.I f
(floating point)
.I o
(octal) or
.I x
(hexidecimal).
Note that arabic output conversion formats are cumulative: requesting more than
one is possible, and will result in their being printed side by side
on the same line.  (Supply multiple output format flags to do this).
.PP
To write 
.I shortsams, 
provide the flag
.I -os.
Speicifying 
.I shortsams
for output turns off printing any arabic format.
This flag will be ignored if the standard output is connected to a
terminal.
Because it is not desirable to try to print either
.I floatsams
or
.I shortsams
on a terminal, these modes are automatically disabled when the standard
output is a terminal.  In this case, 
.I floatsam 
input will produce
arabic floating point format on output, and
.I shortsam
input will produce
arabic decimal format on output.
.PP
Arabic format output can be accompanied by the sample number (flag:
.I -s
), and/or
the time in seconds 
(flag:
.I -t
), at some sampling rate (flag:
.I -RN,
for sampling rate N).
.SH Input Format Conversion
The standard input reads 
.I floatsams
by default when connected to a file or pipe.  When connected to a terminal,
it defaults to expecting arithmetic expressions in
.B expr(3carl)
format (see below).
Input can be coerced
to be any of the same formats as are available for output, as listed
above, by providing a flag of the form
.I -iX
where
.I X
is, again, one of 
.I b, d, f, o, s,
or 
.I x.
(Again, input of 
.I floatsams
or
.I shortsams
from a terminal is neither possible nor particularly meaningful,
unless you are a computer).
.SH Data Ranges
.I Floatsam
data are nominally expected to range over the
signed unit interval (that is, the range [-1, +1]).
.I Shortsam
data are nominally expected to range over their maximum precision. 
For instance, 16-bit binary data can represent numbers in the interval
[-32768, +32767].
When converting from 
.I floatsam 
to
.I shortsam
data, scaling must be performed.  
In the typical case, the signed unit interval 
of floating point data is mapped by default into the 16-bit integer 
range [-32768, +32767].  Thus when 
.I shortsams,
are read, their values are
divided by 32767
so as to map the integer values
into the signed unit interval.  
If the output is 
.I floatsams,
these converted values are output directly.  If the output is
.I shortsams,
they are rescaled by being multiplied by 32767.
.PP
The various arabic formats are similarly scaled, to maintain symmetry.
Arabic floating point data is expected to be in the signed unit
interval, and decimal, octal and hexidecimal are are expected by default
to range over the 16-bit binary range of [32768, +32767].
.PP
The range of integer data can be modified.  The format specification
.I pN
sets the range (precision) of integer data formats.  For example,
the flag
.I -op2047
sets the integer output range to [-2048, +2047], appropriate for 12-bit
.I shortsam
format.
The precision flag can be set to anything, in fact, limited by the
precision of the host computer.  
However, please note that precisions larger than 16 bits will
only work with arabic input and output formats.
Setting
it to a value greater than the precision of 16-bit binary data will
not work if the input or output is 
.I shortsams,
because 
.I shortsams 
can't represent anything bigger than the interval
[-32768, 32767].
.SH Examples
.nf
.RS .5i
(xform reads floating point arabic, writes the same)
	% xform
(xform reads/writes floatsams)
	% wave | xform | sndout
(xform reads floatsams, writes arabic)
	% wave | xform
(xform reads arabic, writes floatsams)
	% xform | sndout
(xform reads/writes floating point arabic)
	% xform -if -of < file > other_file
(xform drives unix plotting programs)
	% wave -T.01 | xform -of | graph -a | plot -T4014
.fi
.RE
.SH Expressions
.B xform
also has the ability to apply arbitrary arithmetic expressions to the input
sample stream.  Multiple expressions may be given, with each being 
applied to the result of the last expression in a cascade fashion.
The output sample stream is the cumulative effect of all expressions.
The expression format is nearly identical to that of 
.B cmusic.
.PP
The current input sample is available in expressions as the symbol
.I x
(or
.I X,
upper case is equivalent
).
Thus, the minimal equation to 
.I xform 
is simply
.I x,
which merely copies the input sample to the output, just as does specifying
no expression at all.  
.PP
Note, the value of the sample can be expected to be
in the signed unit interval (unless modified by input format
conventions).
.PP
A history of the last 1024 input and output samples is kept in a circular
buffer.  These are
available in expressions via the special symbols:
.I xM
and
.I yN,
for past input 
.I M 
and past output
.I N,
respectively, where 
.I M
and
.I N
are integers giving the sample order.  Thus,
.I x0
is the same as
.I x,
which refer to the current input sample,
.I x1
is the immediately preceeding input sample, and so on.
Likewise, 
.I y1
refers to the last output sample, etc.
Thus, rather arbitrary filtering of signals is possible.
.PP
Here are some simple examples (comments in parenthesis):
.RS .5i
.nf
(Copy input to output).
	% wave | xform 
(Same as above).
	% wave | xform "x"
(Offset).
	% wave | xform "x+.5"
(Differentiate).
	% wave | xform "x-x1"
(Produce sine wave the hard way).
	% wave -wr | xform "sin(x*2*3.14)"
(Averaging filter).
	% wave | xform ".5*x-.5*x1"
(Multiple expressions, output value is 3)
	% wave -wd | xform "x+1" "x+1"
.fi
Note, the "" marks around arithmetic expressions keep the shell from 
trying to interpret characters such as '*'. 
.SH Format of Expressions
Expressions may contain several types of operands and operators.  
Expressions must not include blank spaces.
The syntax of expressions is a subset of that available in
.B cmusic.
The current list of possibilities
is as follows:
.PP
.RS .25i
.SH OPERANDS:
.IP "x or xN or XN" 15
refers to input sample x, or N'th previous input.
.IP "yN or YN" 15
refers to N'th previous input.
.IP numbers 15
Numbers may have three bases; all are of type float
whether they include a decimal point or not.
.IP decimal		
Any string of digits, which either includes a decimal
point, or which does not include a decimal point.
.IP hexadecimal	
If a number does not include a decimal point and starts
with the characters 0x, then base 16 is interpreted.
.IP octal		
If a number does not include a decimal point and
starts with the digit 0, base 8 will be interpreted.
.SH OPERATORS:
.IP PARENTHESES
Parentheses must balance, and may be used freely to establish
operator precedence.  Function arguments should be enclosed in
parentheses.
.IP UNOPS 
The following are unary operators available in expressions in order
precedence, with the first set of operators done before anything in the
second set.  Unary operations are done before binary operations, and
binary operations are done before post operations.
.RS .5i
.IP "{sin,cos,atan,ln,exp,floor,abs,sqrt,rand}"
(These are the standard trigonometric functions sine, cosine, 
and arctangent, from the UNIX math library, as well as the 
natural logarithm, exponential, floor, absolute value, and 
square root functions.  Rand is a function which returns a 
random value between 0 and its (positive) argument.)
.IP {-} 10
(Unary minus, as in -3*p5)
.RE
.SH
BINOPS 
.PP
The precedence is as shown below: ^ and % are done before * and /,
and * and / are done before + and -.
.RS .25i
.IP {^,%} 10
(3^.5 means 3 to the .5 power; 397%17 means 397 modulo 17)
.IP {*,/} 10
(5*79.2 means 5 times 79.2; 9/5 means 9 divided by 5 (float result))
.IP {+,-} 10
(3+3 means 3 plus 3, 3-8 means 3 minus 8)
.RE
.SH
POSTOPS 
.PP
Post operators are done last. They generally modify the resulting value
of the expression which preceeds them.
.RS .25i
.IP dB  
converts dB (logarithmic) to linear scale
example: -6dB = 10^(-6/20) = 0.5 (approx.).
.IP K   
converts K to units
example: 8K = 8 * 1024 = 8192.
.IP Deg 
converts degrees to radians
example: 180Deg = (180 / 360) * TWOPI = 3.14159.
.IP IS  
computes the sum of the first N inverse terms,
i.e., 3invs = 1 + 1/2 + 1/3. 0IS = 0 by definition.
.RE
.RE
.SH AUTHOR
Gareth Loy
.SH SEE ALSO
The expression format is a subset of that in
.B cmusic.
Not all things available there are necessarily available here.
Expression evaluation is provided via the subroutine 
.B expr(3carl).
.PP
.SH BUGS
For convenience, the notation
.I y,
which refers to the current output sample (i.e., the one not yet computed)
is supported; its value is defined to equal the current input sample.
The notation
.I y0
is undefined, and may produce garbage.
.PP
For simple format conversion, it replaces
.B btoa,
.B atob,
and
.B seefloat.
However, the implementation of the expression interpreter is grotesquely
inefficient for sample data computation.  Thus, it does not replace any
of the other CARL transform programs, because of its efficiency limitation.
In its defense, one can suppose that the time it takes to implement
a dedicated program to accomplish some transform
will be greater than the running time of
.B xform
itself.
