R/bgNoise.R

Defines functions bgNoise

Documented in bgNoise

#' @title Background Noise and Soundscape Power Index
#'
#' @description Calculate the Background Noise and Soundscape Power values of a single audio using the methodology proposed in Towsey 2017
#'
#' @param soundfile tuneR Wave object or path to a valid audio file
#' @param channel channel where the metric values will be extract from. Available channels are: `"stereo"`, `"mono"`, `"left"` or `"right"`. Defaults to `"stereo"`
#' @param timeBin size (in seconds) of the time bin. Set to `NULL` to use the entire audio as a single bin. Defaults to `60`
#' @param dbThreshold minimum allowed value of dB for the spectrograms. Set to `NULL` to leave db values unrestricted Defaults to `-90`, as set by Towsey 2017
#' @param targetSampRate desired sample rate of the audios.  This argument is only used to down sample the audio. If `NULL`, then audio's sample rate remains the same. Defaults to `NULL`
#' @param wl window length of the spectrogram. Defaults to `512`
#' @param window window used to smooth the spectrogram. Switch to `signal::hanning(wl)` to use hanning instead. Defaults to `signal::hammning(wl)`
#' @param overlap overlap between the spectrogram windows. Defaults to `wl/2` (half the window length)
#' @param histbreaks breaks used to calculate Background Noise. Available breaks are: `"FD"`, `"Sturges`", `"scott"` and `100`. Defaults to `"FD"`.
#' <br>Can also be set to any numerical value to limit or increase the amount of breaks.
#' @param DCfix if the DC offset should be removed before the metrics are calculated. Defaults to `TRUE`
#'
#' @returns This function returns a [noise.matrix-class] object
#'
#' @details Background Noise (`BGN`) is an acoustic metric that measures the most common continuous baseline level of acoustic energy in a frequency window and in a time bin. It was developed by Towsey 2017 using the Lamel et al 1981 algorithm.
#' The metric is calculated by taking the modal value of intensity values in temporal bin c in frequency window f of a recording:
#'
#'\deqn{BGN_{f} = mode(dB_{cf})}
#'
#'Soundscape Power represents a measure of signal-to-noise ratio. It measures the relation of BGN to the loudest intensities in temporal bin c in frequency window f:
#'
#'\deqn{POW_{f} = max(dB_{cf}) - BGN_{cf}}
#'
#' This mean we'll have a value of BGN and POW to each frequency window of a recording.
#'
#' @references
#' Towsey, M. W. (2017). The calculation of acoustic indices derived from long-duration recordings of the natural environment. In eprints.qut.edu.au. https://eprints.qut.edu.au/110634/
#' <br>Lamel, L., Rabiner, L., Rosenberg, A., & Wilpon, J. (1981). An improved endpoint detector for isolated word recognition. IEEE Transactions on Acoustics, Speech, and Signal Processing, 29(4), 777-785 https://doi.org/10.1109/TASSP.1981.1163642
#'
#'@export
#'@importFrom signal specgram
#'@importFrom tuneR readWave
#'@importFrom tuneR readMP3
#'@importFrom tuneR downsample
#'
#' @examples
#' ### For our main example we'll create an artificial audio with
#' ### white noise to test its Background Noise
#' # We'll use the package tuneR
#' library(tuneR)
#'
#' # Define the audio sample rate, duration and number of samples
#' samprate <- 12050
#' dur <- 60
#' n <- samprate * dur
#'
#' # Then we generate white noise
#' set.seed(413)
#' noise <- rnorm(n)
#'
#' # Linear fade-out envelope
#' fade <- seq(1, 0, length.out = n)
#'
#' # Apply fade
#' signal <- noise * fade
#'
#' wave <- Wave(left = signal, right = signal,
#'             samp.rate = samprate,
#'             bit = 16)
#'
#' # Heres our artificial audio
#'
#' wave
#'
#' # Running the bgNoise function with all the default arguments
#' bgn <- bgNoise(wave)
#'
#' # See the results
#' bgn
#'
#' # Plot background noise and soundscape power
#' plot(bgn)
#'
#'\donttest{
#' ### This is a secondary example using audio from a real soundscape
#' ### These audios are originated from the Escutadô Project, a project
#' ### that records the soundscapes of the brazilian semiarid
#' # Getting audiofile from the online Zenodo library
#' dir <- paste(tempdir(), "forExample", sep = "/")
#' dir.create(dir)
#' rec <- paste0("GAL24576_20250401_", sprintf("%06d", 0), ".wav")
#' recDir <- paste(dir, rec , sep = "/")
#' url <- paste0("https://zenodo.org/records/17575795/files/",
#'               rec,
#'               "?download=1")
#'
#' # Downloading the file, might take some time denpending on your internet
#' download.file(url, destfile = recDir, mode = "wb")
#'
#' # Running the bgNoise function with all the default arguments
#' bgn <- bgNoise(recDir)
#'
#' # Here's the result
#' bgn
#'
#' # Plot background noise and soundscape power values
#' plot(bgn)
#'
#' # Plot the two indices against each other
#' plot(bgn@values$left$BGN$BGN1, bgn@values$left$POW$POW1,
#'      xlab = "BGN (dB)", ylab = "POW (dB)", pch = 16)
#'
#' # Now lets test and plot their correlation
#' BGNPOWlm <- lm(bgn@values$left$BGN$BGN1~bgn@values$left$POW$POW1)
#' summary(BGNPOWlm)
#' abline(lm(bgn@values$left$BGN$BGN1~bgn@values$left$POW$POW1), col = "red")
#'}
bgNoise <- function(soundfile,
                    channel = "stereo",
                    timeBin = 60,
                    dbThreshold = -90,
                    targetSampRate = NULL,
                    wl = 512,
                    window = signal::hamming(wl),
                    overlap = ceiling(length(window) / 2),
                    histbreaks = "FD",
                    DCfix = TRUE) {

  argHandler(FUN = "bgNoise", channel, timeBin, dbThreshold, targetSampRate, wl,
             window, overlap, histbreaks, DCfix)

  audio <- if (is.character(soundfile)) {
    fileExt <- tolower(tools::file_ext(soundfile))
    if (fileExt %in% c("mp3", "wav")) {
      if (fileExt == "mp3") {
        tuneR::readMP3(soundfile)
      } else {
        tuneR::readWave(soundfile)
      }
    } else {
      stop("The audio file must be in MP3 or WAV format.")
    }
  } else {
    soundfile
  }

  if(channel == "mono" && audio@stereo) {
    audio <- tuneR::mono(audio, which = "both")
  }

  if (channel == "stereo" && !audio@stereo) {
    message("Audio is not stereo, defaulting to left channel.")
    channel <- "mono"
  }

  if (!is.null(targetSampRate)) {
    audio <- tuneR::downsample(audio, targetSampRate)
  }

  BGNexp <- processChannel(
      audio,
      channel = channel,
      timeBin = timeBin,
      wl = wl,
      overlap = overlap,
      dbThreshold = dbThreshold,
      window = window,
      histbreaks = histbreaks,
      DCfix = DCfix,
      noiseOBJ = new("noise.matrix")
    )

  if (BGNexp@channel == "stereo") {
    BGNexp@wl <- nrow(BGNexp@values$left$BGN)

  } else {
    BGNexp@wl <- nrow(BGNexp@values[[channel]]$BGN)

  }

  return(BGNexp)

}

Try the Ruido package in your browser

Any scripts or data that you put into this service are public.

Ruido documentation built on April 18, 2026, 5:07 p.m.