From 77780175aab74de1f400ef52dfca11d4071434c7 Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Tue, 17 Sep 2024 10:33:06 -0500 Subject: [PATCH 01/12] improved parameter documentation for prep_static_ggspectro. Fixed bug in segmenting for files with durations or crops that are not exact multiples of xLim --- DESCRIPTION | 4 ++-- R/prep_static_ggspectro.R | 40 +++++++++++++++++++++--------------- R/processSound.R | 11 +++++----- man/prep_static_ggspectro.Rd | 20 +++++++++--------- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 92554b5..33cb885 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: dynaSpec Type: Package Title: Dynamic Spectrogram Visualizations -Version: 1.0.2 +Version: 1.0.3 Date: 2024-02-20 Description: A set of tools to generate dynamic spectrogram visualizations in video format. License: GPL (>= 2) @@ -13,7 +13,7 @@ URL: https://github.com/maRce10/dynaSpec BugReports: https://github.com/maRce10/dynaSpec/issues NeedsCompilation: no Suggests: parallel, imager, fs -RoxygenNote: 7.3.1 +RoxygenNote: 7.3.2 Repository: CRANs Language: en-US Encoding: UTF-8 diff --git a/R/prep_static_ggspectro.R b/R/prep_static_ggspectro.R index 1e6db27..75d3762 100644 --- a/R/prep_static_ggspectro.R +++ b/R/prep_static_ggspectro.R @@ -13,20 +13,20 @@ #' colbins=30,ampThresh=0,bgFlood=FALSE,fontAndAxisCol=NULL,optim=NULL,...) #' #' @param soundFile should work with URLs, full and relative paths; handles .mp3 and .wav -#' @param destFolder needs to be like "figures/spectrograms/" to be relative to working directory; goes to soundFile folder by default or working directory if soundFile is a URL; can specify "wd" to output to the working directory -#' @param outFilename if left out, will use input name in output filename -#' @param savePNG save static spectrograms as PNGs? They will be exported to destFolder +#' @param destFolder path to directory to save output. Needs to be like "figures/spectrograms/" to be relative to working directory. Default=parent folder of soundFile. Specify "wd" to output to the working directory, gotten from [get_wd()] +#' @param outFilename name for output PNG. default=NULL will use input name in output filename. +#' @param savePNG logical; Save static spectrograms as PNGs? They will be exported to destFolder. #' @param colPal color palette; one of "viridis","magma","plasma","inferno","cividis" from the \code{\link[viridis]{viridis}} package OR a 2 value vector (e.g. c("white","black")), defining the start and end of a custom color gradient -#' @param crop subset of recording to include; if crop=NULL, use whole file; if number, interpreted as crop first X.X sec; if c(X1,X2), interpreted as specific time interval in sec -#' @param xLim is the time limit in seconds for all spectrograms; i.e. page width in seconds for multi-page dynamic spectrograms (defaults to WAV file length, unless file duration >5s). To override the 5s limit, put xLim=Inf. -#' @param yLim is the frequency limits (y-axis); default is c(0,10) aka 0-10kHz -#' @param plotLegend include a legend showing amplitude colors? -#' @param onlyPlotSpec do you want to just plot the spec and leave out the legend, axes, and axis labels? -#' @param ampTrans amplitude transform for boosting spectrum contrast; defaults to identity (actual dB values); specify a decimal number for the lambda value of scales::modulus_trans(); 2.5 is a good place to start. (This amplifies your loud values the most, while not increasing background noise much at all) +#' @param crop subset of recording to include; default crop=NULL will use whole file, up to 10 sec; if a number, interpreted as crop first X.X sec; if c(X1,X2), interpreted as trimming out a specific time interval in sec; if crop=FALSE, will not crop at all, even for recordings over 10 sec. +#' @param xLim the time limit (x-axis width) in seconds for all spectrograms; i.e. page width in seconds for multi-page dynamic spectrograms (defaults to WAV file length, unless file duration >5s). To override the 5s limit, put xLim=Inf or specify the desired spectrogram x-axis limit. +#' @param yLim the frequency limits (y-axis); default is c(0,10) aka 0-10kHz +#' @param plotLegend logical; include a legend showing amplitude colors? default=FALSE +#' @param onlyPlotSpec logical; do you want to just plot the spec and leave out the legend, axes, and axis labels? default= TRUE +#' @param ampTrans amplitude transform for boosting spectrum contrast; default=1 (actual dB values); specify a decimal number for the lambda value of scales::modulus_trans(); 2.5 is a good place to start. (This amplifies your loud values the most, while not increasing background noise much at all) #' @param min_dB the minimum decibel (quietest sound) to include in the spec; defaults to -30 (-40 would include quieter sounds; -20 would cut out all but very loud sounds) #' @param filter apply a bandpass filter? Defaults to none (NULL). Expects 'c(0,2)' where sound from 0 to 2kHz would be filtered out #' @param bg background color (defaults to 1st value of chosen palette) -#' @param wl window length for the spectrogram (low values= higher temporal res; high values= higher freq. res). Default 512 is a good tradeoff +#' @param wl window length for the spectrogram (low values= higher temporal res; high values= higher freq. res). Default 512 is a good tradeoff; human speech would look better at 1024 or higher, giving higher frequency resolution. #' @param ovlp how much overlap (as percent) between sliding windows to generate spec? Default 90 looks good, but takes longer #' @param wn window name (slight tweaks on algorithm that affect smoothness of output) see \code{\link[seewave]{spectro}} #' @param specWidth what width (in inches) would you like to make your PNG output be, if saving a static spec? @@ -122,13 +122,21 @@ prep_static_ggspectro <- destFolder = dirname(tools::file_path_as_absolute(soundFile)) } } + destFolder0 <- destFolder + #handle relative destFolder path that ends with /, but doesn't start with / + if(!fs::is_absolute_path(destFolder0)){ + destFolder <- fs::path(fs::path_dir(soundFile),destFolder0) + fs::dir_create(destFolder) + message("Relative destFolder supplied:'",destFolder0,"'. Will save files to soundFile parent dir:\n > ",destFolder) + } + #Put soundFile in working dir if requested - if (destFolder == "wd") { + if (destFolder0 == "wd") { destFolder <- getwd() } - if (!grepl("/$", destFolder)) { - destFolder = paste0(destFolder, "/") + if (!grepl("/$", destFolder0)) { + destFolder = paste0(destFolder0, "/") }#if destFolder missing terminal /, add it if (is.url(soundFile)) { @@ -160,7 +168,7 @@ prep_static_ggspectro <- #Handle file naming for spec if (is.null(outFilename)) { - outFilename = paste0(tools::file_path_sans_ext(basename(soundFile)), ".PNG") + outFilename = paste0(tools::file_path_sans_ext(basename(soundFile)), ".png") } if (!grepl(".png|PNG", outFilename)) { outFilename = paste0(outFilename, ".png") @@ -184,7 +192,7 @@ prep_static_ggspectro <- } #Convert MP3s to WAV - if (tools::file_ext(soundFile) == "mp3") { + if (tools::file_ext(soundFile) %in% c("mp3","MP3")) { print("***Converting mp3 to wav***") wav0 <- tuneR::readMP3(soundFile) } else{ @@ -204,7 +212,7 @@ prep_static_ggspectro <- xLim = xLim, filter = filter, ampThresh) - + browser() if (length(yLim) == 1) { yLim = c(0, yLim) } diff --git a/R/processSound.R b/R/processSound.R index 3f21d17..9508264 100644 --- a/R/processSound.R +++ b/R/processSound.R @@ -98,11 +98,11 @@ processSound <- function(wav0, filter, ampThresh, crop, xLim, ...) { timeRemainder <- (ceiling(wavDur / xLim[2]) * xLim[2] - wavDur) > 0.001#(wavDur%/%xLim[2]-wavDur/xLim[2] #If user wants to have xLim be Infinite (override 5sec max for long files) - if(xLim[2] %in% c(Inf,"Inf")){ + if (xLim[2] %in% c(Inf, "Inf")) { wavDur <- max(length(wav@left), length(wav@right)) / wav@samp.rate xLim[2] <- wavDur - #Else fill out remainders with filler silence - }else if (xLim[2] > wavDur | timeRemainder ) { + #Else fill out remainders with filler silence + } else if (xLim[2] > wavDur | timeRemainder) { if (timeRemainder) { diffT <- ceiling(wavDur / xLim[2]) * xLim[2] - wavDur } else{ @@ -122,7 +122,8 @@ processSound <- function(wav0, filter, ampThresh, crop, xLim, ...) { wavDur <- max(length(wav@left), length(wav@right)) / wav@samp.rate } #Segment wav or make list of 1 if no segmentation - segLens <- seq(0, wavDur, xLim[2]) + #The ceiling code here is to deal with e.g. duration of 29.999 and xLim=10 that would only produce 2 segments + segLens <- seq(0, ceiling(wavDur/xLim[2])*xLim[2], xLim[2]) indx <- 1:(length(segLens) - 1) segWavs <- lapply(indx, function(i) @@ -133,7 +134,7 @@ processSound <- function(wav0, filter, ampThresh, crop, xLim, ...) { output = "Wave", bit = wav0@bit )) - #browser() + return(list( newWav = wav, segWavs = segWavs, diff --git a/man/prep_static_ggspectro.Rd b/man/prep_static_ggspectro.Rd index 810e1f1..8692424 100644 --- a/man/prep_static_ggspectro.Rd +++ b/man/prep_static_ggspectro.Rd @@ -14,33 +14,33 @@ colbins=30,ampThresh=0,bgFlood=FALSE,fontAndAxisCol=NULL,optim=NULL,...) \arguments{ \item{soundFile}{should work with URLs, full and relative paths; handles .mp3 and .wav} -\item{destFolder}{needs to be like "figures/spectrograms/" to be relative to working directory; goes to soundFile folder by default or working directory if soundFile is a URL; can specify "wd" to output to the working directory} +\item{destFolder}{path to directory to save output. Needs to be like "figures/spectrograms/" to be relative to working directory. Default=parent folder of soundFile. Specify "wd" to output to the working directory, gotten from [get_wd()]} -\item{outFilename}{if left out, will use input name in output filename} +\item{outFilename}{name for output PNG. default=NULL will use input name in output filename.} -\item{savePNG}{save static spectrograms as PNGs? They will be exported to destFolder} +\item{savePNG}{logical; Save static spectrograms as PNGs? They will be exported to destFolder.} \item{colPal}{color palette; one of "viridis","magma","plasma","inferno","cividis" from the \code{\link[viridis]{viridis}} package OR a 2 value vector (e.g. c("white","black")), defining the start and end of a custom color gradient} -\item{crop}{subset of recording to include; if crop=NULL, use whole file; if number, interpreted as crop first X.X sec; if c(X1,X2), interpreted as specific time interval in sec} +\item{crop}{subset of recording to include; default crop=NULL will use whole file, up to 10 sec; if a number, interpreted as crop first X.X sec; if c(X1,X2), interpreted as trimming out a specific time interval in sec; if crop=FALSE, will not crop at all, even for recordings over 10 sec.} \item{bg}{background color (defaults to 1st value of chosen palette)} \item{filter}{apply a bandpass filter? Defaults to none (NULL). Expects 'c(0,2)' where sound from 0 to 2kHz would be filtered out} -\item{xLim}{is the time limit in seconds for all spectrograms; i.e. page width in seconds for multi-page dynamic spectrograms (defaults to WAV file length, unless file duration >5s). To override the 5s limit, put xLim=Inf.} +\item{xLim}{the time limit (x-axis width) in seconds for all spectrograms; i.e. page width in seconds for multi-page dynamic spectrograms (defaults to WAV file length, unless file duration >5s). To override the 5s limit, put xLim=Inf or specify the desired spectrogram x-axis limit.} -\item{yLim}{is the frequency limits (y-axis); default is c(0,10) aka 0-10kHz} +\item{yLim}{the frequency limits (y-axis); default is c(0,10) aka 0-10kHz} -\item{plotLegend}{include a legend showing amplitude colors?} +\item{plotLegend}{logical; include a legend showing amplitude colors? default=FALSE} -\item{onlyPlotSpec}{do you want to just plot the spec and leave out the legend, axes, and axis labels?} +\item{onlyPlotSpec}{logical; do you want to just plot the spec and leave out the legend, axes, and axis labels? default= TRUE} -\item{ampTrans}{amplitude transform for boosting spectrum contrast; defaults to identity (actual dB values); specify a decimal number for the lambda value of scales::modulus_trans(); 2.5 is a good place to start. (This amplifies your loud values the most, while not increasing background noise much at all)} +\item{ampTrans}{amplitude transform for boosting spectrum contrast; default=1 (actual dB values); specify a decimal number for the lambda value of scales::modulus_trans(); 2.5 is a good place to start. (This amplifies your loud values the most, while not increasing background noise much at all)} \item{min_dB}{the minimum decibel (quietest sound) to include in the spec; defaults to -30 (-40 would include quieter sounds; -20 would cut out all but very loud sounds)} -\item{wl}{window length for the spectrogram (low values= higher temporal res; high values= higher freq. res). Default 512 is a good tradeoff} +\item{wl}{window length for the spectrogram (low values= higher temporal res; high values= higher freq. res). Default 512 is a good tradeoff; human speech would look better at 1024 or higher, giving higher frequency resolution.} \item{ovlp}{how much overlap (as percent) between sliding windows to generate spec? Default 90 looks good, but takes longer} From 61252babc5aab16a6fdc5a7fcf2fdb04d3f74823 Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Tue, 17 Sep 2024 11:25:13 -0500 Subject: [PATCH 02/12] added title parameter for specs. Updated examples in prep_static_ggspectro --- R/ggSpec.R | 9 ++++++--- R/prep_static_ggspectro.R | 17 +++++++++++------ R/processSound.R | 2 +- man/prep_static_ggspectro.Rd | 15 ++++++++++----- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/R/ggSpec.R b/R/ggSpec.R index 524c61b..d0157cf 100644 --- a/R/ggSpec.R +++ b/R/ggSpec.R @@ -8,6 +8,7 @@ ggSpec <- specWidth, specHeight, destFolder, + title, ovlp, wl, wn, @@ -108,13 +109,15 @@ ggSpec <- level=NULL #just to shut up the check - #Plot that thang - # # + +# Plot that thang --------------------------------------------------------- + Glist[[i]] <- ggplot2::ggplot(df_i, ggplot2::aes(x = time, y = freq, z = amplitude)) + ggplot2::xlim(segLens[i], segLens[i + 1]) + ggplot2::ylim(yLim) + #Labels - ggplot2::labs(x = "Time (s)", y = "Frequency (kHz)", fill = "Amplitude\n(dB)\n") + + ggplot2::labs(x = "Time (s)", y = "Frequency (kHz)", fill = "Amplitude\n(dB)\n", + title=title) + { #Set scale according to viridis or custom color scheme if (isViridis) { diff --git a/R/prep_static_ggspectro.R b/R/prep_static_ggspectro.R index 75d3762..61776b8 100644 --- a/R/prep_static_ggspectro.R +++ b/R/prep_static_ggspectro.R @@ -20,6 +20,7 @@ #' @param crop subset of recording to include; default crop=NULL will use whole file, up to 10 sec; if a number, interpreted as crop first X.X sec; if c(X1,X2), interpreted as trimming out a specific time interval in sec; if crop=FALSE, will not crop at all, even for recordings over 10 sec. #' @param xLim the time limit (x-axis width) in seconds for all spectrograms; i.e. page width in seconds for multi-page dynamic spectrograms (defaults to WAV file length, unless file duration >5s). To override the 5s limit, put xLim=Inf or specify the desired spectrogram x-axis limit. #' @param yLim the frequency limits (y-axis); default is c(0,10) aka 0-10kHz +#' @param title string for title of plots; default=NULL #' @param plotLegend logical; include a legend showing amplitude colors? default=FALSE #' @param onlyPlotSpec logical; do you want to just plot the spec and leave out the legend, axes, and axis labels? default= TRUE #' @param ampTrans amplitude transform for boosting spectrum contrast; default=1 (actual dB values); specify a decimal number for the lambda value of scales::modulus_trans(); 2.5 is a good place to start. (This amplifies your loud values the most, while not increasing background noise much at all) @@ -72,12 +73,15 @@ #' maleBarnSwallow<-prep_static_ggspectro(f[2],destFolder="wd",onlyPlotSpec = FALSE, #' bgFlood=TRUE,ampTrans=2,min_dB=-40) #' -#' #much stronger, now let's combine them (you need the cowplot package) +#' #much stronger, now let's combine them +#' (you need the patchwork package to use the / operator to stack plots) +#' library(patchwork) +#' (femaleBarnSwallow$spec[[1]]+ggplot2::xlim(0,5)) / +#' (maleBarnSwallow$spec[[1]]+ggplot2::xlim(0,5)) + +#' patchwork::plot_annotation(title="Female and Male barn swallow songs", +#' caption="Female song (top) is much shorter, but similar complexity to males. See: MR Wilkins et al. (2020) Animal Behaviour 168") #' -#' # cowplot::plot_grid(femaleBarnSwallow$spec[[1]]+xlim(0,5)+ggtitle("female barn swallow song"), -#' # maleBarnSwallow$spec[[1]]+xlim(0,5)+ggtitle("male barn swallow song"),ncol=1,labels="auto") -#' -#' # ggsave("M&F_barn_swallow_song_specs.jpeg") +#' # ggplot2::ggsave("M&F_barn_swallow_song_specs.jpeg",width=11,height=7) #' #' # see more examples at https://marce10.github.io/dynaSpec/ #' } @@ -98,6 +102,7 @@ prep_static_ggspectro <- filter = NULL, xLim = NULL, yLim = c(0, 10), + title=NULL, plotLegend = FALSE, onlyPlotSpec = TRUE, ampTrans = 1, @@ -212,7 +217,6 @@ prep_static_ggspectro <- xLim = xLim, filter = filter, ampThresh) - browser() if (length(yLim) == 1) { yLim = c(0, yLim) } @@ -227,6 +231,7 @@ prep_static_ggspectro <- specWidth = specWidth, specHeight = specHeight, destFolder = destFolder, + title = title, colPal = colPal, isViridis = isViridis, crop = crop, diff --git a/R/processSound.R b/R/processSound.R index 9508264..6e7cc4f 100644 --- a/R/processSound.R +++ b/R/processSound.R @@ -96,7 +96,7 @@ processSound <- function(wav0, filter, ampThresh, crop, xLim, ...) { #Add silence at the end if (user-supplied) xLim>cropped Duration or xLim doesn't divide into even segments of wave duration timeRemainder <- - (ceiling(wavDur / xLim[2]) * xLim[2] - wavDur) > 0.001#(wavDur%/%xLim[2]-wavDur/xLim[2] + (ceiling(wavDur / xLim[2]) * xLim[2] - wavDur) > 0#(wavDur%/%xLim[2]-wavDur/xLim[2] #If user wants to have xLim be Infinite (override 5sec max for long files) if (xLim[2] %in% c(Inf, "Inf")) { wavDur <- max(length(wav@left), length(wav@right)) / wav@samp.rate diff --git a/man/prep_static_ggspectro.Rd b/man/prep_static_ggspectro.Rd index 8692424..f2afb19 100644 --- a/man/prep_static_ggspectro.Rd +++ b/man/prep_static_ggspectro.Rd @@ -32,6 +32,8 @@ colbins=30,ampThresh=0,bgFlood=FALSE,fontAndAxisCol=NULL,optim=NULL,...) \item{yLim}{the frequency limits (y-axis); default is c(0,10) aka 0-10kHz} +\item{title}{string for title of plots; default=NULL} + \item{plotLegend}{logical; include a legend showing amplitude colors? default=FALSE} \item{onlyPlotSpec}{logical; do you want to just plot the spec and leave out the legend, axes, and axis labels? default= TRUE} @@ -98,12 +100,15 @@ bgFlood=TRUE) maleBarnSwallow<-prep_static_ggspectro(f[2],destFolder="wd",onlyPlotSpec = FALSE, bgFlood=TRUE,ampTrans=2,min_dB=-40) -#much stronger, now let's combine them (you need the cowplot package) - -# cowplot::plot_grid(femaleBarnSwallow$spec[[1]]+xlim(0,5)+ggtitle("female barn swallow song"), -# maleBarnSwallow$spec[[1]]+xlim(0,5)+ggtitle("male barn swallow song"),ncol=1,labels="auto") +#much stronger, now let's combine them +(you need the patchwork package to use the / operator to stack plots) +library(patchwork) +(femaleBarnSwallow$spec[[1]]+ggplot2::xlim(0,5)) / +(maleBarnSwallow$spec[[1]]+ggplot2::xlim(0,5)) + +patchwork::plot_annotation(title="Female and Male barn swallow songs", +caption="Female song (top) is much shorter, but similar complexity to males. See: MR Wilkins et al. (2020) Animal Behaviour 168") -# ggsave("M&F_barn_swallow_song_specs.jpeg") +# ggplot2::ggsave("M&F_barn_swallow_song_specs.jpeg",width=11,height=7) # see more examples at https://marce10.github.io/dynaSpec/ } From e41dfa35f39d6304eedbbb634b751825d2c0a477 Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Tue, 17 Sep 2024 11:47:12 -0500 Subject: [PATCH 03/12] added title parameter support to paged_spectro --- R/paged_spectro.R | 4 ++-- R/prep_static_ggspectro.R | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/R/paged_spectro.R b/R/paged_spectro.R index 2e4e059..82b0696 100644 --- a/R/paged_spectro.R +++ b/R/paged_spectro.R @@ -129,12 +129,12 @@ for(i in 1:length(specParams$segWavs)) cursor<-seq(range_i[1],range_i[2],specParams$xLim[2]/framerate) played<-data.frame(xmin=cursor,xmax=rep(range_i[2],length(cursor)),ymin=rep(specParams$yLim[1],length(cursor)),ymax=rep(specParams$yLim[2], length(cursor))) - #Make ggplot overlay of highlight box on spectrogram vidSegment<-{ ggplot2::ggplot(played)+ggplot2::xlim(range_i)+ggplot2::ylim(specParams$yLim)+ #Labels - ggplot2::labs(x="Time (s)",y="Frequency (kHz)",fill="Amplitude\n(dB)\n")+ + ggplot2::labs(x="Time (s)",y="Frequency (kHz)",fill="Amplitude\n(dB)\n", + title=specParams$title)+ ##Animate() seems to shrink font size a bit mytheme_lg(specParams$bg)+ diff --git a/R/prep_static_ggspectro.R b/R/prep_static_ggspectro.R index 61776b8..9fe64f7 100644 --- a/R/prep_static_ggspectro.R +++ b/R/prep_static_ggspectro.R @@ -270,6 +270,7 @@ prep_static_ggspectro <- isViridis = isViridis, xLim = prepped$xLim, yLim = yLim, + title = title, plotLegend = plotLegend, onlyPlotSpec = onlyPlotSpec, ampTrans = ampTrans, From 04eebee5993c88d63ce80a8ee1fe0f5629b69e19 Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Tue, 17 Sep 2024 11:49:23 -0500 Subject: [PATCH 04/12] changed delTemps to more scrutable delete_temp_files parameter --- R/paged_spectro.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/paged_spectro.R b/R/paged_spectro.R index 82b0696..64a3779 100644 --- a/R/paged_spectro.R +++ b/R/paged_spectro.R @@ -15,7 +15,7 @@ #' @param vidName expects "FileName", .mp4 not necessary; if not supplied, will be named after the file you used in prep_static_ggspectro() #' @param highlightCol default "#4B0C6BFF" (a purple color to match the default viridis 'inferno' palette) #' @param highlightAlpha opacity of the highlight box; default is 0.6 -#' @param cursorCol Color of the leading edge of the highlight box; default "#4B0C6BFF" +#' @param cursorCol Color of the leading edge of the highlight box; default "white" #' @param delTemps Default= TRUE, deletes temporary files (specs & WAV files used to create concatenated video) #' @param framerate by default, set to 30 (currently this is not supported, as animate doesn't honor the setting) #' @return Nothing is returned, though progress and file save locations are output to user. Video should play after rendering. @@ -58,7 +58,7 @@ #' # see more examples at https://marce10.github.io/dynaSpec/ #' } -paged_spectro <-function(specParams,destFolder,vidName,framerate=30,highlightCol="#4B0C6BFF",highlightAlpha=.6,cursorCol="#4B0C6BFF",delTemps=TRUE) +paged_spectro <-function(specParams,destFolder,vidName,framerate=30,highlightCol="#4B0C6BFF",highlightAlpha=.6,cursorCol="white",delTemps=TRUE) { xmin<-ymin <- xmax <- ymax <- NULL #This ^^ suppresses note about "no visible binding for global variable ‘xmax’" From 540b5eec2ce85c3f9c3d7ada05d27f4f3c9d6347 Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Tue, 17 Sep 2024 11:52:37 -0500 Subject: [PATCH 05/12] changed default cursor to white --- R/paged_spectro.R | 8 +++----- man/paged_spectro.Rd | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/R/paged_spectro.R b/R/paged_spectro.R index 64a3779..c84fc62 100644 --- a/R/paged_spectro.R +++ b/R/paged_spectro.R @@ -8,15 +8,13 @@ #' is defined by the xLim parameter in \code{\link{prep_static_ggspectro}}. You can also output temporary segmented files, if desired. #' #' @aliases pagedSpectro pagedSpec -#' @usage paged_spectro(specParams,destFolder,vidName,framerate=30,highlightCol="#4B0C6BFF", -#' highlightAlpha=.6,cursorCol="#4B0C6BFF",delTemps=TRUE) #' @param specParams an object returned from \code{\link{prep_static_ggspectro}} #' @param destFolder destination of output video; this setting overwrites setting from specParams object #' @param vidName expects "FileName", .mp4 not necessary; if not supplied, will be named after the file you used in prep_static_ggspectro() #' @param highlightCol default "#4B0C6BFF" (a purple color to match the default viridis 'inferno' palette) #' @param highlightAlpha opacity of the highlight box; default is 0.6 #' @param cursorCol Color of the leading edge of the highlight box; default "white" -#' @param delTemps Default= TRUE, deletes temporary files (specs & WAV files used to create concatenated video) +#' @param delete_temp_files Default= TRUE, deletes temporary files (specs & WAV files used to create concatenated video) #' @param framerate by default, set to 30 (currently this is not supported, as animate doesn't honor the setting) #' @return Nothing is returned, though progress and file save locations are output to user. Video should play after rendering. #' @seealso \code{\link{prep_static_ggspectro}} @@ -58,7 +56,7 @@ #' # see more examples at https://marce10.github.io/dynaSpec/ #' } -paged_spectro <-function(specParams,destFolder,vidName,framerate=30,highlightCol="#4B0C6BFF",highlightAlpha=.6,cursorCol="white",delTemps=TRUE) +paged_spectro <-function(specParams,destFolder,vidName,framerate=30,highlightCol="#4B0C6BFF",highlightAlpha=.6,cursorCol="white",delete_temp_files=TRUE) { xmin<-ymin <- xmax <- ymax <- NULL #This ^^ suppresses note about "no visible binding for global variable ‘xmax’" @@ -225,7 +223,7 @@ for(i in 1:length(specParams$segWavs)) cat(paste0("file saved @",vidName)) system(paste0('open "',vidName,'"')) - if(delTemps){unlink(tempdir,recursive=TRUE);print(paste0("FYI temporary file directory deleted @ ",tempdir))} + if(delete_temp_files){unlink(tempdir,recursive=TRUE);print(paste0("FYI temporary file directory deleted @ ",tempdir))} }#end else which passed FFMPEG check }#end paged_spectro definition diff --git a/man/paged_spectro.Rd b/man/paged_spectro.Rd index 765c51a..0336476 100644 --- a/man/paged_spectro.Rd +++ b/man/paged_spectro.Rd @@ -6,8 +6,16 @@ \alias{pagedSpec} \title{Make a paged dynamic spectrogram similar to spectral display in Adobe Audition} \usage{ -paged_spectro(specParams,destFolder,vidName,framerate=30,highlightCol="#4B0C6BFF", -highlightAlpha=.6,cursorCol="#4B0C6BFF",delTemps=TRUE) +paged_spectro( + specParams, + destFolder, + vidName, + framerate = 30, + highlightCol = "#4B0C6BFF", + highlightAlpha = 0.6, + cursorCol = "white", + delete_temp_files = TRUE +) } \arguments{ \item{specParams}{an object returned from \code{\link{prep_static_ggspectro}}} @@ -22,9 +30,9 @@ highlightAlpha=.6,cursorCol="#4B0C6BFF",delTemps=TRUE) \item{highlightAlpha}{opacity of the highlight box; default is 0.6} -\item{cursorCol}{Color of the leading edge of the highlight box; default "#4B0C6BFF"} +\item{cursorCol}{Color of the leading edge of the highlight box; default "white"} -\item{delTemps}{Default= TRUE, deletes temporary files (specs & WAV files used to create concatenated video)} +\item{delete_temp_files}{Default= TRUE, deletes temporary files (specs & WAV files used to create concatenated video)} } \value{ Nothing is returned, though progress and file save locations are output to user. Video should play after rendering. From 6efd4939c6caf100801096ee8e748e8264370ea3 Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Tue, 17 Sep 2024 11:56:07 -0500 Subject: [PATCH 06/12] fix partially matched filename param in writeWave --- R/paged_spectro.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/paged_spectro.R b/R/paged_spectro.R index c84fc62..20bcc61 100644 --- a/R/paged_spectro.R +++ b/R/paged_spectro.R @@ -97,7 +97,7 @@ if(!missing(vidName)){ outWAV<-lapply(1:length(specParams$segWavs),function(x) {paste0(tempdir,iName0,"_",x,"_.wav")}) invisible( lapply(1:length(specParams$segWavs), function(x){fn=outWAV[[x]] - tuneR::writeWave(specParams$segWavs[[x]],file=fn) + tuneR::writeWave(specParams$segWavs[[x]],filename=fn) cat(paste0("\nSaved temp wav segment: ",fn))})) } From b99f31e7e9501210a2c034b48f48a5fcf1c50c51 Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Tue, 17 Sep 2024 11:59:16 -0500 Subject: [PATCH 07/12] changed cat/print to message() calls --- R/paged_spectro.R | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/R/paged_spectro.R b/R/paged_spectro.R index 20bcc61..bae7cba 100644 --- a/R/paged_spectro.R +++ b/R/paged_spectro.R @@ -219,11 +219,13 @@ for(i in 1:length(specParams$segWavs)) } - cat("\n\nAll done!\n") - cat(paste0("file saved @",vidName)) + message("\n\nAll done!\nfile saved @",vidName) system(paste0('open "',vidName,'"')) - if(delete_temp_files){unlink(tempdir,recursive=TRUE);print(paste0("FYI temporary file directory deleted @ ",tempdir))} + if(delete_temp_files){ + unlink(tempdir,recursive=TRUE) + message("FYI temporary file directory deleted @ ",tempdir) + } }#end else which passed FFMPEG check }#end paged_spectro definition From b8c631f5265b68309cb421c51ee86c3951c75c03 Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Tue, 17 Sep 2024 21:58:44 -0500 Subject: [PATCH 08/12] added resample parameter to speed up spectrogram generation --- R/ggSpec.R | 12 +++- R/prep_static_ggspectro.R | 6 +- R/processSound.R | 128 ++++++++++++++++++++++++-------------- 3 files changed, 96 insertions(+), 50 deletions(-) diff --git a/R/ggSpec.R b/R/ggSpec.R index d0157cf..38bb614 100644 --- a/R/ggSpec.R +++ b/R/ggSpec.R @@ -3,6 +3,7 @@ ggSpec <- function(wav, soundFile, + resampleRate, segLens, savePNG, specWidth, @@ -34,8 +35,7 @@ ggSpec <- nSegs = length(segLens) - 1 } - - # bg="#ebe834" + # bg="#ebe834" #Font color adapted from https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color if (is.null(fontAndAxisCol)) { @@ -57,6 +57,14 @@ ggSpec <- # text(1,1,"READABLE?",cex=5,col=contrastFont) + + if(!is.null(resampleRate)){ + wav0 <- wav #backup + message("Original wav (",wav0@samp.rate,"samples/sec) data points: ",length(wav0@left)) + wav <- tuneR::downsample(wav,samp.rate=resampleRate) + message("Original wav (",wav@samp.rate,"samples/sec) data points: ",length(wav@left)) + } + #Modified from seewave::ggspectro #---> # norm =FALSE is important for having similar gain across different recordings diff --git a/R/prep_static_ggspectro.R b/R/prep_static_ggspectro.R index 9fe64f7..4f8ffd8 100644 --- a/R/prep_static_ggspectro.R +++ b/R/prep_static_ggspectro.R @@ -23,6 +23,7 @@ #' @param title string for title of plots; default=NULL #' @param plotLegend logical; include a legend showing amplitude colors? default=FALSE #' @param onlyPlotSpec logical; do you want to just plot the spec and leave out the legend, axes, and axis labels? default= TRUE +#' @param resampleRate a number in Hz to downsample audio for spectrogram only. This will simplify audio data and speed up generation of spectrogram. Passed to [tuneR::downsample()]. Put NULL to keep original sample rate for spectrogram. #' @param ampTrans amplitude transform for boosting spectrum contrast; default=1 (actual dB values); specify a decimal number for the lambda value of scales::modulus_trans(); 2.5 is a good place to start. (This amplifies your loud values the most, while not increasing background noise much at all) #' @param min_dB the minimum decibel (quietest sound) to include in the spec; defaults to -30 (-40 would include quieter sounds; -20 would cut out all but very loud sounds) #' @param filter apply a bandpass filter? Defaults to none (NULL). Expects 'c(0,2)' where sound from 0 to 2kHz would be filtered out @@ -106,6 +107,7 @@ prep_static_ggspectro <- plotLegend = FALSE, onlyPlotSpec = TRUE, ampTrans = 1, + resampleRate = NULL, min_dB = -30, wl = 512, ovlp = 90, @@ -216,7 +218,8 @@ prep_static_ggspectro <- crop = crop, xLim = xLim, filter = filter, - ampThresh) + ampThresh=ampThresh) + if (length(yLim) == 1) { yLim = c(0, yLim) } @@ -226,6 +229,7 @@ prep_static_ggspectro <- ggSpec( wav = prepped$newWav, soundFile = soundFile, + resampleRate = resampleRate, segLens = prepped$segLens, savePNG = savePNG, specWidth = specWidth, diff --git a/R/processSound.R b/R/processSound.R index 6e7cc4f..f94aef3 100644 --- a/R/processSound.R +++ b/R/processSound.R @@ -1,8 +1,12 @@ # processSound: filter, crop, and segment wav (internal function) processSound <- function(wav0, filter, ampThresh, crop, xLim, ...) { + + smplRt <- wav0@samp.rate + fileDur0 <- max(length(wav0@left), length(wav0@right)) / smplRt + ##Figure out crop & spectrogram temporal window width #If crop provided as single digit, interpret as first X sec @@ -39,20 +43,43 @@ processSound <- function(wav0, filter, ampThresh, crop, xLim, ...) { #crop is set now for all cases + + # Deal with xLim for segmenting wavs -------------------------------------- + # if xLim not provided, default to smaller of 5sec or wav duration + cropped_dur <- crop[2] - crop[1] + + if (is.null(xLim)) { + xLim <- c(0, min(5, cropped_dur)) + if (xLim[2] == 5) { + message("\n*****\nxLim set to 5 sec by default; define to override\n*****\n") + } + } else{ + #If xLim provided as single digit, interpret as X sec + if (length(xLim) == 1) { + xLim <- c(0, xLim) + } + } + + #If user wants to have xLim be Infinite (override 5sec max for long files) + if (xLim[2] %in% c(Inf, "Inf")) { + xLim[2] <- cropped_dur + } + + #assign new wave file for use going forward #the bit=wav0@bit is REALLY important! Should be standard, but it doesn't work - wav <- - if (crop[2] == fileDur0) { - wav0 - } else{ - seewave::cutw( - wav0, - from = crop[1], - to = crop[2], - output = "Wave", - bit = wav0@bit - ) - } + + if (crop[2] == fileDur0) { + wav <- wav0 + } else{ + wav <- seewave::cutw( + wav0, + from = crop[1], + to = crop[2], + output = "Wave", + bit = wav0@bit + ) + } wavDur <- max(length(wav@left), length(wav@right)) / wav@samp.rate #Apply filters @@ -79,38 +106,34 @@ processSound <- function(wav0, filter, ampThresh, crop, xLim, ...) { - ##Deal with xLim for segmenting wavs - # if xLim not provided, default to smaller of 5sec or wav duration - - if (is.null(xLim)) { - xLim <- c(0, min(5, wavDur)) - if (xLim[2] == 5) { - cat("\n*****\nxLim set to 5 sec by default; define to override\n*****\n") - } - } else{ - #If xLim provided as single digit, interpret as X sec - if (length(xLim) == 1) { - xLim <- c(0, xLim) - } - } + # Make wav file match page xlims ------------------------------------------ + #Given xLim, what is the full length the recording needs to be? + max_page_dur <- ceiling(wavDur / xLim[2]) * xLim[2] #Add silence at the end if (user-supplied) xLim>cropped Duration or xLim doesn't divide into even segments of wave duration + timeRemainder <- - (ceiling(wavDur / xLim[2]) * xLim[2] - wavDur) > 0#(wavDur%/%xLim[2]-wavDur/xLim[2] - #If user wants to have xLim be Infinite (override 5sec max for long files) - if (xLim[2] %in% c(Inf, "Inf")) { - wavDur <- max(length(wav@left), length(wav@right)) / wav@samp.rate - xLim[2] <- wavDur + (max_page_dur - wavDur) + + is_timeRemainder <- timeRemainder > 0 + + + #If file is longer than max_page_dur, trim it + if (wavDur > max_page_dur) { + #trim the wav file again to match a multiple of xLim pages + wav <- seewave::cutw( + wav, + from = crop[1], + to = max_page_dur, + output = "Wave", + bit = wav0@bit + ) + #Else fill out remainders with filler silence - } else if (xLim[2] > wavDur | timeRemainder) { - if (timeRemainder) { - diffT <- ceiling(wavDur / xLim[2]) * xLim[2] - wavDur - } else{ - diffT <- xLim[2] - wavDur - } + } else if (is_timeRemainder) { fillerWAV <- tuneR::silence( - duration = diffT, + duration = timeRemainder, samp.rate = smplRt, xunit = "time", pcm = T, @@ -123,7 +146,8 @@ processSound <- function(wav0, filter, ampThresh, crop, xLim, ...) { } #Segment wav or make list of 1 if no segmentation #The ceiling code here is to deal with e.g. duration of 29.999 and xLim=10 that would only produce 2 segments - segLens <- seq(0, ceiling(wavDur/xLim[2])*xLim[2], xLim[2]) + + segLens <- seq(0, ceiling(wavDur / xLim[2]) * xLim[2], xLim[2]) indx <- 1:(length(segLens) - 1) segWavs <- lapply(indx, function(i) @@ -134,12 +158,22 @@ processSound <- function(wav0, filter, ampThresh, crop, xLim, ...) { output = "Wave", bit = wav0@bit )) - - return(list( - newWav = wav, - segWavs = segWavs, - wavDur = wavDur, - segLens = segLens, - xLim = xLim - )) + n_pages = length(segWavs) + message( + "Segmented original file into ", + n_pages, + " WAV files, each ", + diff(xLim), + " seconds long." + ) + return( + list( + newWav = wav, + n_pages = n_pages, + segWavs = segWavs, + wavDur = wavDur, + segLens = segLens, + xLim = xLim + ) + ) }#End processSound From c6b0f5298fef1f2043b248225c06b2e4f9ce71af Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Tue, 17 Sep 2024 22:25:44 -0500 Subject: [PATCH 09/12] made 15000 the default resample rate for making spectrograms. Goes faster and shows a bit more realistic spectrograms with discernible background --- R/prep_static_ggspectro.R | 4 ++-- man/prep_static_ggspectro.Rd | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/R/prep_static_ggspectro.R b/R/prep_static_ggspectro.R index 4f8ffd8..8e966fe 100644 --- a/R/prep_static_ggspectro.R +++ b/R/prep_static_ggspectro.R @@ -23,7 +23,7 @@ #' @param title string for title of plots; default=NULL #' @param plotLegend logical; include a legend showing amplitude colors? default=FALSE #' @param onlyPlotSpec logical; do you want to just plot the spec and leave out the legend, axes, and axis labels? default= TRUE -#' @param resampleRate a number in Hz to downsample audio for spectrogram only. This will simplify audio data and speed up generation of spectrogram. Passed to [tuneR::downsample()]. Put NULL to keep original sample rate for spectrogram. +#' @param resampleRate a number in Hz to downsample audio for spectrogram only. This will simplify audio data and speed up generation of spectrogram. Passed to [tuneR::downsample()]. Default=15000 shaves off a few seconds without losing much quality. Put NULL to keep original sample rate for spectrogram. Audiofile will not be resampled for MP4. #' @param ampTrans amplitude transform for boosting spectrum contrast; default=1 (actual dB values); specify a decimal number for the lambda value of scales::modulus_trans(); 2.5 is a good place to start. (This amplifies your loud values the most, while not increasing background noise much at all) #' @param min_dB the minimum decibel (quietest sound) to include in the spec; defaults to -30 (-40 would include quieter sounds; -20 would cut out all but very loud sounds) #' @param filter apply a bandpass filter? Defaults to none (NULL). Expects 'c(0,2)' where sound from 0 to 2kHz would be filtered out @@ -107,7 +107,7 @@ prep_static_ggspectro <- plotLegend = FALSE, onlyPlotSpec = TRUE, ampTrans = 1, - resampleRate = NULL, + resampleRate = 15000, min_dB = -30, wl = 512, ovlp = 90, diff --git a/man/prep_static_ggspectro.Rd b/man/prep_static_ggspectro.Rd index f2afb19..f51f130 100644 --- a/man/prep_static_ggspectro.Rd +++ b/man/prep_static_ggspectro.Rd @@ -40,6 +40,8 @@ colbins=30,ampThresh=0,bgFlood=FALSE,fontAndAxisCol=NULL,optim=NULL,...) \item{ampTrans}{amplitude transform for boosting spectrum contrast; default=1 (actual dB values); specify a decimal number for the lambda value of scales::modulus_trans(); 2.5 is a good place to start. (This amplifies your loud values the most, while not increasing background noise much at all)} +\item{resampleRate}{a number in Hz to downsample audio for spectrogram only. This will simplify audio data and speed up generation of spectrogram. Passed to [tuneR::downsample()]. Default=15000 shaves off a few seconds without losing much quality. Put NULL to keep original sample rate for spectrogram. Audiofile will not be resampled for MP4.} + \item{min_dB}{the minimum decibel (quietest sound) to include in the spec; defaults to -30 (-40 would include quieter sounds; -20 would cut out all but very loud sounds)} \item{wl}{window length for the spectrogram (low values= higher temporal res; high values= higher freq. res). Default 512 is a good tradeoff; human speech would look better at 1024 or higher, giving higher frequency resolution.} From 8fb361c8fb660576c688c2851a095361af5ed9b7 Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Fri, 20 Sep 2024 11:01:22 -0500 Subject: [PATCH 10/12] fixed error where WAV durations slightly longer than 30sec making a 40sec video --- R/prep_static_ggspectro.R | 1 + R/processSound.R | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/R/prep_static_ggspectro.R b/R/prep_static_ggspectro.R index 8e966fe..bf64c85 100644 --- a/R/prep_static_ggspectro.R +++ b/R/prep_static_ggspectro.R @@ -269,6 +269,7 @@ prep_static_ggspectro <- soundFile = soundFile, destFolder = destFolder, outFilename = outFilename, + n_pages= length(prepped$segWavs), crop = crop, colPal = colPal, isViridis = isViridis, diff --git a/R/processSound.R b/R/processSound.R index f94aef3..c276dbd 100644 --- a/R/processSound.R +++ b/R/processSound.R @@ -108,9 +108,7 @@ processSound <- function(wav0, filter, ampThresh, crop, xLim, ...) { # Make wav file match page xlims ------------------------------------------ #Given xLim, what is the full length the recording needs to be? - max_page_dur <- ceiling(wavDur / xLim[2]) * xLim[2] - - #Add silence at the end if (user-supplied) xLim>cropped Duration or xLim doesn't divide into even segments of wave duration + max_page_dur <- ceiling( round(wavDur,digits=2) / xLim[2]) * xLim[2] timeRemainder <- (max_page_dur - wavDur) @@ -140,10 +138,12 @@ processSound <- function(wav0, filter, ampThresh, crop, xLim, ...) { bit = wav@bit ) wav <- tuneR::bind(wav, fillerWAV) + } + #pastew results in intermittent problems! Don't use! bind seems much more dependable #seewave::pastew(wave1=fillerWAV,wave2=wav,at="end",output="Wave",join=T,bit=wav0@bit) wavDur <- max(length(wav@left), length(wav@right)) / wav@samp.rate - } + #Segment wav or make list of 1 if no segmentation #The ceiling code here is to deal with e.g. duration of 29.999 and xLim=10 that would only produce 2 segments From 96b3545bd6c0caabb66b208562d61f65c6e759e7 Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Fri, 20 Sep 2024 11:07:15 -0500 Subject: [PATCH 11/12] remove manual usage declaration --- R/prep_static_ggspectro.R | 5 ----- man/prep_static_ggspectro.Rd | 33 +++++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/R/prep_static_ggspectro.R b/R/prep_static_ggspectro.R index bf64c85..b1ae6e5 100644 --- a/R/prep_static_ggspectro.R +++ b/R/prep_static_ggspectro.R @@ -7,11 +7,6 @@ #' #' @aliases prepStaticSpec prepStaticGGspec #' -#' @usage prep_static_ggspectro(soundFile,destFolder,outFilename,savePNG=FALSE,colPal="inferno", -#' crop=NULL,bg=NULL,filter=NULL,xLim=NULL,yLim=c(0,10),plotLegend=FALSE,onlyPlotSpec=TRUE, -#' ampTrans=1,min_dB=-30,wl=512, ovlp=90,wn="blackman",specWidth=9,specHeight=3, -#' colbins=30,ampThresh=0,bgFlood=FALSE,fontAndAxisCol=NULL,optim=NULL,...) -#' #' @param soundFile should work with URLs, full and relative paths; handles .mp3 and .wav #' @param destFolder path to directory to save output. Needs to be like "figures/spectrograms/" to be relative to working directory. Default=parent folder of soundFile. Specify "wd" to output to the working directory, gotten from [get_wd()] #' @param outFilename name for output PNG. default=NULL will use input name in output filename. diff --git a/man/prep_static_ggspectro.Rd b/man/prep_static_ggspectro.Rd index f51f130..ac9f9dd 100644 --- a/man/prep_static_ggspectro.Rd +++ b/man/prep_static_ggspectro.Rd @@ -6,10 +6,35 @@ \alias{prepStaticGGspec} \title{Generate ggplot2-based spectrogram(s), which can be passed to paged_spectro} \usage{ -prep_static_ggspectro(soundFile,destFolder,outFilename,savePNG=FALSE,colPal="inferno", -crop=NULL,bg=NULL,filter=NULL,xLim=NULL,yLim=c(0,10),plotLegend=FALSE,onlyPlotSpec=TRUE, -ampTrans=1,min_dB=-30,wl=512, ovlp=90,wn="blackman",specWidth=9,specHeight=3, -colbins=30,ampThresh=0,bgFlood=FALSE,fontAndAxisCol=NULL,optim=NULL,...) +prep_static_ggspectro( + soundFile, + destFolder, + outFilename = NULL, + savePNG = FALSE, + colPal = "inferno", + crop = NULL, + bg = NULL, + filter = NULL, + xLim = NULL, + yLim = c(0, 10), + title = NULL, + plotLegend = FALSE, + onlyPlotSpec = TRUE, + ampTrans = 1, + resampleRate = 15000, + min_dB = -30, + wl = 512, + ovlp = 90, + wn = "blackman", + specWidth = 9, + specHeight = 3, + colbins = 30, + ampThresh = 0, + bgFlood = FALSE, + fontAndAxisCol = NULL, + optim = NULL, + ... +) } \arguments{ \item{soundFile}{should work with URLs, full and relative paths; handles .mp3 and .wav} From 45678ed4fe3bd1c117d90689b25f448c3e9992d7 Mon Sep 17 00:00:00 2001 From: Matt Wilkins Date: Wed, 25 Sep 2024 15:49:21 -0500 Subject: [PATCH 12/12] version news update --- NEWS.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS.md b/NEWS.md index 397fd5a..f613e37 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,10 @@ +# *dynaSpec 1.0.3* + +* Fix logic for crop and xLim in prep_static_ggspectro() +* Other fixes to have more predictable behavior of exported MP4 videos using "Matt's approach" with paged_spectro() +* Added title parameter to add a title to both static and subsequent paged spectrogram (MP4) +* Added resampleRate parameter to prep_static_ggspectro() for control over resolution of spectrogram (and to speed things up) + # *dynaSpec 1.0.1* * Fix resampling issue when sampling rate of waves != 44.1 kHz