library(dplyr) library(ggplot2) library(reshape2) # Note: this sript assumes that you have saved a Praat Spectrogram # using the function "Save to text file. " # It will not work if you save to a short text file, # and will not work if you save to a binary file. # you should first set the working directory to wherever the spectrogram is saved. # change this next line to map to the appropriate directory on your computer dir_spectrogram_files <- "C:\\Users\\Matt\\Documents\\Website\\tools" setwd(dir_spectrogram_files) # Here's the main function: convert_spectrogram_to_df <- function(spect_name){ spect <- readLines(spect_name) %>% colsplit(., pattern = " = ", names = c("coordinate","Value")) spect <- spect[4:nrow(spect),] %>% mutate(Value = as.numeric(Value)) Freq_floor <- spect[spect$coordinate=="ymin", "Value"] Freq_max <- spect[spect$coordinate=="ymax", "Value"] Time_start <- spect[spect$coordinate=="xmin", "Value"] Time_end <- spect[spect$coordinate=="xmax", "Value"] num_times <- spect[spect$coordinate=="nx", "Value"] time_bin_size <- spect[spect$coordinate=="dx", "Value"] num_freq_bins <- spect[spect$coordinate=="ny", "Value"] freq_bin_size <- spect[spect$coordinate=="dy", "Value"] spect_vals <- spect$coordinate[12:length(spect$coordinate)] %>% data.frame(meas = .) %>% mutate(meas = as.character(meas)) %>% mutate(is.Freqstep = ifelse(grepl(x = meas, pattern=":"), 1, 0)) %>% mutate(Freqstep = cumsum(is.Freqstep)) %>% mutate(Timestep = {meas %>% colsplit(., pattern = "\\]|\\]", names = c("junk","Timebin")) %>% mutate(Timebin = gsub(replacement = "", x = Timebin, pattern="\\[|\\]")) %>% mutate(Timebin = as.numeric(Timebin)) %>% `[[`(., "Timebin")}) %>% mutate(Time = (Timestep - 1) * time_bin_size) %>% mutate(Frequency = (Freqstep - 1) * freq_bin_size) reference_SP <- 0.00002 df <- cbind(spect[12:nrow(spect),], spect_vals) %>% mutate(filename = spect_name) %>% select(filename, Timestep, Freqstep, Time, Frequency, Pressure = Value) %>% # mutate(Pressure = round(Pressure, 5)) %>% mutate(Level = 20 * log10(Pressure / reference_SP)) df <- df[!is.na(df$Time),] rm(spect, spect_vals) return(df) } #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# # Here's how to constrain dynamic range # (the way you'd do in Praat) constrain_dynamic_range <- function(spectrogram_object, dynamic_range = 60){ # first make a copy of the Level variable, # so that you don't lose information spectrogram_object$Level_dr <- spectrogram_object$Level # remove anything that's more than [DR] below the max level spectrogram_object$Level_dr[spectrogram_object$Level_dr < (max(spectrogram_object$Level_dr, na.rm=TRUE) - dynamic_range)] <- NA return(spectrogram_object) } #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# # this is an example of using this single function to read in # lots of spectrogram files into a single big data frame: # you should first set the working directory to wherever the spectrogram is saved. setwd(dir_spectrogram_files) # make the list of spectrograms spect_files <- list.files(pattern = "Spectrogram") # apply the function to the list of spectrogram files, # combine together big_spect_df <- spect_files %>% lapply(., convert_spectrogram_to_df) %>% bind_rows() # constrain the dynamic range big_spect_df <- big_spect_df %>% constrain_dynamic_range() # verify dynamic range adjustment with plot hist(big_spect_df$Level) hist(big_spect_df$Level_dr) #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# # Here's an example of how to plot it setwd(dir_spectrogram_files) my_spect_file <- "Time.Spectrogram" single_spect_df <- my_spect_file %>% convert_spectrogram_to_df() %>% constrain_dynamic_range(dynamic_range = 70) px_spectrogram <- ggplot(single_spect_df)+ aes(x = Time, y=Frequency, fill=Level_dr)+ geom_tile()+ scale_fill_gradient(high="black", low="white", na.value = "white")+ coord_cartesian(ylim=c(0, 6200))+ xlab("Time (s)")+ scale_y_continuous("Frequency (Hz)", breaks=seq(0, 6000, 2000))+ theme_bw()+ theme(legend.position="none", panel.grid.major = element_blank(), panel.grid.minor = element_blank()) px_spectrogram #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%# # # save it! # ggsave(px_spectrogram, filename = "my_spectrogram.png", # height = 3.2, width = 5, dpi = 150)