I assume this is a relatively simple DSP task, but I'm having trouble finding any information on how to approach my problem. Hopefully someone with more experience and brain power can help me out:

I have many (thousands) audio records of bird calls. I am looking for a technique that will identify the timestamps within each audio file during which the bird is chirping. Here's an example of a high quality audio file:

This is an example of a clean audio file, with little background noise

Ultimately, I wish to export a table of the frequencies created by the bird in each file, for further analysis. I've already created a Python program that will allow me to manually select data points of interest, but I'd like to automate the process.

The simplest process I can think of would be to set a minimum power threshold for data points of interest, but the audio files have varying degrees of background noise. Some of the audio files may be unusable due to background noise, which is fine, but they need to be flagged as such.

So the two questions are:
1) How to identify low-quality audio files
2) How to identify the useful sections of high-quality audio files


EDIT: I don't know why i thought this question was matlab based, but my solution is written with matlab in mind. a quick search showed my the python scikit has otsu's method for automatic thresholding (this is what matlab uses). Other than that I think most of the code is relatively python safe and can easily be translated. My apologies for my error

from skimage import filter
val = filter.threshold_otsu(camera)


Could you threshold the amplitude of the recording? say this is our recording

enter image description here

where we are just plotting


can we say the chirping is probably above 2? and assume everything below magnitude=2 is just noise? If so, and assuming you have the imageprocessing toolbox, you could

  1. normalize the audiofile amplitude (between 0-1) needed for next step
  2. get automatic thresholding of file imageprocessing toolbox function
  3. find indicies that exceed threshold and say these are bird chirps

the only problem is with sound even with a strong signal, it will usually cross 0 so you would have discontinuities even in the actual bird chirping. Maybe you can add some sort of hysteresis to the masking operation. Like if the current sample is below the threshold BUT a large percentage of the previous few samples were above the threshold, we will assume this sample is also an interest point

roughly your code would be something like this (im not near a comp with matlab, so this may have slight syntax errors). This is also not very optimized, but maybe it's a springboard for you or others

%% step 1
%we are using magnitude only
my_min = min(abs(soundfile));
my_max = max(abs(soundfile));

%gets sound file magnitude between 0-1 only
normalized_sound_mag = 1/(my_max-my_min) * (abs(soundfile) - my_min);

%% step 2
%get a threshold, we needed the magnitude between 0-1 for this function to work
sound_thresh = graythresh(normalized_sound_mag);

%% step 3
%this vector will store all sample indexes that are interesting
idx_sound = 0;

num_for_hysteresis = 10;        %the number of samples to use for hysteresis
hysteresis_percentage = 0.8;    %percentage of samples that must be above threshold
                                %so say in our set of 10, 2 samples are below threshold
                                %since .8 are above it, we say they are all of interest

%because the way we implement hysteresis we have to skip the first few samples
for (i=num_for_hysteresis:1:length(normalized_sound_mag))
    %if we are above thresh, without a doubt save the index
    if (normalized_sound_mag(i) > sound_thresh)
        idx_sound = [idx_sound, i];
        %hysteresis check prev samples, creates a boolean vector. 1 means value above thresh, 0 means it was below
        samples_above_thresh = normalized_sound_mag(i-num_for_hysteresis:i) > sound_thresh;

        %nnz, gets the number of nonzero elements in a matrix
        num_prev_samples_above_thresh = nnz(samples_above_thresh);

        %if the number of samples in the prev window met our criteria, this current sample 
        %is probably of interest as well
        if (num_prev_samples_above_thresh > hysteresis_percentage * num_for_hysteresis)
            idx_sound = [idx_sound, i];

%idx_sound should now have all the indicies f interest, these can now be used 
%directly on the original soundclip

we could also use the frequency power and threshold, rather than the sound amplitude, the basic outline would still be the same.

  • Wow, what a comprehensive response. Terms like "automatic thresholding", "Otsu's Method" and "hysteresis" are just what I was looking for to get me pointed in the right direction. I will have to play around with hysteresis and see how necessary it is-- each data point is already an 1 millesecond moving average, which should smooth out any discontinuities within the strong signals. Does the threshold imply anything about the signal to noise ratio? For example, would a threshold of 0.7 necessarily indicate a low-quality recording? – Keith L Feb 26 '15 at 6:28
  • I never thought about it that way but I would believe the threshold is related to SNR. Otsu basically tries to fit 2 Gaussian distributions to your histogram.The threshold is the avg of the two means.Imagine you had 2 Gauss dist N1(.2,.1) N2(.25,.1) the thresh would be .225 So while low, I'd say the chirp/silence are really close together and probably have a high SNR.It isn't exactly the SNR.Maybe using the means&variances you might be able to extract something closer to SNR like mean_chirp/mean_silence.You would have to build your own function for otsu thresh so you could access the means – andrew Feb 26 '15 at 20:56

Looks like good files contain a range of frequency power whereas low quality could be flagged if they lack such a range as you suggest

To identify interesting time points just create a time window starting a few moments prior to each frequency power spike lasting somewhat after such a peak

Animals know to repeat their chirps so you could boost confidence in seeing a high quality file if it contains repeat frequency power spikes with similar signatures

  • Thanks for the response, Scott. With regards to your first point, it's not so much a matter of calculating (Max Power - Min Power), but the signal-to-noise ratio. Do you think the simple equation SNR = μ/σ would be an adequate way to classify files as either "high quality" or "low quality"? I'll have to experiment. – Keith L Feb 26 '15 at 5:01
  • To your second point, can you recommend a way to identify how to size the time window around the peak? The calls vary in time length, so it's not a matter of simply saying +/-X milleseconds from the peak. What I've thought of is to start/end the window when the signal power drops below the noise threshold. Lastly, can you recommend a technique to compare signatures? – Keith L Feb 26 '15 at 5:12

Your Answer


By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.