Skip to content

Instantly share code, notes, and snippets.

@endolith
Last active September 16, 2020 18:15
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save endolith/129445 to your computer and use it in GitHub Desktop.
Save endolith/129445 to your computer and use it in GitHub Desktop.
Count zero crossings to determine frequency
function [frequency, period, crossings, seconds, samples]=freq(wavefile, siz)
% FREQ Measures frequency of mono .WAV files by counting zero crossings
%
% [frequency, period, crossings, seconds, samples]=freq(wavefile, siz, fmt24bit)
%
% frequency : in hertz
% period : in seconds
% crossings : the total number of zero crossings
% seconds : total amount of time between first and last zero crossing
% samples : total number of samples between first and last zero crossing
%
% wavfile : file name
% (The ".wav" extension is appended if no extension is given.)
% siz : 'size' returns the size of the audio data
% : [N1 N2] returns only samples N1 through N2
% : N1 returns the first N1 samples
% : default is all the data
% endolith@gmail.com July 12th, 2005
% Meant to measure frequency very accurately, for comparing ADC clocks. Only useful in the specific circumstance I was using it, with long wav files and signal much larger than noise, so that noise doesn't cause spurious zero crossings
% Show help
if nargin < 1
help freq;
return;
end
%Load WAV file
if nargin < 2
[sig, sf, bits] = wavread (wavefile);
else
if nargin < 3
[sig, sf, bits] = wavread (wavefile, siz);
end
end
%We need high precision for these numbers
output_precision(9)
%Find all zero crossings
c=[(sig(1:size(sig,1)-1)<=0).*(sig(2:size(sig,1))>0);0];
%Find locations of the rising edge zero crossings
a=find(c);
%Calculate number of samples between first and last zero crossing (relevant data)
samples=(a(size(a,1)))-a(1)
% Should specify the precision of the measurement (1000.0 Hz for a short sample, 1000.00000 Hz for a long sample?)
%Calculate time in seconds of relevant section
seconds=samples/sf
%Number of crossings in relevant section
crossings=size(a,1)-1
%Frequency is crossings per second
frequency=crossings*sf/samples
period=1/frequency
%Plot
%closeplot
%d=zeros(size(sig,1),1);
%d(a(1):a(size(a,1))-1)=1;
%dsize = size(d(d>0),1)
%t = [1:size(sig,1)];
%plot(t,sig,t,c,t,d)
%allcs = size(c(c>0),1)
from __future__ import division
from numpy import logical_and, average, diff
from matplotlib.mlab import find
def freq_from_crossings(sig, fs):
"""Estimate frequency by counting zero crossings
Doesn't work if there are multiple zero crossings per cycle.
"""
indices = find(logical_and(sig[1:] >= 0, sig[:-1] < 0))
# Linear interpolation to find truer zero crossings
crossings = [i - sig[i] / (sig[i+1] - sig[i]) for i in indices]
return fs / average(diff(crossings))
@lewham97
Copy link

@endolith I’m looking to count zero crossings of a square wave with a peak of 3.3v using a Raspberry Pi to calculate the frequency. I’m hoping that this code will be suitable for the job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment