Computing Bioacoustic

# Install and load required packages
packages <- c("tuneR", "soundecology", "seewave")
installed <- installed.packages()[, "Package"]
new_packages <- packages[!packages %in% installed]
if (length(new_packages) > 0) install.packages(new_packages)

library(tuneR)
## Warning: package 'tuneR' was built under R version 4.3.3
library(soundecology)
## Warning: package 'soundecology' was built under R version 4.3.3
library(seewave)
## Warning: package 'seewave' was built under R version 4.3.3
# Step 1: Read the audio file (ensure the correct file path)
audio_path <- "C:/Users/lenovo/Downloads/DATA ZOOM H2N-20241003T073619Z-001/DATA ZOOM H2N/ZOOM0022 (Petak 5).WAV"

# Ensure the file exists before proceeding
if (!file.exists(audio_path)) stop("File not found: ", audio_path)

audio <- tryCatch({
  readWave(audio_path)
}, error = function(e) {
  stop("Failed to read audio file: ", e$message)
})

# Display the metadata of the audio file to verify the file has been loaded correctly
print(audio)
## 
## Wave Object
##  Number of Samples:      13622400
##  Duration (seconds):     308.9
##  Samplingrate (Hertz):   44100
##  Channels (Mono/Stereo): Stereo
##  PCM (integer format):   TRUE
##  Bit (8/16/24/32/64):    16
# Define processing parameters
segment_duration <- 60  # Duration of each segment in seconds
samples_per_segment <- segment_duration * audio@samp.rate  # Number of samples per segment

# Define frequency ranges for sonotyping
anthrophony_range <- c(0, 255)   # Human-made sounds
biophony_range    <- c(1001, 5000) # Biological sounds
geophony_range    <- c(256, 1000)  # Natural, non-biological sounds

# Initialize counters for each sound type
anthrophony_count <- 0
biophony_count    <- 0
geophony_count    <- 0

# Initialize total time counters for each sound type
anthrophony_total_time <- 0
biophony_total_time    <- 0
geophony_total_time    <- 0

# Initialize lists to store bioacoustic indices
aei_values <- c()
ndsi_values <- c()
adi_values <- c()
bioacoustic_index_values <- c()

# Calculate the number of segments
num_segments <- ceiling(length(audio@left) / samples_per_segment)

# Loop over segments and process each one
for (i in 1:num_segments) {
  start_sample <- ((i - 1) * samples_per_segment) + 1
  end_sample   <- min(i * samples_per_segment, length(audio@left))
  
  # Extract the segment
  segment_left <- audio@left[start_sample:end_sample]
  
  # Ensure the segment has enough data
  if (length(segment_left) < 1024) {  # Adjust minimum length requirement
    message(paste("Segment", i, "is too short for analysis, skipping..."))
    next
  }
  
  # Create the segment object
  segment <- Wave(left = segment_left, right = segment_left, samp.rate = audio@samp.rate, bit = audio@bit)
  
  # Calculate mean amplitude of the segment
  mean_amplitude <- mean(abs(segment_left))  # Using absolute values to avoid negative amplitudes
  
  # ---- Sonotyping Analysis ---- #
  fft_segment <- fft(segment@left)
  n <- length(segment@left)
  frequencies <- seq(0, segment@samp.rate / 2, length.out = floor(n / 2) + 1)
  magnitude <- Mod(fft_segment)[1:(floor(n / 2) + 1)]
  
  # Extract the dominant frequency (frequency with the highest magnitude)
  dominant_freq <- frequencies[which.max(magnitude)]
  sonotype <- "Unknown"
  
  if (exists("dominant_freq")) {
    # Classification based on dominant frequency
    if (dominant_freq >= anthrophony_range[1] && dominant_freq <= anthrophony_range[2]) {
      sonotype <- "Anthrophony (Human-made noise)"
      anthrophony_count <- anthrophony_count + 1
      anthrophony_total_time <- anthrophony_total_time + segment_duration
    } else if (dominant_freq >= biophony_range[1] && dominant_freq <= biophony_range[2]) {
      sonotype <- "Biophony (Biological sounds)"
      biophony_count <- biophony_count + 1
      biophony_total_time <- biophony_total_time + segment_duration
    } else if (dominant_freq >= geophony_range[1] && dominant_freq <= geophony_range[2]) {
      sonotype <- "Geophony (Natural non-biological sounds)"
      geophony_count <- geophony_count + 1
      geophony_total_time <- geophony_total_time + segment_duration
    }
  }
  
  # Calculate the time (in minutes) from the start of the audio file
  segment_time_minutes <- (start_sample - 1) / audio@samp.rate / 60
  
  # ---- Plot the Spectrogram for the segment ---- #
  tryCatch({
    par(mfrow = c(1, 1))  # Reset to single plot
    par(mar = c(4, 4, 2, 1))  # Set margins for the plot
    spectro(segment, f = audio@samp.rate, flim = c(0, 5), 
            main = paste("Spectrogram of Segment", i), collevels = seq(-40, 0, 1))
  }, error = function(e) {
    message("Error in Spectrogram for segment ", i, ": ", e$message)
  })
    
  # Log the mean amplitude, dominant frequency, time (in minutes), and sonotype
  message(paste("Segment", i, "Time (minutes):", round(segment_time_minutes, 2), 
                "- Mean Amplitude:", round(mean_amplitude, 4), 
                "- Dominant Frequency:", round(dominant_freq, 2), "Hz", 
                "- Sonotype:", sonotype))
  
  # ---- Plot the Oscillogram for the segment ---- #
  tryCatch({
    par(mfrow = c(1, 1))  # Reset to single plot
    par(mar = c(4, 4, 2, 1))  # Set margins for the plot
    plot(seq_along(segment@left) / segment@samp.rate, segment@left, type = "l", 
         main = paste("Oscillogram of Segment", i), xlab = "Time (seconds)", ylab = "Amplitude")
  }, error = function(e) {
    message("Error in Oscillogram for segment ", i, ": ", e$message)
  })
  
  # ---- FFT of the Audio Segment ---- #
  tryCatch({
    par(mfrow = c(1, 1))  # Reset to single plot
    par(mar = c(4, 4, 2, 1))  # Set margins for the FFT plot
    plot(frequencies, magnitude, type = "l", main = paste("FFT of Segment", i), 
         xlab = "Frequency (Hz)", ylab = "Magnitude", col = "black", lwd = 2)
  }, error = function(e) {
    message("Error in FFT for segment ", i, ": ", e$message)
  })
  # ---- Calculate Bioacoustic Indices ---- #
  tryCatch({
    aei_result <- acoustic_evenness(segment)
    ndsi_result <- ndsi(segment)
    adi_result <- acoustic_diversity(segment)
    bioacoustic_result <- bioacoustic_index(segment)
    
    # Store the results
    aei_values <- c(aei_values, mean(c(aei_result$left, aei_result$right)))
    ndsi_values <- c(ndsi_values, mean(c(ndsi_result$left, ndsi_result$right)))
    adi_values <- c(adi_values, mean(c(adi_result$left, adi_result$right)))
    bioacoustic_index_values <- c(bioacoustic_index_values, mean(c(bioacoustic_result$left, bioacoustic_result$right)))
    
  }, error = function(e) {
    message("Error in calculating bioacoustic indices for segment ", i, ": ", e$message)
  })
}
## Segment 1 Time (minutes): 0 - Mean Amplitude: 161.3197 - Dominant Frequency: 38.12 Hz - Sonotype: Anthrophony (Human-made noise)

## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Evenness Index: 
##    Left channel: 0.159749
##    Right channel: 0.159749
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
##   Normalized Difference Soundscape Index:
## 
##    Left channel: 0.8963975
##    Right channel: 0.8963975
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Diversity Index: 
##    Left channel: 2.236363
##    Right channel: 2.236363
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Bioacoustic Index:
##    Left channel: 2.022391
##    Right channel: 2.022391
## Warning in mean.default(c(aei_result$left, aei_result$right)): argument is not
## numeric or logical: returning NA
## Warning in mean.default(c(ndsi_result$left, ndsi_result$right)): argument is
## not numeric or logical: returning NA
## Warning in mean.default(c(adi_result$left, adi_result$right)): argument is not
## numeric or logical: returning NA

## Segment 2 Time (minutes): 1 - Mean Amplitude: 56.6093 - Dominant Frequency: 38.12 Hz - Sonotype: Anthrophony (Human-made noise)

## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Evenness Index: 
##    Left channel: 0.201925
##    Right channel: 0.201925
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
##   Normalized Difference Soundscape Index:
## 
##    Left channel: 0.5590755
##    Right channel: 0.5590755
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Diversity Index: 
##    Left channel: 2.238294
##    Right channel: 2.238294
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Bioacoustic Index:
##    Left channel: 2.205467
##    Right channel: 2.205467
## Warning in mean.default(c(aei_result$left, aei_result$right)): argument is not
## numeric or logical: returning NA
## Warning in mean.default(c(ndsi_result$left, ndsi_result$right)): argument is
## not numeric or logical: returning NA
## Warning in mean.default(c(adi_result$left, adi_result$right)): argument is not
## numeric or logical: returning NA

## Segment 3 Time (minutes): 2 - Mean Amplitude: 62.8684 - Dominant Frequency: 38.12 Hz - Sonotype: Anthrophony (Human-made noise)

## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Evenness Index: 
##    Left channel: 0.067771
##    Right channel: 0.067771
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
##   Normalized Difference Soundscape Index:
## 
##    Left channel: 0.4390927
##    Right channel: 0.4390927
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Diversity Index: 
##    Left channel: 2.295375
##    Right channel: 2.295375
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Bioacoustic Index:
##    Left channel: 2.718499
##    Right channel: 2.718499
## Warning in mean.default(c(aei_result$left, aei_result$right)): argument is not
## numeric or logical: returning NA
## Warning in mean.default(c(ndsi_result$left, ndsi_result$right)): argument is
## not numeric or logical: returning NA
## Warning in mean.default(c(adi_result$left, adi_result$right)): argument is not
## numeric or logical: returning NA

## Segment 4 Time (minutes): 3 - Mean Amplitude: 72.0633 - Dominant Frequency: 38.12 Hz - Sonotype: Anthrophony (Human-made noise)

## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Evenness Index: 
##    Left channel: 0.137998
##    Right channel: 0.137998
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
##   Normalized Difference Soundscape Index:
## 
##    Left channel: 0.452111
##    Right channel: 0.452111
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Diversity Index: 
##    Left channel: 2.272868
##    Right channel: 2.272868
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Bioacoustic Index:
##    Left channel: 2.616688
##    Right channel: 2.616688
## Warning in mean.default(c(aei_result$left, aei_result$right)): argument is not
## numeric or logical: returning NA
## Warning in mean.default(c(ndsi_result$left, ndsi_result$right)): argument is
## not numeric or logical: returning NA
## Warning in mean.default(c(adi_result$left, adi_result$right)): argument is not
## numeric or logical: returning NA

## This took quite a lot of time to display this graphic, you may set 'fastdisp=TRUE' for a faster, but less accurate, display
## Segment 5 Time (minutes): 4 - Mean Amplitude: 90.911 - Dominant Frequency: 38.12 Hz - Sonotype: Anthrophony (Human-made noise)

## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Evenness Index: 
##    Left channel: 0.155639
##    Right channel: 0.155639
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
##   Normalized Difference Soundscape Index:
## 
##    Left channel: 0.6137915
##    Right channel: 0.6137915
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Diversity Index: 
##    Left channel: 2.264599
##    Right channel: 2.264599
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Bioacoustic Index:
##    Left channel: 2.444244
##    Right channel: 2.444244
## Warning in mean.default(c(aei_result$left, aei_result$right)): argument is not
## numeric or logical: returning NA
## Warning in mean.default(c(ndsi_result$left, ndsi_result$right)): argument is
## not numeric or logical: returning NA
## Warning in mean.default(c(adi_result$left, adi_result$right)): argument is not
## numeric or logical: returning NA

## Segment 6 Time (minutes): 5 - Mean Amplitude: 332.1001 - Dominant Frequency: 4577.12 Hz - Sonotype: Biophony (Biological sounds)

## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Evenness Index: 
##    Left channel: 0.02414
##    Right channel: 0.02414
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
##   Normalized Difference Soundscape Index:
## 
##    Left channel: 0.9078794
##    Right channel: 0.9078794
## 
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Acoustic Diversity Index: 
##    Left channel: 2.301468
##    Right channel: 2.301468
## 
##  This is a stereo file. Results will be given for each channel.
## 
##  Calculating index. Please wait... 
## 
##   Bioacoustic Index:
##    Left channel: 3.091766
##    Right channel: 3.091766
## Warning in mean.default(c(aei_result$left, aei_result$right)): argument is not
## numeric or logical: returning NA
## Warning in mean.default(c(ndsi_result$left, ndsi_result$right)): argument is
## not numeric or logical: returning NA
## Warning in mean.default(c(adi_result$left, adi_result$right)): argument is not
## numeric or logical: returning NA

# ---- Summary of Results ---- #
# Calculate the frequency of occurrence for each sound type
anthrophony_frequency <- anthrophony_count / num_segments * 100  # in percentage
biophony_frequency    <- biophony_count / num_segments * 100     # in percentage
geophony_frequency    <- geophony_count / num_segments * 100     # in percentage

# Display the results
cat("\nSummary of Sonotyping and Bioacoustic Index Analysis:\n")
## 
## Summary of Sonotyping and Bioacoustic Index Analysis:
cat("Anthrophony Frequency of Occurrence:", round(anthrophony_frequency, 2), "%\n")
## Anthrophony Frequency of Occurrence: 83.33 %
cat("Biophony Frequency of Occurrence:", round(biophony_frequency, 2), "%\n")
## Biophony Frequency of Occurrence: 16.67 %
cat("Geophony Frequency of Occurrence:", round(geophony_frequency, 2), "%\n")
## Geophony Frequency of Occurrence: 0 %
# ---- Bar Plot ---- #
# Plot the bar chart with margins adjusted for RMarkdown
bar_positions <- barplot(
  c(anthrophony_frequency, biophony_frequency, geophony_frequency), 
  names.arg = c("Anthrophony", "Biophony", "Geophony"), 
  col = c('#FF0000', '#008000', '#0000FF'), 
  ylim = c(0, 100), 
  main = "Distribution of Sound Types", 
  xlab = "Sound Types", 
  ylab = "Frequency (%)", 
  space = 0.8
)

# Add text on the bars to display the percentage
text(
  x = bar_positions, 
  y = c(anthrophony_frequency, biophony_frequency, geophony_frequency) + 5,  
  labels = paste0(round(c(anthrophony_frequency, biophony_frequency, geophony_frequency), 2), "%")
)