Time detection with amplitude and duration filters

The time and frequency amplitude distributions of signals with a good signal-to-noise ratio can be used to automatically detect their time position (i.e. automatically annotate the audio files).

We will use as an example a recording from a long-billed hermit found in the folder “./examples/detection”. A long spectrogram will help to get an idea of the structure of the song in this species:

# cargar warbleR 
library(warbleR)

# parametros globales
warbleR_options(wl = 200, ovlp = 90, wav.path = "PONER RUTA A 'ejemplos/deteccion' AQUI", flim = c(2, 11))

# spectrograma largo
full_spec(ovlp = 50, sxrow = 26.5 / 12, rows = 12)

The auto_detec() function uses thresholds applied to amplitude envelopes as well as frequency range and duration filters to detect the position in time. The code below applies the following parameters to detect the songs:

  • A threshold of 14%
  • A filter of minimum duration of 0.1 s
  • A filter with a maximum duration of 0.17 s ‘A smoothing (’ ssmooth ’) of 400 samples
ad <- autodetec(threshold = 14, mindur= 0.1, maxdur = 0.17, bp = c(2, 11), ssmooth = 400, ls = TRUE, sxrow = 26.5 / 12, rows = 12)

 

The detection looks like this:

Detection using cross-correlation

Signals can be also be detected using spectrographic cross-correlation the package monitoR. This package aims to facilitate the detection of acoustic templates. The code here is similar but much less detailed than the vignette from monitoR, so I recommend Look at it if you want to get more information.

monitoR executes a cross-correlation between the sound files to search for the signals using previously defined templates. Therefore, templates must be clear samples of the signals we want to detect. Here is how the package works using the same recording as in the previous example.

First we need to create the template. We just have to provide the name of the sound file where the template is located, the beginning and the end, and the frequency range (an annotation). We will load the first song detected in the previous code:

library(monitoR)

pl1 <- makeCorTemplate("./examples/detection/LBH.374.SUR-2.wav", t.lim = c(ad$start[1], ad$end[1]), wl = 300, ovlp = 90, frq.lim = c(1, 11), dens = 1, name = "pl1")

## 
## Automatic point selection.
## 
## Done.

Now we can run the correlation over the entire file:

cscores <- corMatch(survey = "./examples/detection/LBH.374.SUR-2.wav", templates = pl1, parallel = FALSE, show.prog = FALSE, time.source = "fileinfo", cor.method = "pearson", warn = FALSE)
## 
## Starting  pl1 . . .
##  Fourier transform on survey . . .
##  Continuing. . .
## 
##  Done.

The detection peaks can be extracted with the findPeaks() function and plot them like this:

cdetects <- findPeaks(cscores)
## 
## Done with  pl1
## Done
# graficar
plot(cdetects, hit.marker="points")

However, that display is not useful for long files. Alternatively we can extract the values of the detections and use warbleR to visualize them. Detections can be extracted like this:

dtcs <- cdetects@detections[[1]]

 

  • Convert the detections produced with monitorR to a selection table with the format of warbleR

  • Use the full_spec() function to display the detections

 

Detect frequency range

To define the frequency range in an annotation usually involves “drawing” manually the selection boxes in Raven/Audacity/Syrinx. An alternative, and potentially less subjective, way is to infer the range using the energy distribution in the frequency domain by applying amplitude thresholds in the spectra. There are 2 functions of warbleR that do exactly that:

  • freq_range_detec(): detects the frequency range of the signals in ‘wave’ objects (as a function sewave). You can produce images in the graphics window if plot = TRUE.

  • freq_range(): applies freq_range_detec() iteratively to the signals in a selection table (like most warbleR functions). Image files are produced if img = TRUE which includes a spectrogram and a frequency spectrum for each selection.

freq_range_detec

freq_range_detec() works on ‘wave’ objects. In this example, we use it to detect the frequency range in the first ‘tico’ note:

w2 <- readWave("./examples/detection/LBH.374.SUR-2.wav", from = ad$start[1], 
               to = ad$end[1], units = "seconds")

data(tico)

tico1 <- cutw(tico, from = 0, to =  0.5, output = "Wave")

freq_range_detec(tico1, bp = c(2, 9.6), fsmooth = 1, threshold = 8)

##   bottom.freq top.freq
## 1     2.49165  4.91715

freq_range

As mentioned earlier, the frequency range can be calculated for the entire selection in a selection table using freq_range():

fr_ad <- freq_range(X = ad, bp = c(2, 12), fsmooth = 0.001, ovlp = 95, 
                          wl = 200, threshold = 10, img = FALSE)

head(fr_ad)
##         sound.files selec     start       end bottom.freq top.freq
## 1 LBH.374.SUR-2.wav     1 0.3325400 0.4673247     2.97675  8.70975
## 2 LBH.374.SUR-2.wav     2 0.8496606 0.9728126     2.97675  8.70975
## 3 LBH.374.SUR-2.wav     3 1.3889354 1.5192757     3.19725  8.48925
## 4 LBH.374.SUR-2.wav     4 1.9285731 2.0534712     3.19725  8.70975
## 5 LBH.374.SUR-2.wav     5 2.4643559 2.5838571          NA  8.70975
## 6 LBH.374.SUR-2.wav     6 2.9814085 3.1123383     2.97675  8.48925

 

Now we have a selection table with the “coordinates” of time and frequency for each song in the audio file.

 

  • Use the full_spec() function to display the selections in the “fr_ad” selection table

  • Convert the “fr_ad” selection table to an extended selection table (hint: function selection_table())

 

Session information

## R version 3.6.1 (2019-07-05)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.3 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=es_CR.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=es_CR.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=es_CR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=es_CR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] monitoR_1.0.7      kableExtra_1.1.0   warbleR_1.1.16    
## [4] NatureSounds_1.0.1 seewave_2.1.4      tuneR_1.3.3       
## [7] maps_3.3.0        
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_1.0.2        pracma_2.2.5      highr_0.8        
##  [4] pillar_1.4.2      compiler_3.6.1    bitops_1.0-6     
##  [7] iterators_1.0.12  tools_3.6.1       Sim.DiffProc_4.4 
## [10] zeallot_0.1.0     digest_0.6.21     viridisLite_0.3.0
## [13] tibble_2.1.3      evaluate_0.14     pkgconfig_2.0.2  
## [16] fftw_1.0-5        rlang_0.4.0       rstudioapi_0.10  
## [19] yaml_2.2.0        parallel_3.6.1    xfun_0.9         
## [22] xml2_1.2.2        httr_1.4.1        stringr_1.4.0    
## [25] knitr_1.24        vctrs_0.2.0       hms_0.5.1        
## [28] webshot_0.5.1     glue_1.3.1        R6_2.4.0         
## [31] dtw_1.21-3        jpeg_0.1-8        pbapply_1.4-2    
## [34] rmarkdown_1.15    soundgen_1.5.0    readr_1.3.1      
## [37] magrittr_1.5      scales_1.0.0      backports_1.1.4  
## [40] htmltools_0.3.6   MASS_7.3-51.4     rvest_0.3.4      
## [43] colorspace_1.4-1  Deriv_3.8.5       stringi_1.4.3    
## [46] proxy_0.4-23      munsell_0.5.0     signal_0.7-6     
## [49] RCurl_1.95-4.12   crayon_1.3.4      rjson_0.2.20