File Exchange

image thumbnail


version (3.37 KB) by Steffen Brueckner
Detect zero (or any other) level crossing of signals.


Updated 05 Apr 2016

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.

Cite As

Steffen Brueckner (2021). crossing (, MATLAB Central File Exchange. Retrieved .

Comments and Ratings (41)

Conner Herndon

Bas-Jan Zandt

Thanks a lot! Like Krabbe commented, the addition can result in an error.


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.

Lorenzo Ciampolini

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



Pls try:

load iddata1

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

Patrick Krabbe

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);

big ted

Perfect, and clearly documented. Many thanks!


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



Raj Sodhi

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

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

Exactly what i needed, Thanks!

Raj Sodhi

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.


doesn't seem to work

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

Carlos Martinez

It doesn't work any more.

Patrick Tamellini

Great, worked ok for me.

Paulo Emmanuel

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

Eric T

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

Nauman Qureshi

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

MATLAB Release Compatibility
Created with R2007a
Compatible with any release
Platform Compatibility
Windows macOS Linux

Inspired: Ringdown

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!