function [mag,pts] = locatespeech(sig,N,step,fs)
% [magnitude,points] = locatespeech(signal, window, step, samplingfreq)
%
% locatespeech - returns cut magnitude and a vector of endpoints (pts) of speech signal.
%
% To find the enpoints, locatespeech does the following:
% 1) Removes any DC offset in the signal
% 2) Computes magnitude and zero-crossing rate of the signal
% 3) Computes magnitude and zero-crossing rate of noise at 1st 100 ms.
% 4) Set thresholds based on these values of noise
% 5) For start point:
% a) Find pt. where mag consistently tops upper mag threshold
% b) Work backwards to see where it goes below lower mag threshold
% c) Look in the previous 25 frames of zeroxing to see if it is still
% above the zero-xing threshold. If so, move it back to where it
% first drops below this threshold.
% 6) For end point, follow the same procedure as in (5) except reverse
% everything
%
% ELEC 301 Project - "Mars Lander the Theologian", aka, "Speaker Verification"
% Sara MacAlpine, Aamir Virani, Nipul Bharani, JP Slavinsky
% WRC (OCEE) Class of 2001 - Fall '99
% 1) Remove DC offset
sig_no_dc = removedc(sig);
% 2) Compute Avg. Mag and Zero-X rate of sig
m = avgmag(sig_no_dc,N,step);
z = zeroxing(sig_no_dc,N,step);
% 3) Compute mag and zero-crossing of noise (first 100 msec of sig) - already computed,
% just cut it out of m and z above
hundredmsec_rel = round((fs*.2)/step); % # samples that equals 100ms
% Ends of these may be corrupted due to zero padding -- chop off N/step
% samples from each side
chop = ceil((N/2-step)/step); % round up for safety
noise_m = m(2+chop:hundredmsec_rel-chop);
noise_z = z(2+chop:hundredmsec_rel-chop);
% Compute means and st. deviations of each, so we can develop thresholds.
noise_m_mean = mean(noise_m);
noise_m_std = std(noise_m);
noise_z_mean = mean(noise_z);
noise_z_std = std(noise_z);
% Set lower thresholds
fudge = 5;
ITL = noise_m_mean + fudge*noise_m_std;
IZCT = noise_z_mean + fudge*noise_z_std;
% Define upper threshold for avg mag.
ITU = 3.2*noise_m_mean; % since std << mean, twice the mean should cover it
% find place where sig consistently tops ITU.
start = 3; % since window goes back two spots, start at 3rd sample
avg_last3pts = 0; % ITU won't be topped in the first 3 pts, so initialize to 0
while avg_last3pts < ITU,
start = start + 1;
avg_last3pts = (m(start) + m(start-1) + m(start-2))/3;
end
% move backwards to find where we first go under ITL
while m(start) > ITL,
start = start - 1;
end
% See if need to move start back due to zero-crossing
below_izct_count = 0;
first_below = -999;
if start > 25
for i = start:-1:start-25,
if z(i) < IZCT
below_izct_count = below_izct_count + 1;
if first_below == -999
first_below = i;
end
end
end
if below_izct_count >= 3
start = first_below;
end
end
% Now do the same process backwards for the end;
endpt = length(m)-2;
avg_last3pts = 0; % threshhold won't occur in first 3 pts, so initialize to 0
while avg_last3pts < ITU,
endpt = endpt - 1;
avg_last3pts = (m(endpt) + m(endpt+1) + m(endpt+2))/3;
end
% move forwards to find where we first go under ITL
while m(start) > ITL,
endpt = endpt + 1;
end
% See if need to move start back due to zero-crossing
below_izct_count = 0;
first_below = -999;
if (endpt-length(z)) > 25
for i = endpt:1:endpt+25,
if z(i) < IZCT
below_izct_count = below_izct_count + 1;
if first_below == -999
first_below = i;
end
end
end
if below_izct_count >= 3
endpt = first_below;
end
end
% Return values (multiply endpoints by step so that it is scaled
% appropriately for the actual signal
mag = m(start:endpt);
pts = [start*step endpt*step];