Code

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

Comments:

kaz
Said:
Good point, however in 2's complement system you can avoid multiplier by checking sign bit change.
8 years ago
0
Reply
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
6 years ago
-2
Reply
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.
6 years ago
+1
Reply
Sorry, you need javascript enabled to post any comments.
shubham2ece
Said:
good work!
2 years ago
+1
Reply
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
7 months ago
0
Reply
Sorry, you need javascript enabled to post any comments.
atho123
Said:
anybody know the matlabcode for slnr precoding
4 months ago
0
Reply
Sorry, you need javascript enabled to post any comments.
Sorry, you need javascript enabled to post any comments.