CHANGES IN SOUNDGEN VERSION 2.7.1 [22-Oct-2024] NEW FUNCTIONS: * findPeaks(): a bare-bones, very fast function to find peaks in a numeric vector * getHNR(): finds the peak of the autocorrelation function and its amplitude as an estimate of the harmonics-to-noise ratio (HNR) of a time series MINOR: * optimized code, especially soundgen() and analyze() ~1.5x faster * spectrogram(): new arguments "logSpec" for toggling the log-transformation and "specManual" for plotting manually prepared spectrogram-like matrices BUGS FIXED: * plotMS(): logWarpY with correct labels * phasegram(), detectNLP(): ignores silent frames * reverb(): fixed incorrect input checking with changing echoDelay etc. CHANGES IN SOUNDGEN VERSION 2.7.0 [11-Sep-2024] MAJOR: * audSpectrogram(): Butterworth, Chebyshev, and gammatone filters implemented; default ERB bandwidths or specified constant-Q bandwidths; number of filters specified overall or per octave * modulationSpectrum(): STFT or auditory input spectrograms (calling audSpectrogram with the new filter options); 1D or 2D FFT used to produce the modulation spectrum; changed routines and many new options for calculating roughness (eg lognormal weighting functions) * analyze(): revised algorithm for roughness estimation (see above - calls modulationSpectrum) MINOR: * invertSpectrogram(), invertModulSpec(): updated documentation, returns squared error * added a Matlab-like color palette from plot3D::jet.col (colorPalette = 'matlab') * getSurprisal(): arguments "nFilters", "step", "yScale", "dynamicRange", "minFreq", "maxFreq" are deprecated and put into the new argument "audSpec_list" instead BUGS FIXED: * modulationSpectrum(), analyze(): roughness is calculated over both halves of the MPS if 2D FFT is used CHANGES IN SOUNDGEN VERSION 2.6.3 [27-May-2024] NEW FUNCTIONS: * noiseRemoval(): noise removal by spectral subtraction MINOR: * formant_app(): spectral plot cleared each trial and shows the spectrum of synthesized sound, shortcut for synthesize-and-play (P), default number of LPC coefficients shown (grayed out), synthetic sampling rate identical to that of input * transplantFormants(): "blur" as an alternative way to specify the amount of spectral smoothing (and optionally smoothing in the time domain) to apply to the donor sound * apps: new parameter "nColors"" to customize the spectrogram's palette BUGS FIXED: * segment(): correct plotting with method = 'env' * annotation_app(): correct plotting with yScale = 'mel' * spectrogram(): png with reassigned spectrograms saved correctly CHANGES IN SOUNDGEN VERSION 2.6.2 [03-Dec-2023] MINOR: * analyze(): more efficient, flexible, and hopefully accurate autocorrelation-based pitch tracking and HNR calculation * soundgen(): noise amplitude refers to the ratio of RMS amplitudes (intensities) of noise to the periodic component, not a ratio of linear amplitudes, as in earlier versions BUGS FIXED: * spectrogram(yScale = 'mel') doesn't crash * playme() correctly parses file extensions other than "wav" * all shiny apps save non-extensible WAV files with "tuneR::writeWave(extensible=FALSE)", ensuring correct audio playback in Firefox 118-120. Thanks to Uwe Ligges. CHANGES IN SOUNDGEN VERSION 2.6.1 [29-Sep-2023] NEW FUNCTIONS: * findJumps(): automatic detetion of apparent discontinuities (jumps) in a provided frequency contour MINOR: * annotation_app(), pitch_app(), formant_app() return global objects with their output. Thanks to Tecumseh Fitch for suggesting this feature * phasegram(): theiler.window defaults to the first minimum of ACF * osc(), segment(), getRMS(), phasegram(), etc.: when analyzing part of a longer recording with from/to, plot time relative to the original (ie starting from "from" s) * getSurprisal(): method "acf" normalizes surprisal by the length of analyzed sequence (up to "winSurp") BUGS FIXED: * bandpass doesn't crash when trying to plot the spectrum of input containing NAs * audSpectrogram(), getSurprisal(): correct plotting when analyzing parts of long recordings with from...to * segment(): saves audio correctly (normalization bug), doesn't crash when propNoise is automatically set to a single frame * formant_app(), pitch_app(): much faster when working with long audio files (don't call fft to extract envelopes, better workflow, etc.) CHANGES IN SOUNDGEN VERSION 2.6.0 [22-May-2023] NEW FUNCTIONS: * plotMS() for plotting a modulation spectrum produced with modulationSpectrum() * nonlinPred() for predicting new points in a time series based on reconstructed phase space * naiveBayes() for predicting classes of observations in a possibly autocorrelated time series * phasegram() for plotting Poincare sections through phase portraits and extracting nonlinear statistics such as the correlation dimension * detectNLP() for automatically detecting and annotating nonlinear vocal phenomena: subharmonics, sidebands, deterministic chaos, and pitch jumps (EXPERIMENTAL) MAJOR: * formant_app(), annotation_app(), pitch_app(), soundgen_app(): reassigned spectrograms available * spectrogram() and all other functions using "colorTheme": an alternative new argument "col" for specifying the exact colors in the palette for more flexibility compared to "colorTheme" * modulationSpectrum(): a separate logWarpX / logWarpY for the two dimensions, which affect only the plot but not the processed matrix, new argument "normalize" MINOR: * spectrogram(): by default, reassigned spectrograms are plotted without rasterizing * getSurprisal(): faster, extraContour controls the color etc of the surprisal contour * getSurprisal(): alternative method implemented based on nonlinear prediction (method = 'np') * bandpass(): new argument "bw" for Gaussian filters, improved plotting * soundgen(): a new algorithm for clumpering epochs when generating nonlinear phenomena stochastically (also used by naiveBayes) BUGS FIXED: * analyze() and all functions that call .resample(): fixed extra NAs that appeared after sampling rate conversion. Thanks to Virgile Daunay for noticing the problem * interpolMatrix() and upstream functions (eg modulationSpectrum) interpolate when downsampling and preserve colnames in all conditions CHANGES IN SOUNDGEN VERSION 2.5.3 [10-Dec-2022] MINOR * vignettes removed to comply with CRAN's restrictions on package size and complexity * spectrogram(), apps: reassigned spectrogram available (specType = "reassigned", replaces former argument "method") * spectrogram(), apps: a new argument "blur" for blurring or sharpening the spectrogram in frequency and/or time * analyze(): pitchMethods = 'spec' has more robust smoothing defaults so works with eg ultrasound * analyze(): improved calculation of harmHeight * analyze(): new spectral descriptor "entropySh" = normalized Shannon entropy (in addition to "entropy" = Weiner entropy) * formant_app(): button for reverting all formant measurements in an annotation to defaults (as measured) BUGS FIXED: * estimateVTL() diagnostic plot: corrected blue line warning for harmonics (formants that are integer multiple of F1 in closed-open tube model) * analyze(): pitchMethods = 'spec' less likely to crash * formant_app(): more tolerant of incorrectly or incompletely formatted csv input, doesn't crash if analyze doesn't find enough formants, playback doesn't crash when some formants are NA * timeStretch() saves audio correctly CHANGES IN SOUNDGEN VERSION 2.5.2 [14-August-2022] MINOR: * estimateVTL(), schwa(), formant_app(): new argument "tube" to implement either closed-open or open-open tube approximation * estimateVTL(), formant_app(): regression plots sensitive to interceptZero, show multiples of F1 * schwa(), formant_app(): relative formant frequencies expressed in units of formant spacing (dF) instead of semitones, soundgen::hillenbrand dataset updated accordingly * pitchDescriptives() accept the output of analyze('folder_with_many_files')$detailed * getRMS(): new argument "stereo" for working with stereo recordings - thanks to Cameron Anderson * pitchShift(), transplantFormants(), flatSpectrum(), analyze(), resample(), etc.: improved efficiency thanks to calling fast internal versions of some basic functions BUGS FIXED: * pitch_app() and formant_app() work on Mac OS * writeAudio() and upstream functions: audio saved correctly (bug because of incorrect order of arguments) * resample() and all upstream functions like analyze(): correct processing of vectors with initial NA and one unique non-NA value (eg constant-f0 manual pitch contours) * analyze(), pitch_app(): fixed crashing with adaptPrior = TRUE in files with <2 putatively voiced frames * analyze(): fixed occasional crashing when analyzing from... to... (RMS calculation failed due to imperfectly aligned timing) - thanks to Constantijn Kaland * pitch_app(): pitch contour always passes through manual anchors (previously it could occasionally deviate because of interpolation) * annotation_app(): spectrogram brush (selection) cleared on click / next CHANGES IN SOUNDGEN VERSION 2.5.1 [10-February-2022] NEW FUNCTIONS: * notesToHz(): convert musical notation to Hz MINOR: * analyze(): new measures of frequency modulation (fmFreq, fmDep, fmPurity) * analyze(): alternative measure of amplitude modulation based on amplitude envelope (amEnvFreq, amEnvDep, amEnvPurity) * analyze(), modulationSpectrum(): amFreq renamed to amMsFreq and amDep to amMsPurity * analyze(): new measure of RMS amplitude of only non-silent frames "ampl_noSilence"" (same as "ampl"", but NA for frames below silence threshold) * pitchDescriptives(): timeUnit must always be explicitly specified (to avoid mistakes with s/ms) * pitch_app(): oscillogram doubles as voicing bar (click to voice/unvoice a frame) * formant_app(): variable playback pitch BUGS FIXED: * soundgen(): variable vibratoFreq interpolated correctly * formant_app(), pitch_app(), annotation_app(): more precise timing of playback with javascript * segment(): syllables saved without normalizing their amplitude to that of the loudest syllable * all functions that create an html file with clickable plots: correct handling of relative paths * all functions that process multiple inputs (eg analyze, segment, ...): much faster preprocessing of long file cues due to a fixed bug with checking file sizes CHANGES IN SOUNDGEN VERSION 2.5.0 [21-November-2021] NEW FUNCTIONS: * prosody(): exaggerates or flattens the intonation * HzToNotes(): converts Hz to musical notation (notes) * HzToERB(), ERBToHz(): converts from Hz to ERB rate and back (Equivalent Rectangular Bandwidth) MAJOR: * most functions that accept multiple audio files as input (analyze, segment, spectrogram, etc.) take a new argument "cores" for parallel processing * all functions that save audio preserve the original scale or offer normalization options * all functions that produce htmlPlots use relative paths if audio and plots are in the same folder (so can be copied without breaking hyperlinks), aboslute paths otherwise * removed all deprecated functions MINOR: * analyze(): updated cepstral pitch tracking method * analyze(): a new output "CPP" (Cepstral Peak Prominence) measures breathiness * analyze(): a new output "voiced_noSilence" measures the proportion of voiced non-silent frames * fade() accepts files, folders etc as input, new arguments fadeIn_points/fadeOut_points to distinguish from fadeIn/fadeOut (in ms) * spectrogram() and related functions accept yScale = "ERB" CHANGES IN SOUNDGEN VERSION 2.4.0 [16-October-2021] NEW FUNCTIONS: * getDuration(): returns the duration of one or more audio files, with and without leading/trailing silences * annotation_app(): Shiny app for annotating audio (simplified version of formant_app) * timeStretch(): a fast algorithm for time-stretching without preserving pitch MINOR: * bandpass(): new argument "dB" to control the strength of effect (defaults to Inf) * spectrogram() and all related functions: bark and mel frequency scales are warped as before, but labeled in Hz * pitch_app(), formant_app(): platform-independent and updated hotkeys BUGS FIXED: * spectrogram(): osc no longer saved as a separate png file when osc = 'dB' * shiftPitch(): fixed crashing when shifting only formants * formant_app(): deleted sigle annotations per file are removed from the output CHANGES IN SOUNDGEN VERSION 2.3.0 [06-September-2021] NEW FUNCTIONS: * getPitchZc(): fast pitch tracker based on zero-crossing detection * getSurprisal(): tracks the (un)predictability of spectral changes over time as a measure of salience MINOR: * analyze(), pitch_app(): new pitch tracker "zc" * analyze(), pitch_app(): new default sub-method of pitch tracking based on heighest common factor of harmonics as an alternative to the BaNa method (pitchMethods = "spec", pitchSpec = list(method = c("commonFactor", "BaNa")[1]) * analyze(), pitch_app(): new pathfinding algorithm for finding optimal pitch contours (modified Viterbi with random seeds) * spectrogram(), analyze(), etc.: new options for yScale = 'bark' and 'mel' * audSpectrogram(): alternative scales for central frequencies of filters (defaults to bark), time resolution controlled by the new "step" argument * updated and simplified vignette on acoustic analysis BUGS FIXED: * bandpass(): downsampled input is centered before applying a fade-out, then re-normalized to avoid introducing artefacts at the end * segment(): switch from Hilbert to absolute envelope to make sure method = "env" works correctly with complete silence between syllables * analyze(), pitch_app(): pitchMethod = "spec" treats a single detected harmonic as f0 * segment(): correct path in html when saving plots * getSmoothContour() preserves NAs when upsampling if NA_to_zero = FALSE * resample() preserves final NA, extra argument "len" * audSpectrogram(): plots saved correctly * deprecated functions no longer exported CHANGES IN SOUNDGEN VERSION 2.2.0 [07-August-2021] NEW FUNCTIONS: * shiftPitch(): shifts pitch and/or formants + performs time stretch * resample(): changes the sampling rate without introducing artefacts like aliasing * bandpass(): low-pass, high-pass, bandpass, and bandstop filters with FFT MINOR: * analyze(): new outputs "flux" (change in acoustic features) and "epoch" (stable regions based on flux), controlled by a new argument "flux = list(...)" * shiftFormants(): arguments "scaleFactor" renamed to "multFormants" to be consistent with the new function shiftPitch() * getSpectralEnvelope(), generateNoise() and other functions that call getSmoothContour() pass smoothing parameters as "smoothing = list()" instead of separate "interpol = ..., loessSpan = ..." * schwa(): new argument "plot" for visualizing vowel quality in speaker-normalized F1-F2 space BUGS FIXED: * formant_app(): small-scale debugging * analyze(), pitch_app(): more consistent thresholds in medianSmoother (affects the smoothing of feature contours) CHANGES IN SOUNDGEN VERSION 2.1.0 [19-June-2021] NEW FUNCTIONS: * shiftFormants(): raises or lowers formants in a sound without changing its pitch * pitchDescriptives(): extracts common descriptives of time series such as pitch contours: measures of average / range / variability / slope / inflections etc * findInflections(): finds inflections in time series such as pitch contours MINOR * analyze(), modulationSpectrum(): new outputs "amFreq" and "amDep" give the frequency and depth of amplitude modulation * analyze(), pitch_app(): adaptive second-pass priors (new argument "priorAdapt") * analyze(), pitch_app(): prior distribution for pitch candidates is lognormal instead of gamma * switch from Seeing Speech to Hillenbrand 1995 for vowel centroids in formant_app() * getSmoothContour(): downsampling is preceeded by low-pass filtering to avoid aliasing * formant_app(): adjustable playback speed * pitch_app(): support for opening previously saved pitch contours (added as manual anchors) * reportTime() and all loops that use it: max two time levels shown (eg days + hours) BUGS FIXED: * analyze(), pitch_app(): pitch contour plotted as both lines and points to ensure that isolated voiced frames surrounded by NAs are shown * formant_app(): vowel plot, VTL updated in output table, synthetic audio playback with browser, NAs not filled in user annotations * formant_app(), pitch_app(): bug-prone "overlap" setting removed, use "step" instead * pitch_app(): brush is cleared on double click instead of "mouseout" (otherwise it's hard to operate buttons like voice/unvoice) * ssm(): silence has novelty = 0 * analyze(): correctly plots extraContour with negative values (eg HNR, amDep) CHANGES IN SOUNDGEN VERSION 2.0.0 [15-March-2021] GLOBAL (seriously affects back-compatibility): * This version represents an attempt to standardize and better integrate all functions for acoustic analysis in the package. Functions for sound synthesis, notably soundgen(), are not affected by these structural changes and remain fully back-compatible. * Functions analyzeFolder(), spectrogramFolder(), segmentFolder(), modulationSpectrumFolder(), getRMSFolder(), getLoudnessFolder() are deprecated. * Instead, analyze(), spectrogram(), osc(), segment(), modulationSpectrum(), getRMS(), getLoudness(), ssm(), playme(), etc. accept as input either a single sound (numeric vector, Wave object, or filename) or multiple sounds (a list of vectors or Wave objects, multiple filenames like "c(file1, file2)"", or path to folder with audio files). * Functions for acoustic analysis return lists with both detailed results and summaries; for example, analyze() returns a list with two components: "$detailed" (frame-by-frame acoustic measures, one dataframe per file) and "$summary" (summaries based on "summaryFun", one row per file). * Harmonized terminology throughout the package for basic arguments like "from", "to", saving plots ("savePlots") and audio ("saveAudio"), reporting estimated time left ("reportEvery"), etc. MAJOR (affects back-compatibility) * segment(): a new segmentation algorithm based on spectral signal-noise separation, several deprecated and several new arguments, support for long files (>1 h of audio), an option to export detected syllables as separate files, etc. * transplantFormants(): a single argument "freqWindow", support for Wave input, etc. * analyze(): SPL_measured and Pref moved to a new argument "loudness = list(SPL_measured, Pref, spreadSpectrum)" * analyze(): interpolWin, interpolTol, interpolCert moved to a new argument "interpol = list(win, tol, cert)" * compareSounds(): multivariate DTW, different input formats, new arguments, etc. NEW FUNCTIONS: * reverb(): adds reverberation and/or echo to a sound * getEnv(): returns the amplitude envelope of a sound * audSpectrogram(): produces a spectrogram by applying a bank of bandpass filters with Mel-spaced central frequencies (experimental) MINOR: * spectrogram(), analyze(): a new argument "extraContour" for plotting something over the spectrogram * analyze(): spectral slope (specSlope) is returned in dB/kHz * analyze() calls ssm() and returns a novelty contour (a new argument "novelty") * analyze(): updated cepstral pitch tracking, new argument in pitchCep = list(cepPenalty) to regulate how much high-frequency cepstral candidates are mistrusted * analyze() returns strength of subharmonics per frame (output "subRatio" and "subDep") * pitch_app(), formant_app(): user zoom settings preserved when moving between audio files in queue * formant_app(): added a plot of relative formant frequencies to compare with IPA vowels * soundgen(): pitch anchors can contain NAs, eg "pitch = c(150, 200, NA, 110)" - the 3rd quarter will be unvoiced * addFormants(): new argument "zFun" for arbitrary transformations of the spectrogram between STFT and iSTFT (eg for de-noising, spectral warping, etc.) * flatEnv() AKA compressor(): a new argument "compression" regulates the amount of compression, updated plotting * ssm(): a new argument "sparse" for quickly extracting just the novelty contour from long sounds, changes in default settings, input "audiogram" renamed to "melspec", etc. BUGS FIXED: * formant_app(): fixed occasional crashing when scrolling with left/right buttons, other small-scale debugging * soundgen(): fixed a problem with occasionally cutting off sounds with sharp attack, which made them end with audible clicks, and with tempEffects(formDisp = 0) * flatEnv(), transplantEnv(), transplantFormants(): fixed problems with envelope extraction previously caused by incorrect smoothing CHANGES IN SOUNDGEN VERSION 1.8.2 [17-October-2020] NEW FUNCTIONS: * addAM(): adds amplitude modulation to a sound MINOR: * soundgen(): new argument "amType" for sinusoidal or logistic amplitude modulation * soundgen(): "addSilence" can be of length 2 to add different amounts of silence before/after the synthesized sound * pitch_app(): the "voice" button forces selection to be treated as voiced if any candidates are available (before its function was merely to undo "unvoice") * pitch_app(): faster updates when adding/removing anchors (path updated only for current syllable) and when setting a new prior (analyze() is not re-run) * pitch_app(): a single manual pitch anchor is still interpreted as a new syllable * analyze(), pitch_app(): interpolation uses loess instead of medians * pitch_app(), formant_app(): either "step" or "overlap" can be used to control windowing * analyze(), analyzeFolder(): silence threshold is adjusted to max amplitude of input, so very quiet audio can still be treated as voiced BUGS FIXED: * formant_app(): doesn't crash when appending annotations * pitch_app(), formant_app(): fixed incompletely plotted oscillogram CHANGES IN SOUNDGEN VERSION 1.8.1 [18-September-2020] MINOR * soundgen(), getSpectralEnvelope(): a more consisent implementation of zero-pole models, which affects manually specified formant amplitudes. Check your old code! * soundgen(), getSpectralEnvelope(): formantDepStoch is now treated as a multiplication factor instead of dB (0 = no formant, 1 = default amplitude). Check your old code! * soundgen(): updated list of tempEffects * soundgen(): modified smoothing and trend of random walks, eg when generating nonlinear effects stochastically * fade(), crossFade(): new defaults of steepness values, added gaussian shape * estimateVTL(), schwa(), formant_app(): a new argument "interceptZero" for controlling whether the regression line is forced to pass through the origin * analyze(): cutFreq can be a vector of length 2 - eg cutFreq = c(100, 8000) - to produce spectral descriptives from a particular range of frequencies * analyze(): a new argument "voicedSeparate" - if TRUE (default), most descriptors are returned separately for the entire sound and only for voiced frames. This removes ambiguities in earlier versions, where some variables were silently set to NA for unvoiced frames. BUGS FIXED: * soundgen(): correct timing of glottis anchors * soundgen(): invalidArgAction = 'ignore' overrides inbuilt limits of AM parameters * soundgen_app(): correct parsing of long formant lists * pitch_app(): spectrogram plot responds to change in input settings * formant_app(): doesn't crash when changing VTL settings * analyze(), analyzeFolder(): correct plotting with ylim under 1 kHz CHANGES IN SOUNDGEN VERSION 1.8.0 [11-August-2020] NEW FUNCTIONS: * formant_app(): a Shiny web app for manually correcting formant measurements MAJOR: * pitch_app(): a new layout and numerous changes, e.g. caching to speed up the plotting of long files * modulationSpectrum(), modulationSpectrumFolder(): the default is now to measure roughness for multiple frames rather than for the entire sound, thus returning a vector of roughness values over time (controlled by a new argument "amRes") * soundgen(): smoothing(list = ...) regulates interpolation of pitch and amplitude contours. Arguments "interpol", "discontThres", and "jumpThres" are thus deprecated (moved to "smoothing"), and an extra argument "loessSpan" is added to regulate the amount of smoothing * osc() replaces osc_db() MINOR: * estimateVTL(): more advanced plotting, including Cook's distance as a measure of the influence of each formant frequency on apparent VTL * osc(), spectrogram(): fast plotting of long audio files * spectrogram() and all functions that call it (eg analyze, analyzeFolder, getLoudness): argument osc_dB is deprecated, use osc = 'dB' instead * analyze(): new arguments from/to to analyze only a part of sound, NAs not omitted when running custom summaryFun, median smoothing ignores NAs * analyze(), analyzeFolder(), segment(), segmentFolder(), getLoudnessFolder(), getRMSFolder(), modulationSpectrumFolder(): argument "summary" is deprecated and replaced with "summaryFun = NULL" * analyze(), analyzeFolder(): smarter interpolation and smoothing of pitch contours * analyze() and analyzeFolder() now also return roughness and roughnessVoiced * reportTime() and many plots: smarter time labels BUGS FIXED: * morph() accepts vectors like "vibratoFreq = c(0, 3)" in both formulas without crashing * pitch_app() saves all files propertly if multiple folders are opened consecutively without saving the output * spectrogram(): more precise frequency labels, fixed zero padding * filterSoundByMS(): the argument "action = c('remove', 'preserve')" now has an effect * modulationSpectrum(): more precise amplitude modulation labels CHANGES IN SOUNDGEN VERSION 1.7.0 [24-May-2020] MAJOR (affects back-compatibility): * A modified way of creating subharmonics and sidebands in soundgen(): * The old argument "subDep"" now controls the max amplitude of g0 vs f0 harmonics, while a new argument "subWidth" controls the width of sidebands. Check your old code! Setting "subDep = 100, subWidth = old_value_of_subDep" gives the same results as in earlier versions of soundgen * A new argument "subRatio" controls the number of subharmonics, but this behavior can be overridden by the old argument "subFreq" * All pitch-tracker-specific arguments in analyze() are provided as lists: * All arguments starting with "dom", "autocor", "cep", and "spec" are deprecated * Instead, use "pitchDom = list(...old arugments...)", "pitchAutocor = list()", etc. * Some arguments have been removed, notably: * analyze(): instead of "candPlot", use tracker specific lists to control how pitch candidate are plotted, eg "pitchAutocor = list(cex = 3, col = 'red')" * All previously deprecated arguments have been removed in all functions. MAJOR: * analyze(), analyzeFolder(), pitch_app(): a fifth method added for pitch tracking, namely Harmonic Product Spectrum ("hps") * analyze(), analyzeFolder(), pitch_app(): a new argument and output "harmHeight" - an estimate of how high harmonics reach in the spectrum * analyze(), analyzeFolder(), pitch_app(): cutFreq defaults to NULL, and all spectral descriptives are exported only once (either for the entire spectrum or under cutFreq) BUGS FIXED: * soundgen(): proper wiggling of secondary control parameters if temperature > 0 * soundgen(): vibratoFreq and vibratoDep can go beyond preset levels if invalidArgAction = 'ignore' * segment(): very short sounds no longer crash MINOR: * pitch_app(): an option to turn off automatic updating of the optimal pitch contour to speed up the processing of long audio files * pitch_app(): easy-to-access frequency zoom (+/- or icons) * pitch_app(): added hotkeys for most buttons * pitch_app(), analyze(), analyzeFolder(): pitch prior and floor/ceiling plotted on the spectrogram * pitch_app(), analyze(), analyzeFolder(): improved resolution of pitch tracking methods 'spec' and 'dom' through parabolic interpolation of spectral peaks, modified algorithm of 'cep' method * pitch_app(), analyze(), analyzeFolder(): "invalidAction = 'ignore'" overrides defaults, just like in soundgen() * pitch_app(), analyze(), analyzeFolder(): a new argument "formants" for passing a list of arguments to phonTools::findformants * analyzeFolder(), segmentFolder(), modulationSpectrumFolder(), getLoudnessFolder(), getRMSFolder(): 'sound' renamed to 'file' in output * schwa() accepts missing values in formant frequencies * estimateVTL() regresses multiple frequency measurements of the same formant without pre-aggregating * spectrogramFolder(), modulationSpectrumFolder(), analyzeFolder(), segmentFolder(): updated html output CHANGES IN SOUNDGEN VERSION 1.6.2 [06-February-2020] BUGS FIXED: * playme(): '...' removed from documentation (new CRAN requirements) MINOR: * soundgen(): new argument "formantLocking" for temporarily locking a harmonic to a formant (a form of source-filter interaction) * soundgen(): formant drift occurs regardless of whether formants are specified as moving or static CHANGES IN SOUNDGEN VERSION 1.6.1 [22-January-2020] BUGS FIXED: * soundgen(): stochastic formants properly added to breathing noise even without specifying VTL (bug introduced in v1.6.0) * soundgen(), getSpectralEnvelope(): manually specifying formant bandwidth works again (bug introduced in v1.6.0) * soundgen(): tempEffects(pitchDriftDep = 0) no longer crashes because removing pitch drift no longer prevents amplitude drift from working * transplantFormants(): step no longer conflicts with overlap * soundgen_app(): debugged consonant presets MINOR: * soundgen(), generateNoise(): a new argument "rolloffNoiseExp" to control rolloff of the unvoiced component * soundgen(): if "noise" argument is numeric rather than a list, noise component is time-locked to voiced component to ensure precisely the same timing * soundgen(): invalidArgAction="ignore" consistently removes all limits (noise-related pars were reset to defaults in earlier versions) * soundgen(): change in defaults related to nonlinear phenomena: nonlinBalance defaults to 100%, with no jitter, shimmer, or subharmonics * soundgen(): higher default pitchSamplingRate, automatically reset to 10 * max pitch for more reliable control of syllable duration * soundgen(), soundgen_app(): nonlinDep is deprecated * soundgen(): the "interpol" parameter is applied to (almost all) types of smoothing more consistently * getSmoothContour(): a new argument "loessSpan" passed on to loess() for controlling the amount of smoothing of pitch contours, etc CHANGES IN SOUNDGEN VERSION 1.6.0 [09-December-2019] BUGS FIXED: * analyze(): proper plotting of oscillogram for audio files NEW FUNCTIONS: * filterSoundByMS(): manipulates the modulation spectrum of a sound (for ex., removing amplitude and/or frequency modulation above a certain threshold) * filterMS(): filters a modulation spectrum by removing a certain range of amplitude modulation (AM) and frequency modulation (FM) frequencies (called by filterSoundByMS) * invertSpectrogram(): reconstructs audio from a spectrogram by trying to guess the phase * specToMS(), msToSpec(): transform a spectrogram to a modulation spectrum and back again with proper AM/FM or time/frequency labels * transplantEnv(): transplants the amplitude envelope from one sound to another MINOR: * soundgen(): vectorized vocal tract length ("vocalTract" argument) - note that this is similar to the "mouth" argument, but with bandwidths adjusted appropriately and with no limitation on the magnitude of formant frequency shifts * soundgen(): a new argument, "formantCeiling", adjusts the frequency to which formant are calculated - increase for extra precision, particularly for longer-than-human vocal tracts * playme(), soundgen(): the default player on Mac is "afplay" * pitch_app(): choose summary function, reset to defaults, etc. * analyze() and analyzeFolder() accept manually checked pitch contours as produced by pitch_app ("pitchManual" argument) * segment(), segmentFolder(): added oscillogram, improved accuracy of timing * transplantFormants() accepts spectral filter produced by getSpectralEnvelope() as an alternative to donor sound CHANGES IN SOUNDGEN VERSION 1.5.1 [12-October-2019] BUGS FIXED: * pitch_app() runs locally, new layout, multiple new features, integrated with analyze() * analyze() and pitch_app(): improved accuracy of autocorrelation-based pitch tracking at high frequencies NEW FUNCTIONS: * pitchSmoothPraat(): smoothes pitch contours with the same algorithm and "bandwidth" parameter as in Praat for improved compatibility * getPrior(): extract and/or plot the prior used for adjusting the certainty in pitch estimates in analyze() MINOR: * soundgen_app(): improved tips * spectrogram(): option to plot frequencies on a logarithmic scale (yScale = 'log') and specify units (ms/s and Hz/kHz) * spectrogram(): by default pads sounds with silence so as to analyze the edges (padWithSilence = TRUE) * ssm(), spectrogram(), modulationSpectrum(), analyze(): standardized specification of "colorTheme" * analyze(): more flexible "cutFreq" defaults * analyze(): priorPlot and plotSpec deprecated * analyze(): support for plotting both spetrogram & oscillogram (finally!) CHANGES IN SOUNDGEN VERSION 1.5.0 [11-September-2019] NEW FUNCTIONS: * pitch_app(): an interactive Shiny app for manually editing intonation (pitch) contours in a web browser Affect back-compatibility: * analyze(): priorMean is now in Hz instead of semitones (but priorSD is still in semitones), priorPlot looks nicer * analyze(): interpolWin and cepSmooth are now in Hz instead of bins * analyze(): snakeStep, interpolWin, and smooth are set to 0 instead of NULL to turn off these types of pitch postprocessing MINOR: * analyze(): set nFormants = 0 to skip formant analysis, SPL_measured = NULL to skip loudness analysis * analyze(): minor changes / debugging in pathfinding algorithms * playme(): supports playing a selected time region (from/to) and mp3 format * spectrogram(): accepts additional base graphical parameters, such as "yaxp" to control the number of tick marks; a new argument "grid" can be added to add grid lines CHANGES IN SOUNDGEN VERSION 1.4.1 [05-July-2019] NEW FUNCTIONS: * flatSpectrum(): flattens the spectrum of a sound by smoothing in the frequency domain * transplantFormants(): takes the general spectral envelope (formants) of one sound and "transplants" it onto another sound MINOR: * soundgen(), playme(), generateNoise(), fart(), beat(): the previously boolean argument "play" can now also be a string to specify the audio player, eg play = 'aplay' or play = 'vlc' * estimateVTL() offers three methods of estimating vocal tract length from formant frequencies * analyze() and analyzeFolder() can summarize the output with arbitrary functions like "function(x) ..." * analyze(), analyzeFolder(): argument "summaryStats" renamed to "summaryFun" to keep the terminology consistent with getLoudnessFolder() and getRMSFolder() * analyze() and analyzeFolder() also return duration without counting silent frames at the beginning/end of the sound * getSpectralEnvelope(): the output matrix contains frequency and time stamps as row/column names * spectrogram(): new output option ("complex") returns a spectrogram with imaginary parts (phase) * getLoudness() and getLoudnessFolder() support mp3 BUG FIXES: * analyze() no longer crashes with pitchMethods = NULL * getLoudness() and analyze() no longer crash with sampling rates above 44100 (NB: frequencies above 27 barks are automatically discarded when calculating subjective loudness) * morph(): proper handling of attackLen and other small debugging * soundgen(): tempEffects(amplDriftDep) is no longer tied to pitchDriftDep, has a more reasonable default, and doesn't affect audio normalization CHANGES IN SOUNDGEN VERSION 1.4.0 [13-March-2019] MAJOR (affect back-compatibility): * soundgen(), fart(), beat(), generateNoise(): removed all deprecated parameters, notably "pitchAnchors", "noiseAnchors", etc. (now simply "pitch", "noise", etc.) * soundgen(): a new argument ("noiseAmpRef") controls how the relative amplitudes of voiced and unvoiced components are specified by the "noise" setting, with 3 options: "f0" (noise amplitude relative to first partial) produces the same results as in earlier versions of soundgen; both "source" (relative to ulfiltered voiced component) and "filtered" (relative to filtered voiced component - the new default) make noise amplitude less dependent on rolloff. The new default is thus to specify the (peak) amplitude of noise directly in relation to the (peak) amplitude of the voiced component, which is different from older versions - check your code! See vignette on sound synthesis, section 2.12.2, "Noise amplitude". NEW FUNCTIONS: * modulationSpectrum(), modulationSpectrumFolder(): calculates and plots a modulation spectrum showing combined spectro-temporal modulation in one sound or all mp3/wav files in a folder, respectively * getRMS(), getRMSFolder(): calculates root mean square amplitude per frame in one sound or all mp3/wav files in a folder, respectively * normalizeFolder(): normalizes the amplitude of all wav/mp3 files in a folder based on their peak or RMS amplitude or subjective loudness * getLoudnessFolder(): a wrapper around getLoudness() for estimating the loudness of all audio files in a folder * gaussianSmooth2D(): performs Gaussian blur of spectrograms, modulation spectra, or any other numeric matrices. * reportTime(): provides a nicely formatted "estimated time left" in loops plus a summary upon completion MINOR: * spectrogram(), getLoudness(): better temporal alignment of the waveform, spectrogram, and loudness contour * analyze(), analyzeFolder(): more precise time stampts for STFT frames * getLoudness(), analyze(): both functions produce mutually consistent estimates; option to specify the "scale" (maximum possible amplitude) of input waveforms (for audio files, the scale is determined automatically), making loudness estimates dependent on the actual vs. theoretically possible amplitude; all sounds were effectively normalized to max amplitude in earlier versions * soundgen_app(): more intelligent behavior of pitch range * Updated vignettes and demos CHANGES IN SOUNDGEN VERSION 1.3.2 [10-January-2019] MINOR: * soundgen(): new argument "rolloffExact" for controlling the strength of each individual harmonic in source spectrum * soundgen(): changed behavior of the "glottis" parameter (but still experimental) for glottal pulses with a closed phase * soundgen(): interpolation of vectorized amDep, amShape, and amFreq changed from 'spline' to 'approx' * analyze(), analyzeFolder(), segment(), segmentFolder(), spectrogram(), spectrogramFolder(): support for mp3 files in addition to wav * analyze(): pitch candidates based on lowest dominant frequency band ("dom") respect pitchCeiling * Updated demos, vignettes, presets, and documentation of exported functions BUG FIXES: * soundgen(), getRolloff(): rolloffOct argument now really controls the change of rolloff per octave above the fundamental frequency, as intended; note that this affects many presets, which have been updated accordingly * soundgen(): proper control of pitch drift with pitchDriftDep * soundgen(), soundgen_app(): pitchFloor and pitchCeiling fully control pitch range, without needing to override permittedValues with "invalidArgAction = 'ignore'" * analyze(): plotting symbols for pitch candidates in plot legend CHANGES IN SOUNDGEN VERSION 1.3.1 [04-October-2018] NEW FUNCTIONS: * getLoudness(): estimates subjective loudness per frame, in sone MINOR: * analyze(), analyzeFolder(): also return loudness per frame, in sone (new arguments: SPL_measured and Pref) * analyze(), analyzeFolder(): new argument "summaryStats" for specifying how to summarize the output (mean, sd, etc.) * analyze(): a legend can be added to plot (thanks to Jerome Sueur for the idea) * analyze(), analyzeFolder(), segment(), segmentFolder(), spectrogram(): plots are saved as .png instead of .jpg * ssm(): new arguments: "padWith" for dealing with edges and "heights" for controlling relative plot sizes * addFormants(): support for user-specified "spectralEnvelope" (a new argument) * soundgen(): adjusted bandwidth calculation for very low formant frequencies (under 250 Hz) * Updated vignettes and documentation of all exported functions BUG FIXES: * analyzeFolder(): the result is returned with correct class (numeric instead of factor) * flatEnv(): fixed a bug that prevented correct removal of DC offset ("killDC") * generateNoise(): proper interpolation of user-specified "spectralEnvelope" (renamed from "filterNoise") * soundgen_app(): fixed a bug introduced in 1.3.0 that caused the app to crash when switching to a new preset * soundgen_app(): proper plotting of amplGlobal and spectrogram view of formantsNoise CHANGES IN SOUNDGEN VERSION 1.3.0 [31-August-2018] * Back-compatible with soundgen 1.2.X. The main change is abolishing the distinction between anchors (previously pitchAnchors, ampAnchors, etc.) and other vectorized arguments to soundgen (jitterDep, rolloff, etc.) Most vectorized arguments can now be either numeric vectors or dataframes. NEW FUNCTIONS: * osc_dB(): draws an oscillogram (waveform) on a log-tranformed, dB scale. Analogous to the "Waveform (dB)" view in Audacity MAJOR: * soundgen(), generateNoise(), beat(), fart(): the word "Anchor" is dropped from arguments (pitchAnchors, pitchAnchorsGlobal, glottisAnchors, amplAnchors, amplAnchorsGlobal, mouthAnchors, noiseAnchors). Write simply "pitch = ..., ampl = ..." instead of "pitchAnchors = ..., amplAnchors = ..." * soundgen(), generateNoise(), getRolloff(): vectorized arguments can be specified on a natural time scale, in the same format as all former anchors. Ex.: "jitterDep = data.frame(time = c(0, 150, 700), value = c(.2, 2, 0))". Affected arguments: vibratoFreq, vibratoDep, subFreq, subDep, jitterLen, jitterDep, shimmerLen, shimmerDep, rolloff, rolloffOct, rolloffKHz, rolloffParab, rolloffParabHarm, amDep, amFreq, amShape MINOR: * soundgen() and related functions: "throwaway" is deprecated and replaced with "dynamicRange" * spectrogram(), soundgen_app(): added dynamic range, support for plotting the oscillogram on a dB scale, and adjustable size of spectrogram/oscillogram panels * soundgen_app(): fixed a bug introduced in 1.2.1 that crashed the app when changing sylLen. Thanks to Andrew Chang for pointing this out * Updated vignettes on sound synthesis and analysis, a new vignette on reproducing an existing sound with soundgen (webpage only, not published with the package because of large audio files) CHANGES IN SOUNDGEN VERSION 1.2.1 [04-August-2018] NEW FUNCTIONS: * generateNoise(): a simplified version of soundgen() for producing purely voiceless vocalizations such as hissing. Unlike soundgen(), it also accepts a manually specified spectral filter of an arbitrary shape instead of formants for flexible generation of non-biological sounds MINOR: * analyze(): spectral median (medianFreq) and spectral centroid (specCentroid) added as separate outputs; type ?analyze() for details * soundgen(): a new argument shimmerLen for controlling the period of shimmer (cf. jitterLen) * soundgen(): a new argument noiseFlatSpec for more advanced control of the spectrum of the unvoiced component * soundgen(): more intelligent automatic adjustment of pitch ceiling, floor, pitch sampling rate, and sampling rate for extreme pitch values * crossFade(): accepts different shapes of fade-in/out * flatEnv(): minor debugging, default method is now "hil" (see ?seewave::env) * schwa() returns relative formant frequencies in both percentages and semitones * Updated url's in documentation * Updated vignettes on sound synthesis and particularly on sound analysis, including a new section on DIY extraction of custom spectral descriptors CHANGES IN SOUNDGEN VERSION 1.2.0 [04-March-2018] * Back-compatibible with soundgen 1.1.x. Old code will mostly produce the same results, except for moving noise formants and amplitude envelopes in polysyllabic sounds. MAJOR: * soundgen(): the argument "formantsNoise" (formants in the unvoiced component) now affects polysyllabic bouts in the same way as "formants" (formants in the voiced component), i.e. moving formants in "noiseFormants" span multiple syllables (see vignette 2.12) * soundgen(): vectorized parameters sylLen, pauseLen, vibratoFreq, vibratoDep, jitterDep, jitterLen, and shimmerDep. For ex., "nSyl = 15, sylLen = 300:150" produces 15 progressively shorter syllables from 300 ms to 150 ms in length (see vignette 2.5) * soundgen(): a new argument, "nonlinRandomWalk", for specifying the exact timing of each vocal regime (0 = none, 1 = subharmonics, 2 = subharmonics + jitter + shimmer). This is intended for making reproducible examples of sounds with nonlinear effects (see vignette 2.11.5) * soundgen(): "amplAnchorsGlobal" adjusts the amplitude from syllable to syllable in discrete steps, instead of applying a smooth amplitude envelope to the entire bout, and it also applies to the unvoiced component (turbulent noise) * depends on seewave >=2.1.0 because of changes in the seewave package NEW FUNCTIONS: * spectrogramFolder(): extracts and saves spectrograms of all .wav files in a folder, creates an html file with a table of click-to-play spectrograms * getRandomWalk(), getIntegerRandomWalk(): functions for customizing the random walks that divide the sound into segments with different nonlinear regimes; see "nonlinRandomWalk" argument to soundgen() MINOR: * soundgen(): an option to add extra stochastic formants to the unvoiced component, just like for the voiced component. To do so, specify "vocalTract" explicitly (see vignette 2.12.1) * soundgen(): the expected range of amplAnchors is now (throwaway, 0), e.g. (-80, 0), and for amplAnchorsGlobal 0 means no change. Values on the old scale will still work (see vignette 2.8) * soundgen(): a negative pause (overlap) is allowed between bouts (but not between syllables) * soundgen(): attack can be different at the beginning and end of a syllable, e.g. "attackLen = c(50, 100)" * getSmoothContour(): proper handling and plotting of anchors that need downsampling, interpolation forced exactly through the specified anchors with interpol = 'approx' * segmentFolder(), analyzeFolder(): new argument "htmlPlots" to create an html file with a table of click-to-play plots; new default strategy for saving plots (see "savePlots" argument) * analyze(), analyzeFolder(), segment(), segmentFolder(): new argument "res" for proper control of the size and resolution of the output plots CHANGES IN SOUNDGEN VERSION 1.1.2 [23-January-2018] NEW FUNCTIONS: * schwa(): estimates expected formant frequencies for a given vocal tract length, deviation of measured formants from the schwa, or formant frequencies in Hz corresponding to given deviations from the schwa * getEntropy(): calculates Shannon or Weiner entropy of a vector such as power spectrum MINOR: * soundgen(): very rapid or instantaneous attack is now achievable without adjusting windowLength * soundgen(): a new top-level scaling factor formantWidth for simple control of formant bandwidth * soundgen(): noiseAnchors are scaled appropriately as syllable length varies due to jitter, while post-syllabic noiseAnchors are not scaled with syllable duration (i.e. the length of post-syllabic aspiration is held constant as syllable length varies) * soundgen(): interpol affects the smoothing of mouth anchors * analyze(), segment(): streamlined and extended plotting options, fixed a bug in saving plots * segment(): fixed a bug that caused pauseLen_sd to always return NA * spectrogram(): proper handling of silent or very short input * spectrogram(): fixed a bug in denoising routines * morph(): fixed a bug with noiseAnchors that are NULL in one sound and another bug caused by changes in duplicated() that were introduced in the new version of r-devel. Thanks to Kurt Hornik for pointing this out CHANGES IN SOUNDGEN VERSION 1.1.1 [02-December-2017] NEW FUNCTIONS: * addFormants() for adding or removing formants from an existing sound * fade() for adding linear/logarithmic/etc fade-in/out * One-click formant picker tool added to soundgen_app() MINOR: * soundgen(): support for discontinuous contours such as pitch jumps, new arguments to soundgen for controlling interpolation between anchors (new arguments: "interpol", "discontThres", "jumpThres") * soundgen(): all tempEffects default to 1 and act like scaling factors, a new tempEffect added ("specDep") * soundgen(): invalidArgAction propagates through temperature effects, ensuring that "weird" parameter values outside the ranges in permittedValues are processed properly * soundgen(): vectorized rolloffNoise * soundgen(): slightly modified effects of creakyBreathy hyperparameter * soundgen_app(): fixed a bug introduced in soundgen 1.1.0, which caused the app to crash with simplified formant specification * Extended and updated vignette on sound generation * Miscellaneous small-scale debugging CHANGES IN SOUNDGEN VERSION 1.1.0 [19-October-2017] MAJOR * Formant generation is now compatible with standard phonetic models (all-pole or zero-pole models instead of densities of gamma distribution). * Unvoiced component is generated with a flat spectrum up to a certain threshold, followed by linear rolloff. * An alternative method of synthesizing glottal pulses one by one ("soundgen(glottisAnchors = ...)". Good for vocal fry and, potentially, for integrating alternative models of glottal pulses (future work). * Back-compatibility in program syntax is preserved, but presets from version 1.0.0 will sound different. The vignette on sound generation and the preset library are updated accordingly. MINOR * Support for shorthand specification of formants with default amplitudes and bandwidths, e.g. "formants = c(500, 1500, 2500)" or "formants = list(f1 = 800, f2 = c(1500, 2200))". * Support for shorthand specification of all anchors in presets and other input to soundgen_app, e.g. "mouthAnchors = c(0, 0, .3, .5)". The expanded format from soundgen 1.0.0 is also supported. * Vectorized rolloff and amplitude modulation parameters, allowing them to change dynamically within a vocalization (command-line only; currently not implemented in the Shiny app). * Additional components in tempEffects offering more control over stochastic behavior of soundgen() (command-line only). * Separate radiation functions for the lips and the nose (when the mouth is closed). The corresponding soundgen() arguments are "lipRad" (replacing "rolloffLip") and "noseRad". * Minor debugging and extended capabilities in soundgen_app(), e.g. preview of formant filter, better intergration of spectrogram and spectrum output plots, a simple way to remove the voiced component, etc. * Minor debugging elsewhere, notably dB conversion, timing of unvoiced segments in polysyllabic vocalizations in soundgen(), format of the output in analyzeFolder() and segmentFolder(), etc. NEW FUNCTIONS: * flatEnv(): normalizes amplitude envelope dynamically, i.e., keeping loudness constant throughout the sound * estimateVTL(): estimates the length of vocal tract based on formant frequencies * fart(): a simplified version of soundgen() for simple and rapid generation of a particular type of sounds, like raspberries, ripping noises, etc * beat(): generation of percussive noises like drum-like beats, clicks, etc RELEASE OF SOUNDGEN VERSION 1.0.0 [04-September-2017]