EOD Simulator
Software
Opening Waveform
Software design for the EOD simulator required several interesting design
consideratons. First of all, the waveform was to be read from a standard file format which contained the individual
samples for the wave, as well as the sample rate and some text data on the wave. The file format read function enters
the raw voltage points into the appropriate variables. Then, the voltage points are normalized to a 0 baseline voltage with a 1.0
peak to peak voltage difference, and the timebase is centered. As the signals are generally acquired at sampling rates
much higher than the PC's maximum rate of 44 KHz, they must be resampled down from ranges of 100-250 KHz for proper output. This resampling is
accomplished with the MatLab resample function. Essentially, a ratio of the old signal to the new signal is formed.
sfactor=s_rate/1000; %% drop the sampling rate by factor of 1000
prate=44; %% This is the 44 KHz sampling rate required for sound card output
qrate=sfactor;
wave=resample(wave,prate,qrate); %%resamples wave by factor of p/q
Afterwards, a new timebase for the resampled signal is formed by creating a timebase to match the correct number of points in
the new signal, matching total signal length as well as required point spacing.
number_entries=size(wave); %%required to manually recalculate new timebase
number_entries=number_entries(1);
maxtime=size(time);
maxtime=maxtime(2);
accum_num=(time(maxtime)-time(1))/number_entries;
%%calculate the new time spacing for resampled signal
accum=time(1);
time=[];
for x=1:number_entries %%loop creates new time matrix
time=[time accum];
accum=accum+accum_num;
end;
As I was working on the reading algorithm, I realized that while each file contained all of the important signal information
within a 4 ms frame, that the padding on the frame was far from uniform. Some signals extended far past this frame with almost
0 signal size, while others were significantly shorter. Two small loops were added to truncate extra data from signals which
exceeded the 4 ms frame. The loops essentially scans the wave and records the points which are located within the bounds
desired and truncates the signal to the appropriate size as follows.
if time(1) < -2
for x=1:number_entries
if time(x) < -2
lowhold=x;
end;
if time(x) < 2
highhold=x;
end;
end;
%Truncate wave into 4 ms frame
wave=wave(lowhold:highhold);
time=time(lowhold:highhold);
The next task was to plot the wave onto axes. This was a fairly simple task, which just required setting the active axis and
plotting the wave within the correct boundaries. An interesting feature added to the end of the "read" routine was the display
of wave text information. By using a new UICONTROL outside the main loop, the wave text box could be redrawn on each subsequent
recalling of the open wave routine. Originally, I placed this control in the main control area, and found problems refreshing
the text with each new waveform. Placing the control here allows it to refresh with each new waveform.
Generating Wave Intervals
There were two specified ways for generating the wave intervals. Both of them generate
a matrix of 100 points, with a 1 representing a time period when the wave should be played and a 0 representing
silcence. The first method of generating this matrix is a random
selection of pulse intervals separations from 10 per second to 1 per second. In the interest of keeping roughly symmetrical
spacings, 6 different permutations of pulses and silences were used. The randperm command was used to generate random
permutations of the numbers from 1 to 6, and the first of these was used to select which of the 6 patterns would be in that
time duration. Creating a random permutation of the numbers from 1 to 6 and just selecting the first seemed a fairer way
than the normal random algorithm which would be difficult to weight equally from 1 to 6.
The other method for selecting intervals is an attempt to more closely approximate the
spacing which would ideally exist in nature. The user inputs a mean value for the interval spacing, a standard deviation,
and a minimum interval spacing length. The code for implementing this spacing algorithm traverses the 100 points between 0 and 10
seconds, jumping by a random interval based on the normal curve with the entered data as shown.
wavetime=zeros(100,1);
wavetime(1)=1;
i=1;
while i < 101
interval=round(max(int_mean+sd*randn,min_interval)*10);
i=i+interval;
wavetime(i)=1;
end
The 10 second frame was shown in a simple plot with vertical lines representing each pulse. The code for
this plot produced a series of lines in the frame at the appropriate locations, traversing the 100 points and drawing a line
at each point in wavetime which was designated by a '1'.
Playing the Sound
There were two different options for outputing the sound. The first one implemented was "continuous tenths". The
reason for this option was mostly for testing purposes. However, the feature was left as it might be useful if a person just
wants a continuous burst. One problem discovered while testing was that the tightly looped sound output function caused errors
opening the sound device. The reason discovered was that the Matlab function wavplay is an asynchronous operation, which plays
the sound while the program continues with other instrucions. As the next instruction was another sound call, it crashed the device.
I found that wavplay had to be run as a synchronous operation, which blocked the program until the call was done. As MatLab's
built-in delay function is rather sketchy and to ensure cross compatibility, pauses were implemented as matrices of appropriate size
to play as empty sound during interval spaces. These zero matrices were also played as synchronous operations to prevent crashing the
sound device.
The other output option was to follow the previously created timebase. This function worked basically the same as the continuous one. However,
this function traverses the interval matrix of 100 points and only plays if the point it is at is a '1', indicating that the sound
should be played at that point.
Webpage created by Joel Avrunin ('01).
Created November 12, 1999. Last modified December 13, 2000.