ECE 381: Laboratory 3 Winter 2006
Touch-tone telephone dialing and music synthesis February 7

    Part I. MATLAB notes MATLAB notes | Background discussion | Assignment

In this assignment, you will need to use such programming constructs of MATLAB as conditional statements, for loops, and functions.

Conditional statements: The most common way to execute alternative sets of statements conditionally is to use if statements. Another way is to use case statements, but this is not as versatile as the former. In other words, anything that can be accomplished by a case can also be accomplished by an if statement, but the converse is not true. So the following brief discussion is on if statements only.

The general form of an if statement in MATLAB is as follows:

if Condition 1,
    Statement[s] 1;
elseif Condition 2,
    Statement[s] 2;
else
    Statement[s] 3
end
Here, only the first if block (together with the associated statements) and the end termination are necessary. The elseif and else blocks are optional. However, while you may have mutiple elseif blocks, only one else block is allowed. Also, the conditions are checked in the order they are entered (from top to bottom), and only those statements associated with the first condition that is satisfied are executed; MATLAB does not continue checking the remaining conditions. In MATLAB, any expression that would evaluate to any value, not just to a Boolean value, can be used as a condition. A zero value is treated as Boolean "false," and any nonzero value as Boolean "true." Usual comparison operators <, <=,>, >=, == are all available. Also available are the logical operators &, |, and ~ for logical "and", "or", and "negation" operations, respectively. The operator for checking two values for being "not equal" is ~= in MATLAB. One point to note is that, in MATLAB, these operators work with general array arguments in the same manner as any arithmetic operator works. For example:
>> [ 10 5 1 ] > [ 8 5 6 ]
ans =
     1   0   0
>> [ 2 0; 50 -3 ] | [ 0 0; 1 10]
ans =
     1   0
     1   1
>> (1:2:9) <= 5
ans =
     1   1   1   0   0 
Although this may prove very powerful as a general programming tool, you will not need to use this feature in this assignment.

Loops: Given the rich set of element-wise operations on arrays, and operations between arrays, it is not incorrect to say that, in MATLAB, one would better stay away from running loops of any kind to the extent possible. This leads to not only simpler coding, but higher computational efficiency as well. Always remember that MATLAB is an interpreted language. In other words, the statements in your MATLAB code are read in, processed, and understood one by one by an interpreter, which subsequently carries out the necessary computation per each statement. Take as an example the task of computing the energy of a discrete-time signal x. If you were to do this by using a for-loop, then it would take many times longer to get the answer than if you used the simple sum(x.^2). This is because, when instructed to compute sum(x.^2), MATLAB essentially executes compiled code after a simple interpretation step, and the compiled code carries out the costly squaring and addition tasks as efficiently as they can get. On the other hand, in the case of doing the same computation using a MATLAB for loop, the cumulative cost of interpretation becomes far too high as the statements within the loop are interpreted again and again, and as compiled code is called repeatedly to do a miniscule computation per call. The trick for good MATLAB programming is, therefore, to formulate problems in such ways that array or matrix operations can be used to obtain the solutions. Of course, loops are not always escapable, and they are okay if the amount of computation per iteration is worth it, or if the total amount computation is not significant. Take this as a rule of thumb. If you are turning a long loop in MATLAB to do some miniscule computation per each iteration step, then the chances are good that there is a better way, not just in terms of execution speed, but also in terms of code length and simplicity. All it takes is some forethought to formulate the given problem right.

This general remark aside, you will want to use loops in this assignment. The two most common loop constructs in MATLAB are for and while statements, and their general forms are as given below:

while Condition,
    Statement[s];
    Some update to affect the Condition in the next round;
end

for var = vector of values for var,
    Do something[s] with the variable var;
end
MATLAB's while loop works in the usual way, similarly to a while loop, say, in C/C++. That is, the Condition is checked at the very beginning, and if it is not "true," the loop is not entered at all; otherwise, the loop is entered, and iterations continue until the Condition becomes "false." MATLAB's for loop, on the other hand, is a little different, as might be seen by reading the above form as "do something with each value in the vector supplied." Let us compute the energy of a discrete-time signal x to exemplify these two types of loops.
energy = 0;                   % initialize
while length(x) > 0,          % on entry, x has a certain number of elements
    energy = energy + x(1)^2; % add the square of the first sample value
    x = x(2:length(x));       % drop the first sample value (done with it)
end                           % on exit, x is empty

energy = 0;                   % initialize
for k = 1:length(x),          % for each index value running over the length
                              % of x
    energy = energy + x(k)^2; % add the square of the sample value at the
                              % current index
end                           % on exit, x remains the same as on entry
One last note, you could nest loops and/or conditional statements within each other to implement more complex behavior. You could thus alter the normal execution of a loop by using conditional continue or break statements within the loop body. Here, continue causes the remaining statements to be skipped, and the loop to continue with the next round, and break causes the loop to be aborted completely. Say, in computing the energy of x, you wish to skip negative sample values:
energy = 0;
while length(x) > 0,
    first = x(1);
    x = x(2:length(x));          % update x before possibly skipping over
    if first < 0, continue; end 
    energy = energy + first^2;
end
Say, you wish to compute the energy up to the first negative sample value:
energy = 0;
for k = 1:length(x),
    if x(k) < 0, break; end
    energy = energy + x(k)^2;
end

Functions: In the previous assignments, you used MATLAB scripts, which ran in the global scope (workspace). This potentially caused such problems as conflict among variable names and cluutering of the workspace with temporary variables, and made you attend to the bookkeeping of variables, their proper initialization in each script, and cleaning of the temporary ones at the end of a script. All this trouble could be easily avoided by using functions instead of scripts as functions run in the local scope. This enables you to reuse variable names without conflict and freeing you of the need to clear temporary variables as this happens automatically in a function. In addition to these advantages, most tasks come naturally with a set of inputs and outputs, and the most important argument for functions is arguably their resuability. Imagine modifying a script to play the different musical pieces of this assignment! The mantra with functions is, no more edit-cut-and-paste, but write-it-once, run-it-many-times-for-different-inputs. This typically requires a little bit more effort in the writing phase, but it is worth it.

MATLAB functions are stored in m-files as are MATLAB scripts. However, the first line (not counting possible leading comment lines) in a function m-file is a special declaration statement that specifies the inputs and outputs of your function as well as its name. Although the name of the file need not match the function name, using the same name for both is common practice, and it eliminates confusion and possible problems. The following N-input, M-output function, for example, is meant to be stored in a file named myfunc.m, which is either in the present working directory or in another directory on the MATLAB search path.

function [out1,out2, ..., outM ] = myfunc(in1,in2, ..., inN)
% MYFUNC   Short description
%     Long, detailed description
%     ...
%     (These leading comment lines are displayed when you call help on
%      this function.)
%     ...

Function definition (body):
    Statements that work on the inputs variables in1, in2, ..., inN,
    and compute values for the output variables out1, out2, ..., outM.
    To return the outputs to the calling environment, just assign values
    to them.
There is no special command to indicate end of function definition. It
ends and you return to the calling environment when the file ends, or when
another function declaration line is found as in the following (whichever
comes first).

function y = subfunc(x)
You can also have subfunctions available only within the scope of this
file. The input and output variables, x and y, of this subfunction could
have been used in the above function body or in other subfunctions. No
name conflicts would arise.

Now, although the output arguments are returned to the calling environment by simple assignments to them within the function body, there is a return command in MATLAB. It causes an immediate return from the function without execution of the rest of it. This can be useful in conditional termination of the function's execution, say upon detecting an error. By the way, good programs test their inputs to make sure that they satisfy any conditions they are supposed to satisfy. For example, if a particular input argument is to take non-negative integer values, what will your function do if you pass -3 for this argument? MATLAB's warning and error commands, both of which accept a message string to be displayed in the command window, are also useful to communicate such misuse with the caller. (A MATLAB string is a vector of characters enclosed in single quotes as in 'A string\nAnother one on the next line'.)

Secondly, how do you make some input arguments optional? The built-in MATLAB variable nargin is used for this purpose. This variable becomes defined only within the function body, and it holds the number of input arguments actually passed by the caller. Checking nargin and seeing that is less than N, the number of arguments in the declaration line, you can assign default values for the missing input arguments conditionally. Note though, this works easily if omissions are from the end of the input argument list. That is, if one input argument is missing, it is the last one; if two are missing, they are the last two. So on. Although it is technically possible to come up with more complex schemes of interpreting different nargin values as meaning different sets of inputs, take this example along the first, simpler line of thought:

if nargin == 3,
    fs = 8192;
elseif nargin ~= 4,
    error('myfunc: Wrong number of inputs!');
end
You could use this in your function for Exercise 1 of this assignment to make the sampling rate an optional input. You could use it in Exercise 2, too, with a slight modification.

Finally, there is also a nargout variable which similarly holds the actual number of output arguments queried by the caller. Its usage is similar to that of nargin. The difference is, omissions of output arguments should result in the omitted variables' being not assigned values within the function body. Many of the ADSP toolbox routines as well as many built-in MATLAB functions employ these techniques.

Miscellaneous: In both exercises of this assignment, the prescribed functions require generation of a side effect: play out the sampled signal to be returned. This amounts to nothing other than calling sound before returning from the functions.

Another MATLAB feature that is useful in this assignment is array concatenation. Recall the way you enter arrays at the command prompt, e.g., [ 1 2 3; 4 5 6 ] for a 2-by-3 matrix. This is nothing but horizontal concatenation, firstly, of 1-by-1 arrays [1], [2], and [3], secondly, of 1-by-1 arrays [4], [5], and [6], resulting in two 1-by-3 arrays, which are subsequently concatenated vertically. This generalizes to concatenation of matrices as in the parallel example: [ A1 A2 A3; A4 A5 A6 ]. However, note that A1, A2 and A3 must have the same number rows so that they can be lined up side by side horizontally. Likewise for A4, A5 and A6. For the subsequent concatenation step to work, the sum of the number of columns of A1, A2 and A3 must be equal to that of A4, A5 and A6 as well, so that [ A1 A2 A3 ] and [ A4 A5 A6 ] can be stacked vertically.


School of Computing and Engineering
University of Missouri - Kansas City
Last updated: February 05, 2006