## Zero Crossing Counter

July 9, 20119 comments Coded in Matlab

In some DSP applications, it can be very helpful to know how many times your signal has crossed the zero-line (amplitude origin).

How is this helpful?  Well, zero-crossings can tell you very quickly if your signal is composed of high frequency content or not.  Let's say your sample rate is 50kHz and over a small window of 1,000 samples there are 500 zero-crossings.  That would mean that every two samples crosses the zero-line (i.e. 12.5kHz)

In speech processing, the zero-crossing counts can help distinguish between voiced and un-voiced speech.  Un-voiced sounds are very noise-like ('Shh' and 'Sss' for example).  In addition, zero-crossings could also be used to determine if your signal has a DC offset.  If you signal is 'muted' and you are not seeing alot of zero-crossings might mean that your signal is offset from the zero-line

One nice thing about the matlab code below is that it is implemented in a very DSP-friendly way.  It ports very easily into C-Code and does minimizes the amount of conditional statements for faster processing time.

``````function count = zero_crossings(x)
% Count the number of zero-crossings from the supplied time-domain
% input vector.  A simple method is applied here that can be easily
% ported to a real-time system that would minimize the number of
% if-else conditionals.
%
% Usage:     COUNT = zero_crossings(X);
%
%            X     is the input time-domain signal (one dimensional)
%            COUNT is the amount of zero-crossings in the input signal
%
% Author:    sparafucile17 06/27/04
%

% initial value
count = 0;

% error checks
if(length(x) == 1)
error('ERROR: input signal must have more than one element');
end

if((size(x, 2) ~= 1) && (size(x, 1) ~= 1))
error('ERROR: Input must be one-dimensional');
end

% force signal to be a vector oriented in the same direction
x = x(:);

num_samples = length(x);
for i=2:num_samples

% Any time you multiply to adjacent values that have a sign difference
% the result will always be negative.  When the signs are identical,
% the product will always be positive.
if((x(i) * x(i-1)) < 0)
count = count + 1;
end

end`````` kaz
Said:
Good point, however in 2's complement system you can avoid multiplier by checking sign bit change.
8 years ago
0
Sorry, you need javascript enabled to post any comments. prudentior
Said:
The code is not correct because n consecutive values == 0 are counted as n-1 zero crossings. Here a different code: % zerocross_count.m clear all clc % Pay attention: 0, must considered (as in 2' complement arithmetic) % as a positive value. % Then two successive values 0 -> 1 not corresponds to a cross, % but the succession -1 -> 0 represents a true cross. v(1,1:6) = [0 0 0 0 0 0]; % No zero crossing v(2,1:6) = [0 0 0 0 0 1]; % No zero crossing v(3,1:6) = [-1 -1 -1 -1 -1 0]; % 1 zero crossing v(4,1:6) = [1 0 0 -1 1 1]; % 2 zero crossing v(5,1:6) = [1 eps 0 -eps 0 -eps]; % 3 zero crossing s = size(v); % size of matrix v l = s(1); % Number of row of matrix v for m=1:l x = v(m,:); disp(' ') disp(['New input vector x: ', num2str(x)]) disp(' ') num_samples = length(x); count = 0; for n=2:num_samples if((x(n) * x(n-1)) <= 0) count = count + 1; end end disp(['Method of product, count = ', num2str(count)]) % Method, eliminating the defects of precedent code x_sign = sign(x); % Negative: -1, Zero: 0, Positive 1 index_0 = find(x_sign == 0); % Index of elements == 0 x_sign(index_0) = 1; % Set elements == 0 to 1 x_sign_diff = diff(x_sign); % Change of sign detection count_ = length(find(x_sign_diff ~= 0)); % Not == 0 means a jump of sign disp(' ') disp(['Method using sign and diff, count = ', num2str(count_)]) disp(' ') end
7 years ago
-2
Sorry, you need javascript enabled to post any comments. sparafucile17
Said:
prudentior, You are correct that consecutive zero's will count as zero-crossings. It is a small mistake on line 36. It should be compared as < 0 and not <=0. I have corrected the code above, so you can still use the DSP-friendly method cited in this example.
7 years ago
+1
Sorry, you need javascript enabled to post any comments. shubham2ece
Said:
good work!
2 years ago
+1
Sorry, you need javascript enabled to post any comments. weetabixharry
Said:
The suggested implementation only counts *consecutive* samples that cross zero. So, for example, x = [-1,0,1] will not be considered as a zero crossing. In many cases, this would be undesirable behaviour.

If you want to count all zero crossings, then something like this would probably be closer to what you need:

function count = zero_crossings(x)

count = 0;

% Check trivial cases
if numel(x) < 2
return;
end

% Error checks
assert(isvector(x), 'ERROR! Input must be a vector.');

% Pre-compute all signs for speed in MATLAB.
% N.B. This both checks sign bit AND checks for zero values.
signs = sign(x);

% Initialise s to first non-zero sign (+1 or -1)
i0 = 0;
s = 0;
while s == 0
i0 = i0 + 1;
s = signs(i0);
end

% Count zero crossings
for i = i0+1:length(x)
% Note: This ignores zeros
if signs(i) == -s
count = count + 1;
s = signs(i);
end
end
9 months ago
0 