Changelog
Source:NEWS.md
pladdrr 5.0.5
Code quality
-
goodpracticestyle pass:- Wrapped all >80-character code lines in hand-written
R/files (auto-generatedRcppExports.Runchanged); long string literals split into concatenated fragments with identical values. - Split five over-long functions into helpers (
autolayer.TextGrid,analyze_files_parallel,plot.Matrix,plot.PowerCepstrum,two_pass_adaptive_pitch); thegoodpracticefunction-length check now passes. - Consolidated cross-file
@paramblocks: dots docs kept in a single canonical file, constructornamedocs inherited from a newpladdrr_shared_method_nameanchor. - Removed the unused
._bust_cachePointProcess method; the 113 remainingcomplexity_unused_internalfindings are documented false positives (S3$dispatch, S3 generics, roxygen anchors, Rcpp export surface) - seedev/goodpractice-dead-code-triage.md. - Test coverage raised 89.3% to 91.8%: added coverage-gap tests for input validation, empty-data warnings, dispatch fallback paths, and
pladdrr.data_lossmodes; not-testable guards (missing-ggplot2 stops, doc anchors, load-time branches) marked# nocov. - NEWS spelling fixes and
inst/WORDLISTadditions (dev,uncommented).
- Wrapped all >80-character code lines in hand-written
pladdrr 5.0.5
CRAN compliance
- Removed the last two
R CMD checkwarnings:- The compiled-code warning (
stderr/stdout/_exitsymbols in the vendored Praat objects):melder_console.cppnow routes console output through the R API (Rprintf/REprintf), gated to the main thread (R’s console API is unsafe off-main-thread, andMelder_casualcan fire inside threaded DSP frame loops; worker-thread messages are dropped). Allexit()call sites in Praat’s CLI paths throw aMelderErrorunderPRAAT_LIBinstead of terminating the process. - The non-portable
PKG_CXXFLAGSflag-ffp-contract=offwas replaced by a source-level#pragma STDC FP_CONTRACT OFFin the vendoredmelder.h(included by every DSP translation unit) — the same bit-exactness guarantee with no compiler flags.
- The compiled-code warning (
- Removed the R-devel “package has both
src/Makevars.inandsrc/Makevars” NOTE: thecleanupscript now deletes the configure-generatedsrc/Makevarsfrom the build copy. - Expanded
inst/WORDLISTand fixed a typo; the documentation now passesspelling::spell_check_package(). - Modernized the test suite (~440 assertion conversions:
expect_gt/gte/ lt/lte,expect_length,expect_named,expect_type,expect_s3_class,expect_identicalfor exact integer comparisons,expect_false,fixed = TRUEon literal patterns,anyNA). - Parallel batch functions (
analyze_files_parallel(),process_sounds_parallel()) now cap their automatic core count at 2 underR CMD check(honoring_R_CHECK_LIMIT_CORES_), so the default-n_corestests pass CRAN’s process-spawn limit while dev/CI still uses all cores. - Fixed a broken example in the
textgrid_create()docs (an uncommented continuation line) that madeR CMD checkfail to run any examples. - Documented the
...argument onplot.*,as.data.frame.*,print.*, andsummary.*methods, and synced the sharedpladdrr_shared_*parameter docs with their usage — clears the “Rd sections” warning.
pladdrr 5.0.4
Bug fixes
The Praat interpreter entry points (
praat_run_script(),The Praat interpreter entry points (
praat_run_script(),praat_eval_numeric(),praat_eval_string(),praat_eval_vector(),praat_eval_matrix(),praat_eval_string_array(), andPraatInterpreter$run()/$eval()/$set_variable()) now rejectNULL, empty, non-scalar, or non-character inputs with a clear R error instead of an opaque C++ failure.Sound$to_textgrid_silences()acceptedmin_silent_duration/min_sounding_durationbut silently ignored them (aTODO). It now merges short silent and sounding intervals via the sameIntervalTier_cutIntervals_minimumDuration+IntervalTier_combineIntervalsOnLabelMatchpasses the intensity-based path already used.PointProcess(tmin, tmax)now creates an empty PointProcess (previously it only accepted an internal pointer and stopped otherwise). Backed by a newpointprocess_module$create_empty()C++ factory wrapping Praat’sPointProcess_create(). Enables empty-object batch operations.praat_eval_string_array("empty$# (n)")segfaulted the R session. The vendored Praatdo_empty_STRVECbuilt its result withautoSTRVEC result { n }, which zero-initialises the vector and so leaves every element a null pointer instead of a valid empty C string; the R wrapper’sMelder_peek32to8()then dereferenced null. It now returnsnempty strings. Also un-skippedformant$save()(its earlier segfault was a symptom of the fixedto_formant_burg()crash).Sound$get_optimal_formant_ceiling()andSound$to_formant_optimal()crashed the R session (SIGTRAP / “irrecoverable exception”) for every input. Two stacked causes were fixed. (1) The vendored PraatSound_to_Formant_commonread the null outputsoundinstead of the localresampledwhen setting up the short-term analysis and Formant/LPC objects, crashing every Burg/robust formant-analysis entry point (to_formant_burg()was also broken). (2) The pladdrrFormant_extractPartstub wrotenewFrame->formant[]without allocating it —Formant_createzeroes frames so the array is null — so the interval path aborted on the first dereference.to_formant_burg(),to_formant_optimal(), andget_optimal_formant_ceiling()now all work.autoplot.Spectrogram(),autolayer.Spectrogram(), andplot.Spectrogram()scrambled the frequency axis for any non-square spectrogram matrix (aexpand.grid()/as.vector()row/column-major mismatch — a 220 Hz tone rendered with its peak at 2201 Hz), and plotted raw linear power directly as if already in dB, making thedynamic_rangeclipping parameter a silent no-op.plot_powercepstrogram()had the same two defects (time/quefrency-axis transposition and missing power-to-dB conversion), plus a hardcodedmax_time <- 5.0placeholder in place of the cepstrogram’s real duration.plot_cpp_timeseries()used the same hardcoded-duration placeholder, and atryCatch()scoping bug (cpp_values[i] <- NAinstead of<<-inside the error handler) meant a failed per-time-point CPP query silently became0instead of being dropped asNA.-
plot_powercepstrum()used a hardcodedmax_quefrency <- 0.05placeholder instead of the cepstrum’s real quefrency range, and plotted itspower_dBcolumn (misleadingly named — the values are raw linear power, not dB) without converting, putting the line trace and its own peak-prominence marker on incompatible scales.None of these 5 functions had any test coverage before this release; 12 new regression tests were added (
test-spectrogram-plot-regression.R,test-cepstrum-plots-regression.R). Follow-up fixes closing the remaining
power_dB-mislabel call sites:autoplot.PowerCepstrum()/autolayer.PowerCepstrum()andplot.PowerCepstrum()still plotted the C++as_data_frame()’s misleadingly-namedpower_dBcolumn (raw linear power) directly under a “Power (dB)” axis, and selected their cepstral-peak marker withwhich.max()on linear power. Both now convert to a real dBpower_dbcolumn before plotting (5 new tests intest-powercepstrum-db-regression.R).plot_powercepstrogram(show_cpp_contour = TRUE)drew its CPP-contour overlay as a flat line at a hardcodedquefrency = 0.01placeholder; it now overlays the real per-time-frame cepstral-peak quefrency, computed as the argmax of each frame’s own raster row.plot.Spectrogram()’spreemphasisargument (default 50) was accepted but never referenced; removed as dead — pre-emphasis belongs in the DSP layer, not a plot method.plot_cpp_timeseries()no longer emits a cosmetic “Mean CPP: NaN dB (SD: NA)” subtitle when every sample fails; it now shows “No samples”.PowerCepstrum$as_data_frame()(the C++RPowerCepstrummodule) returned a column misleadingly namedpower_dBthat actually held raw linear power; renamed to the honestpower. This is a breaking change for any caller that read$as_data_frame()$power_dBdirectly; the affected plotting functions now readpowerand convert topower_db.as.data.frame.LPC()indexed the coefficient matrix as if it were a flat list (coeffs[[i]]), so it emitted one row per frame with a single mislabeled coefficient and silently dropped the othermaxnCoefficients - 1coefficients of every frame. It now reads each frame’s coefficient column (coeffs[, i]), yielding one row per (frame, coefficient) as documented.AmplitudeTier$to_intensity_tier()andAmplitudeTier$save()called non-existent internal wrappers (.amplitudetier_to_intensitytier()/.amplitudetier_save()), so both errored with “could not find function”. They now dispatch through the Rcpp module (to_intensity_tier_ptr()/save()). Sixget_shimmer_*()AmplitudeTier methods were also removed: shimmer is a PointProcess metric (already present there), and these AmplitudeTier copies had no C++ implementation.plot_spectrogram_pitch()’sfreq_maxargument (documented “Maximum frequency to display”) was silently ignored — it was passed toplot.Spectrogram(), which has no such parameter. It now maps toplot.Spectrogram()’sto_freq, so the frequency cap is honored.plot_sound_pitch()’spitch_floor/pitch_ceilingarguments were dead — passed toplot.Pitch(), which ignores them. Removed.Deprecated
get_intensity_at_time()’sinterpolateargument andcreate_sound()’sstart_timeargument were silently ignored; both now forward to the underlying R6 methods.plot.Pitch()/autoplot.Pitch()’sshow_voicingargument never colored by voicing strength: it looked for avoicing_strengthcolumn, butPitch$as_data_frame()names itstrength(and only includes it withinclude_strength = TRUE). Both now pull the strength column and color by it.autolayer.PointProcess()’symin/ymaxarguments were ignored (it usedgeom_vline),autoplot.PCA()/autoplot.Discriminant()’sgarnishargument was dead, and.formant_colors()’smax_formantwas redundant. All now honor their documented behavior.
pladdrr 5.0.1
New features
- Added
autoplot()andautolayer()S3 methods for 27 previously unsupported Praat object classes: AmplitudeTier, DurationTier, IntensityTier, PitchTier, FormantTier, FormantGrid, FormantPath, Excitation, ComplexSpectrogram, Cepstrum, Cochleagram, PowerCepstrogram, MFCC, LFCC, BarkSpectrogram, MelSpectrogram, Matrix, PCA, Discriminant, FormantModeler, Electroglottogram, LongSound, DTW, Polygon, VocalTract, LPC, KlattGrid. - Added
as.data.frame()S3 methods for 15 classes that lacked them.
Bug fixes
-
process_sounds_parallel()shipped already-loadedSoundobjects directly to Windows PSOCK workers; their external pointer to the underlying C++ object cannot survive that process boundary, causing spurious errors on Windows withn_cores > 1. Sounds are now serialized to raw sample data and reconstructed inside each worker. - Fixed
FormantGrid$as_data_frame()missing requiredtime_stepargument. -
autoplot.KlattGrid()/as.data.frame.KlattGrid()passed a formant-type name as a string where the underlying accessor required an integer code, producing empty plots or silently wrong data for every formant type. Fixed to map the name to its integer code before dispatch; also corrected the sharedformant_typedocumentation, which claimed"all"was an accepted value forautolayer.KlattGrid()when onlyautoplot.KlattGrid()actually supports it. -
as.data.frame.Cochleagram()always errored. -
as.data.frame.LPC()always errored, due to a typo’dpower_dBcolumn name that did not exist on the object. -
autolayer.DTW()plotted the wrong columns and crashed on someNULL-valued paths. -
autoplot/autolayer/as.data.frameforMatrix,BarkSpectrogram, andMelSpectrogramplotted raw row/column bin indices instead of the real time/frequency axis values. -
autoplot.Cepstrum()defaulted to a power-cepstrum dB view; Praat’s actual default is a raw signed quefrency-domain view. Fixed the default and added apowerparameter to select the dB view explicitly. -
autoplot.ComplexSpectrogram()andautolayer.ComplexSpectrogram()both mislabeled linear amplitude values as dB and ignoreddynamic_range. -
as.data.frame.VocalTract(),autoplot.VocalTract(), andautolayer.VocalTract()all hardcoded section spacing (dx) instead of reading it from the object, giving wrong x-axis values whenever spacing was non-default. -
autoplot.FormantTier()/autolayer.FormantTier()defaulted to an interpolated line view; Praat’s actual default view is speckle (points). -
autoplot.FormantPath()andautoplot.FormantModeler()always produced empty plots — the former from a column-name mismatch, the latter from a wide/long data-frame format mismatch. -
as.data.frame.PowerCepstrogram()called a nonexistent$as_data_frame()method and always crashed; fixed to route through$to_matrix(). -
Sound$extract_electroglottogram()was never registered in the R6 method table, despite its underlying C++ export existing and being registered; every call crashed with “attempt to apply non-function”.
pladdrr 5.0.0
Bug fixes
-
intensity_tier_to_amplitude_tier()andamplitude_tier_from_point_process()read$.pointeroffIntensityTier/PointProcess/Soundobjects, but those classes store their external pointer under$.xptr($.pointeris only an alias onAmplitudeTier). The mismatch resolved toNULLand failed deep in the C++ layer withR_ExternalPtrAddr: argument of type NILSXP is not an external pointer. Fixed both call sites to use$.xptr. -
matrix_read()called an internal.matrix_read()binding that did not exist, so every call failed withcould not find function ".matrix_read"(silently masked by anR CMD checkNOTE-suppression entry inutils::globalVariables(), not by a real implementation). Added the missing C++ binding (mirroring the existingPitchTier/IntensityTier/TextGridread pattern) and wired upMatrix$save()to the C++ save method that already existed but was never exposed to R. -
get_max_pitch()/get_min_pitch()(deprecated legacy wrappers) calledPitch$get_maximum()/get_minimum()with a staleinterpolation =argument; the current method signature takesinterpolate =(logical). Every call failed withunused argument (interpolation = "none"). Fixed to passinterpolate = FALSE. -
get_formant_at_time()/get_mean_formant()’s documentation pointed users toextract_formants()as the source of a compatible object, butextract_formants()no longer produces one when given an R6Soundobject (it delegates tosound$to_formant_burg(), returning an R6Formantobject instead) — a stale cross-reference left over from the package’s S3-to-R6 migration. No behavior changed; documentation now describes the actual expected input andextract_formants()’s actual return value on both its code paths.
Documentation
- Removed performance claims (absolute and relative) from
DESCRIPTIONandREADME.mdper CRAN submission review, including comparisons to other tools such as Parselmouth. Historical changelog entries with benchmark data have been moved toNEWS-archive.md, which is not shipped in the package tarball. - Reconciled the Praat module count reported in
DESCRIPTION(37 to 38) to match the actual number of exposed Rcpp modules.
Memory
- Reworked spectral moments batch calculations to compute centre of gravity, standard deviation, skewness, and kurtosis directly from the spectrogram data, removing intermediate per-frame allocations. Results are numerically identical to previous versions.
- Pre-allocated the output vectors used to build formant and pitch data frames, and made pitch data frame construction skip allocating the strength/intensity columns when they are not requested.