Appendix C: Expression Evaluator

Overview

The Expression Evaluator is a versatile tool for manipulating and generating audio data.

The Destination box specifies the Sound window where results of the evaluation will be stored. The drop down list contains all Sound windows in the form "X - Filename", where X is the wave identifier number of the Sound window. For example, a Sound window with the title "Hello.wav" could appear as "1 - Hello.wav" in the list. By default, the destination is set to the current Sound window. You can change the destination, if more than one Sound window is opened, by using the up and down keys or by selecting it with the mouse from the drop down list.

The Source box lists currently opened Sound windows. By selecting a source from this list, the function waveX(n) is placed in the expression. X is the wave identifier number, as explained above. Note that if the source and destination are the same, then the source changes during processing.

The large Expression box located at the top of the window is where an expression is entered. A list of valid operations and functions is given in a following section. In most cases, expressions will be some function of n or t, just as in regular math, where y is usually a function of x (i.e. y = f(x)). In the expression evaluator, we can have destination = f(t), where f(t) is any expression you enter.

To create a simple tone, for example, you would enter the expression sin(600*t). You can even alter an existing sound. To double the volume of "1 - Hello.wav", for example, you would select it as the destination and enter the expression wave(n)*2.

To enter an expression, you can:

The evaluator uses several special variables, which you can initialize in the "Incremented variables" and "User constants" groups. These variables are discussed later.

After you have specified the destination, expression, and initial values, choose the Play button to preview it. Choose the OK button (or just press the Enter key) to begin evaluation. If you entered an expression incorrectly, a message will be displayed. If the expression is valid, a processing window will appear. Since the evaluation process takes time, you can stop it at any time with the Cancel button. No changes will be made to the sound if you cancel processing.

You can copy, cut and paste expression in the Expression box using the usual keystrokes (Copy = Ctrl+C, Cut = Ctrl+X, Paste = Ctrl+V). You can also copy and paste expression from the online help.

To speed up evaluation, make sure that you are using memory storage (see Options | Storage).

Evaluation Range, Variables, and Constants

Some knowledge of the structure of digital audio is essential to understand how the evaluator works. To illustrate this structure, let's assume we have the following sound:

Title bar:          Hello.wav
Total length:       2.0 seconds
Sampling rate:      8000Hz
Start marker:       0.5 seconds
Finish marker:      1.2 seconds
Figure: Internal Structure of Hello.wav, 8000Hz, 2 Seconds
File Structure

Digital audio is stored as a series of amplitudes, which are often referred to as samples (see figure). The evaluator interprets each sample as a value between -1 and 1, inclusive. Only samples between the start and finish markers are considered valid; all other values are assumed to be zero. The number of samples selected is defined as N.

Each sample has a relative index number, n, and a time, t. Since the time of each sample depends on the sampling rate, it is usually written in terms of the unit of time between each sample, T. You many have noticed that the time, t, is related to the index number, n, by the equation t=nT. The figure shows how all these variables relate to the structure of the sound.

Using Time in an Expression

Let's assume we have entered the expression "sin(t)". Since expressions are evaluated over the selection range, the initial value for t is automatically set to start marker's position of 0.5. Choosing the OK button evaluates the expression from t = 0.5 to t = 1.2 in steps of 1/8000 of a second, as defined by T. This means that the expression is calculated for each sample in the selection, changing each sample as follows:

Sample4000 = sin(0.500000)
Sample4001 = sin(0.500125)
Sample4002 = sin(0.500250)
...
Sample9600 = sin(1.200000)

Using the Sample Index in an Expression

The sample index is useful for modifying an existing sound. If we want to double the amplitude of Hello.wav, for example, we need to multiply each sample by two and store it back into the sound. In this case, Hello.wav will be both the destination and the source. To set it as the destination, we simply select it from the Destination list. To use it as a source, we need to determine its wave identifier number. These numbers are provided in the Source list. Assuming it is listed as "3 - Hello.wav", we now know that its wave identifier number is 3. This number is necessary for the evaluator's wave function, which has the following syntax:

waveX( n ) where: X = wave identifier number
n = sample index number

Note that when the destination and the source are the same, no number is needed after the wave function. If "wave(n)" is used, then the destination sound is assumed to be the source.

In the evaluator, the index number, n, is relative to the start marker. This means that the start markers position is added to the index number (i.e. n+Start). For the example in the figure above, a relative index of n=0 has an absolute index of 4000.

The final expression is "wave3(n)*2". Choosing OK evaluate this expression from n=0 to n=5600 in steps of 1 (note that N = 5600) . This produces the following changes (remember than n is relative to the start marker's position):

Sample4000 = Sample4000 * 2
Sample4001 = Sample4001 * 2
Sample4002 = Sample4001 * 2
...
Sample9600 = Sample9600 * 2

Note that N and n are always integers. The evaluator rounds indices to the nearest integer, so the expression "wave3(.7)" would be calculated as "wave3(1)".

You can use the sample index number and the wave function to mix two or more wave together. If you have several sounds opened, you can obtain the wave identifier number for each sound from the Source list. If the sounds you wanted to mix were identified as 2 and 3, you would enter the expression:

wave2(n) + wave3(n)

Care must be taken when indexing signals with different sampling rates. If wave1 is a voice recorded at 11025Hz and wave2 is music recorded at 22050Hz, then with wave1 as the destination you'd need to use this expression to correctly mix them:

wave1(n) + wave2(n*2)

Ideally, wave2 would have to be low-pass filtered first. If wave2 is the destination, the expression would be:

wave1(n/2) + wave2(n)

Also be aware that if the source and destination are the same, the source is modified during evaluation. An expression such as wave(n)+wave(n-3000)/3 generates a recursive reverb effect because wave(n-3000) gives the stored, modified values instead of the original source values. This allows for feedback processing. Use separate source and destination sounds to avoid modifying the source.

The variable N has several uses, such as reversing a sample. If wave2 is a new sound that has the same sampling rate and length of wave1, then setting the destination to wave2 and using the expression

wave1(N-n)

makes wave2 the reverse of wave1.

User Constants x, y, and f

User constants can be set to any values you choose. None of these values change during evaluation. They just provide a way of easily changing parameters within an expression without having to edit the expression directly. The constant f is typically used for frequency values. By using the expression

y*sin(2*pi*f*t)

you can generate any tone by specifying the frequency in the f box and the amplitude in the y box.

Conversion Between Variables

The following equations convert between time and sample index number. The start value is the position of the start marker (in seconds).

n = (t - start) / T
t = nT + start
T = 1 / (sampling rate)

Presets

The Presets list in the Expression Evaluator window organizes expressions in a number of groups, such as Dial Tones, Effects, Noise, and Waves. You can create new groups or add expression to existing groups.

To retrieve an expression:
  1. Expand the group containing the expression in the Presets list.
  2. Select the expression from the expanded list.
To add an expression:
  1. Enter the expression in the Expression box.
  2. Choose the add Add button in the Presets box.
  3. Select an existing group name or type in a new group name.
  4. Type in a preset name for the expression.
  5. Choose the OK button.
To delete an expression:
  1. Expand the group containing the expression in the Presets list.
  2. Select the expression from the expanded list.
  3. Choose the remove Remove button in the Presets box.

Evaluator Operators and Functions

The following table summarizes evaluator operators and functions.

Evaluator Operators and Functions
Label Operation, function
(, ) Parenthesis
+, *, -, / Add, multiply, subtract (negate), and divide
% Modulus operator (remainder)
<, > Greater and less than operators. Compares left and right operands. Gives 1 if true or 0 if false. For example, x > y evaluates to 1 if x is greater than y or 0 otherwise.

The expression
wave(n)*(wave(n)>0.001)
replace all samples below 0.001 with silence (zero).
^ To the power of, yx
pi Constant (3.14159...)
cos Cosine
sin Sine
tan Tangent
acos Arccosine
asin Arcsine
atan Arctangent
cosh Hyperbolic cosine
sinh Hyperbolic sine
tanh Hyperbolic tangent
sqrt Square root
abs Absolute value
sgn Sign (-1, 0, or 1).
log, ln Log base 10, natural logarithm
db, idb Converts a number to dB or converts a dB to a number. db(0.5) give -6.02.... idb(-6) gives 0.5....
exp Exponential base e
step Unit step ( 0 for t < 0, 1 for t >= 0 )
int Integer value
rand(n) Generates a uniform random number between 0 and n
limit Limits the value +/-1. If the absolute value is greater than 1, then its magnitude is set to 1.
waveX(n) Sound amplitude at n. X specifies the Sound window as given in the Source list. If no X is specified, the destination Sound window data is used.

Signal Generation

Several signal generation expressions are listed below. Words given in italics represent numeric values that you must enter.

To try one of the following expression:
  1. Choose New from the File menu.
  2. Choose OK to create the new file.
  3. Choose Expression evaluator from the Tool menu.
  4. Type in the expression as given in the example. For example:
        sin(2*pi*261.7*t)
  5. Choose the OK button.
  6. Wait for processing to complete.

Use the Play button to preview the expression before processing the entire file.

Expressions
Type General Expression Examples
Sine wave sin(2*pi*frequency*t) Middle C:
sin(2*pi*261.7*t)

Telephone dial tone for "5": (sin(2*pi*1336*t) + sin(2*pi*773*t)) / 2

Saw wave 1 - 2*abs(1 - 2*frequency*t%2) 200Hz tone:
1 - 2*abs(1 - 2*200*t%2)
White noise amplitude - rand(2*amplitude) Full volume white noise:
1 - rand(2)
Square wave int(2*t*frequency)%2*2-1 400Hz tone:
int(2*t*400)%2*2-1
Sweep sin(2*pi*t^rate) Slow sweep up to 20kHz:
sin( 2*pi*160*(t%5)^3 )
Exponential decay (1 - minimum)*exp(-t) + minimum 50% decay a 500Hz sine wave:
(0.5*exp(-t) + 0.5) * sin(2*pi*500*t)

Custom Filters

One way to create your own digital filter is to use MatlabTM (The Student Edition of Matlab, by The Math Works Inc., published by Prentice-Hall, ISBN 0-13-855974-0). It has many built-in commands that generate filter coefficients. The coefficients can then used in the Expression Evaluator command.

Example of a Low-Pass Filter

In preparation for down-sampling, you can use Matlab to generate the coefficients of a 4th order Butterworth low pass filter that will remove noise above half the Nyquist frequency (one quarter the sampling rate). Enter:

[b,a] = butter(4, 0.5)

The result should be similar to:

b =  0.0940  0.3759  0.5639  0.3759  0.0940
a =  1.0000  0.0000  0.4680  0.0000  0.0177

To implement this filter in the evaluator, assume that the sound to be filtered is in the Sound window titled Sound.wav.

  1. Use File | New to create a new Sound window with the same sampling rate and channels as Sound.wav.
  2. Make sure the length of the new sound is as long (or longer) than Sound.wav.
  3. Use Tool | Expression Evaluator to open the expression evaluator window.
  4. Set the destination to the new sound.
  5. Enter the following expression (assuming Sound.wav has a wave identifier of 1):
    	wave1(n)*0.0940 + wave1(n-1)*0.3759 +
    	wave1(n-2)*0.5639 + wave1(n-3)*0.3759 +
    	wave1(n-4)*0.0940 - wave2(n-2)*0.4860 -
    	wave2(n-4)*0.0177
    
  6. Choose OK to start filtering.