File Exchange

image thumbnail


version 1.0 (3.37 KB) by

Detect zero (or any other) level crossing of signals.



View License

Editor's Note: This file was a File Exchange Pick of the Week

Detect the zero (or any other level) crossing of a given signal, either in discrete data points or using linear interpolation.

Comments and Ratings (39)


Weifu (view profile)

matlab should provide this function natively.
it works perfect on me :) thanks.
can change error(nargchk(1,4,nargin)); in line 35 to simply narginchk(1,4); to avoid the obselete warning.

I used it with Pierre Mégevand fix. I am now trying Krabbe's fix. Will report issues if any occurs.


Giurak (view profile)


grega (view profile)

Pls try:

load iddata1

If first element is about to cross zero, error's yielded. Pls fix.

I really like this function and use it often.
The addition (starting from line 96) does not check for index bounds. THIS IS A BUG AND SHOULD BE FIXED.
You can of course fix it locally, I did it this way:

lower_ind = ind-1;
lower_ind(lower_ind < 1) = 1;
upper_ind = ind+1;
upper_ind(upper_ind > numel(S)) = numel(S);
[~,II] = min(abs([S(lower_ind) ; S(ind) ; S(upper_ind)]),[],1);
ind2 = ind + (II-2); %update indices
ind2(ind2 < 1) = 1;
ind2(ind2 > numel(S)) = numel(S);
t0close = t(ind2);
s0close = S(ind2);

Robert Stead

Perfect, and clearly documented. Many thanks!


Nahid (view profile)

This will do the job:
number_of_crossing_zero = nnz(diff(sign(input_array(find(input_array)))))


Mon (view profile)


Raj Sodhi

Raj Sodhi (view profile)

Near the end, where it calculates closest points, I used the code:

len = length(t) ;
[CC,II] = min(abs([S(max(ind-1,1)) ; S(ind) ; S(min(ind+1,len))]),[],1);
ind2 = max(ind + (II-2),1); %update indices

t0close = t(ind2);
s0close = S(ind2);


Hartmut Wziontek has a nice fix for the problem with the endpoints in the program already, but just in case.
instead of
! [CC,II] = min(abs([S(ind(ind0)-1) ; S(ind(ind0)) ; S(ind(ind0)+1)]),[],1);
you can also do
! [CC,II] = min(abs([S(ind-ind0) ; S(ind) ; S(ind+ind0)]),[],1);
But it's pretty much the same I guess.

Mike B

Mike B (view profile)

Pierre Mégevand

A quick and dirty workaround for the error thrown by the function if the first zero crossing happens between samples 1 and 2 (cf. error message below) is to comment out the last 5 lines of the function (99:102). The first outputs of the function (ind, t0 and s0) remain unaffected.


??? Subscript indices must either be real positive integers or logicals.

Error in ==> crossing at 99
[CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);

Tor Arne

Naty S

Naty S (view profile)

Exactly what i needed, Thanks!

Raj Sodhi

Raj Sodhi (view profile)

If the sign change of S happens between index 1 and index 2, the code breaks, because S(ind-1) refers to S(0), which Matlab doesn't like.

Daniel Forsberg

One of the last lines:
[CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);
doesn't work if you have a zero-crossing between indices 1 and 2.


Clare (view profile)

doesn't seem to work

Index exceeds matrix dimensions.
Error in crossing (line 77)
t0 = t(ind);

It doesn't work any more.

Great, worked ok for me.

Don't know what to do. I'm kinda new at this.

??? Subscript indices must either be real positive integers or logicals.

Error in ==> crossing at 99
[CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);

Error in ==> AudioComp at 38
indexLeftZeroCross = crossing(leftFilteredData);

Yan Cui

M. A. Hopcroft

M. A. Hopcroft (view profile)

Eric T

Eric T (view profile)

Following generates error, same as Urs J error:
crossing([8 .1 -3 -5],[],1)

First Last

Hartmut Wziontek

Nice source, saved some time for me.
However, I'd suggest to following patch to avoid indexes out of range:

*** crossing.m.orig Tue Aug 26 07:41:32 2008
--- crossing.m Tue Aug 26 13:38:27 2008
*************** end
*** 96,103 ****
% Addition:
% Some people like to get the data points closest to the zero crossing,
% so we return these as well
! [CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);
! ind2 = ind + (II-2); %update indices

t0close = t(ind2);
! s0close = S(ind2);
\ No newline at end of file
--- 96,108 ----
% Addition:
% Some people like to get the data points closest to the zero crossing,
% so we return these as well
! % --- hwz 2008-08-26
! % make it work for data starting/ending with a zero crossing!
! ind0 = find(ind > 1 & ind < length(S));
! [CC,II] = min(abs([S(ind(ind0)-1) ; S(ind(ind0)) ; S(ind(ind0)+1)]),[],1);
! II = ind0(II);
! ind2 = ind;
! ind2(ind0) = ind2(ind0) + (II-2); %update indices

t0close = t(ind2);
! s0close = S(ind2);

René Truelsen

Excellent. Just what I was looking for. A function to find the zero-crossings of my LoG filtered signal

Urs J


Search for zeros in a=[-1 1], and it will "crash" at line 99 because index is set to 0.

Abhinav Jha

Is zero crossing, by definition, supposed to return all the indices at which the value of signal stays zero continually, or just the point at which zero is reached ? For eg if
a = [1 2 -1 0 0 0 1]
then should the return indices be
ind = [2 4 5 6],
or only
ind = [2 4].
Doesn't zero crossings mean the points at which zero is crossed ?

Islam Mohammed

if you need the number of crossing, NC.

NC = length(ind1) + length(ind0);

this is because if the signal cross zero exactly at the sample time it will not be calculated in ind1.

Sergio GM

It worked for me! Thanks.

Howard Fishman

For data far from 1, the eps test me not either not pass when you want to interpolate or pass when you shouldn't,

Change line 45 to
if abs(S(ind(ii))) > eps(S(ind(ii)))

Also change line 28 to
if nargin < 3 || isempty(level)

The condition of a peak (not a crossing) at exactly zero as described by Christian Rothleitner can be handled with the following

[t0, indx] = unique(t0);
ind = ind(indx);

Christian Rothleitner

In general a good algorithm. Just an improvement: First search for exact zeros. Otherwise you will count twice. Here the extension:
ind0 = find(S==0); %find amplitudes which are exactly zero
S1 = S(1:end-1) .* S(2:end);
ind1 = find(S1< 0);
ind_all_unsort = [ind0 ind1];
ind = sort(ind_all_unsort);%sorts values in ascending order
t0 = t(ind);

Alan Cumming

I found the same as Zach Lewis, it doesn't really find the correct point (it's one point off), and the interpolation doesn't work either (not only because the function specification line is wrong, either).

Jonathan Kellogg

I found that if you wanted it to linearly interpolate between the t points that you give it, you need to go through the code and everywhere you see par.interpolation you need to change to just par or it breaks on the 'linear' string that put in. Otherwise works well for me.

Zach Lewis

I found that with discrete data, it can be off 1 data point to the actual closest value (closest to 0). I've added this as a check
[CC,II] = min(abs([S(ind-1) S(ind) S(ind+1)]),[],2); %find closest value to zero around crossing
ind = ind+(II-2); %update indices

Rajeeva Kumar

Andre Frotta Muller

Very good!!!!


Mike Price



BSD license

MATLAB Release
MATLAB 7.4 (R2007a)

Inspired: Ringdown

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

» Watch video