pladdrr Migration Guide
Version 3.0.0 and Beyond
This guide helps existing pladdrr users migrate to the latest API improvements, particularly for heavy users with production code.
Summary of Changes
Breaking Changes (None)
All changes are backward compatible. Existing code continues to work.
However, some functions are now deprecated and will show warnings. Update your code to use the preferred alternatives.
Deprecated Functions
Batch Query Functions
Three functions have been deprecated in favor of more consistent naming:
| Deprecated (batch-ops.R) | Use Instead (batch-queries.R) | Status |
|---|---|---|
pitch_get_values_at_times() |
get_pitch_at_times() |
Will be removed in v3.0.0 |
formant_get_values_at_times() |
get_formants_at_times() |
Will be removed in v3.0.0 |
intensity_get_values_at_times() |
get_intensity_at_times() |
Will be removed in v3.0.0 |
Migration:
# OLD (deprecated, shows warning)
f0_values <- pitch_get_values_at_times(pitch, times)
# NEW (preferred)
f0_values <- get_pitch_at_times(pitch, times)Why? The get_*_at_times() naming is
more consistent with the rest of the API.
PowerCepstrogram API Change
PowerCepstrogram was converted from R6 class to function wrapper for consistency.
What Changed
Old R6 style:
# This NO LONGER works
pcg <- PowerCepstrogram$new(.xptr = ptr)New function wrapper style:
# Use this instead
pcg <- PowerCepstrogram(.xptr = ptr)Migration Steps
If you create PowerCepstrogram objects:
# OLD (R6)
pcg <- PowerCepstrogram$new(.xptr = some_ptr)
# NEW (function wrapper)
pcg <- PowerCepstrogram(.xptr = some_ptr)If you use PowerCepstrogram methods:
No changes needed. All methods work identically:
# These work exactly the same in both versions
cpps <- pcg$get_cpps()
mean_cpp <- pcg$get_mean_cpp()
smooth_pcg <- pcg$smooth(0.001, 0.0005)Pointer Extraction Changes
If you work with external pointers directly, the extraction pattern has been standardized.
Old Pattern (May Fail)
# This relied on R6 private environment
ptr <- obj$.__enclos_env__$private$ptr # Fails with new objectsPerformance Optimization Opportunities
New Parallel Processing API (v2.3.0)
If you process many files, you can now easily use parallel processing:
# OLD: Sequential processing
results <- lapply(files, function(f) {
sound <- Sound(f)
pitch <- sound$to_pitch()
pitch$get_mean(0, 0, "hertz")
})
# NEW: Parallel processing
results <- analyze_files_parallel(files, function(sound) {
pitch <- sound$to_pitch()
pitch$get_mean(0, 0, "hertz")
}, n_cores = 4)Notes: - Wraps your existing per-file analysis code with no other changes - Automatic platform detection (Unix/Windows) - Auto-detects optimal core count
New Direct API Functions (v2.3.0)
Four new direct conversion functions that skip R6 object dispatch:
# OLD: Standard API
spec <- sound$to_spectrum()
spg <- sound$to_spectrogram()
ltas <- sound$to_ltas()
pp <- sound$to_point_process_periodic_cc()
# NEW: Direct API
spec_ptr <- to_spectrum_direct(sound)
spg_ptr <- to_spectrogram_direct(sound)
ltas_ptr <- to_ltas_direct(sound)
pp_ptr <- to_point_process_direct(sound)
# Wrap if needed
spec <- Spectrum(.xptr = spec_ptr)Recommended Code Updates
1. Replace Deprecated Functions
Action Required: Update deprecated function calls to avoid warnings.
# Before
f0_vals <- pitch_get_values_at_times(pitch, times)
f1_vals <- formant_get_values_at_times(formant, times, 1)
int_vals <- intensity_get_values_at_times(intensity, times)
# After
f0_vals <- get_pitch_at_times(pitch, times)
f1_vals <- get_formants_at_times(formant, times, formant_numbers = 1)$F1
int_vals <- get_intensity_at_times(intensity, times)Note: get_formants_at_times() returns a
list with F1, F2, F3, F4:
# Get all formants at once
formants <- get_formants_at_times(formant, times, formant_numbers = 1:4)
f1_vals <- formants$F1
f2_vals <- formants$F2
f3_vals <- formants$F3
f4_vals <- formants$F42. Use Parallel Processing for Large Batches
Opportunity: If you process >50 files, consider parallel processing.
# Before: Sequential
corpus_files <- list.files("corpus/", pattern = "\\.wav$", full.names = TRUE)
results <- lapply(corpus_files, function(file) {
sound <- Sound(file)
# ... analysis code ...
})
# After: Parallel
results <- analyze_files_parallel(corpus_files, function(sound) {
# ... same analysis code ...
}, n_cores = 4)3. Optimize Inner Loops with Direct API
Opportunity: If you have performance-critical loops, use Direct API.
# Before: Standard API in loop
for (i in 1:length(sounds)) {
pitch <- sounds[[i]]$to_pitch()
stats <- list(
mean = pitch$get_mean(0, 0, "hertz"),
sd = pitch$get_standard_deviation(0, 0, "hertz"),
min = pitch$get_minimum(0, 0, "hertz"),
max = pitch$get_maximum(0, 0, "hertz")
)
# ... use stats ...
}
# After: Direct API
for (i in 1:length(sounds)) {
pitch_ptr <- to_pitch_direct(sounds[[i]]$.xptr)
stats <- get_pitch_stats_direct(pitch_ptr) # All stats in one call
# ... use stats ...
}
# Even better: Batch + Direct
pitch_ptrs <- sound_to_pitch_batch(sounds, return_r6 = FALSE)
all_stats <- lapply(pitch_ptrs, get_pitch_stats_direct)Unit Code Standardization
If you work with Praat unit codes directly, use the new
unit_to_code() utility (internal, not exported - call with
pladdrr:::):
# Before: Inconsistent mappings in different files
unit_code <- switch(unit, hertz = 0L, mel = 2L, erb = 3L) # Different files had different codes!
# After: Standardized utility
unit_code <- pladdrr:::unit_to_code("hertz", "pitch") # Returns 0L
unit_code <- pladdrr:::unit_to_code("mel", "pitch") # Returns 2L
unit_code <- pladdrr:::unit_to_code("bark", "formant") # Returns 1LTesting Your Migration
Step 1: Check for Deprecation Warnings
Run your code and look for warnings:
# If you see this warning:
# Warning: pitch_get_values_at_times() is deprecated. Use get_pitch_at_times() instead.
# Update your code accordinglyStep 2: Verify Results
After updating, verify results match:
# Old function (deprecated)
old_result <- pitch_get_values_at_times(pitch, times)
# New function
new_result <- get_pitch_at_times(pitch, times)
# Should be identical
all.equal(old_result, new_result)Common Migration Scenarios
Scenario 1: AVQI Voice Quality Analysis
# Before (v2.2.6)
sound <- Sound(system.file("extdata", "test.wav", package = "pladdrr"))
tg <- TextGrid(system.file("extdata", "test.TextGrid", package = "pladdrr"))
# Extract intervals
n_intervals <- tg$get_number_of_intervals(1)
intervals <- lapply(1:n_intervals, function(i) {
list(
start = tg$get_interval_start_time(1, i),
end = tg$get_interval_end_time(1, i)
)
})
# Extract and analyze, one interval at a time
results <- lapply(intervals, function(int) {
part <- sound$extract_part(int$start, int$end)
formant <- part$to_formant()
# ...
})
# After (v2.3.0)
sound <- Sound(system.file("extdata", "test.wav", package = "pladdrr"))
tg <- TextGrid(system.file("extdata", "test.TextGrid", package = "pladdrr"))
# Batch extraction
intervals <- tg$get_all_intervals(1)
start_times <- intervals$start
end_times <- intervals$end
# Combined extract + analyze in one call
formants <- sound_extract_and_formant(sound, start_times, end_times)Scenario 2: Large Corpus Analysis
# Before (v2.2.6)
files <- list.files("corpus/", pattern = "\\.wav$", full.names = TRUE)
results <- lapply(files, function(f) {
sound <- Sound(f)
pitch <- sound$to_pitch()
list(
file = basename(f),
mean_f0 = pitch$get_mean(0, 0, "hertz"),
sd_f0 = pitch$get_standard_deviation(0, 0, "hertz")
)
})
# After (v2.3.0) - Parallel + Direct API
# analysis_func receives only a Sound object, not its source path, so pair
# the results back up with `files` afterwards (or with names(results)).
results <- analyze_files_parallel(files, function(sound) {
pitch_ptr <- to_pitch_direct(sound$.xptr)
stats <- get_pitch_stats_direct(pitch_ptr)
list(
mean_f0 = stats$mean,
sd_f0 = stats$stdev
)
}, n_cores = 4)
names(results) <- basename(files)Scenario 3: Formant Tracking
# Before (v2.2.6)
sound <- Sound(system.file("extdata", "test.wav", package = "pladdrr"))
formant <- sound$to_formant()
times <- seq(0.1, 0.5, by = 0.001)
# One R->C crossing per time point
f1_values <- vapply(times, function(t) {
formant$get_value_at_time(1, t, "hertz")
}, numeric(1))
# After (v2.3.0) - Vectorized, one R->C crossing for the whole vector
f1_values <- get_formants_at_times(formant, times, formant_numbers = 1)$F1Getting Help
If you encounter issues during migration:
-
Check the documentation:
-
vignette("performance-optimization")- Performance guide -
?get_pitch_at_times- Function help -
BATCH_OPERATIONS_GUIDE.md- Batch operations reference
-
Look for deprecation warnings - They tell you exactly what to change
Test with small datasets first - Verify changes work before running on full corpus
Measure your own workload - Use
system.time()/microbenchmarkto see whether a change helps your pipeline
Timeline
- v2.2.7 (Jan 2026): Bug fixes, no breaking changes
- v2.3.0 (Jan 2026): Deprecation warnings added
- v2.4.0 (TBD): Deprecated functions still work but show louder warnings
- v3.0.0 (TBD): Deprecated functions removed
Recommendation: Update your code now to avoid warnings and prepare for v3.0.0.
Quick Reference
Function Replacements
| Old (Deprecated) | New (Preferred) | Change Required |
|---|---|---|
pitch_get_values_at_times() |
get_pitch_at_times() |
Rename only |
formant_get_values_at_times() |
get_formants_at_times() |
Rename + access $F1, $F2
|
intensity_get_values_at_times() |
get_intensity_at_times() |
Rename only |
PowerCepstrogram$new() |
PowerCepstrogram() |
Remove $new
|
New Features to Adopt
| Feature | Function | What It Does |
|---|---|---|
| Parallel processing | analyze_files_parallel() |
Distributes file-level work across cores |
| Direct API | to_*_direct() |
Skips R6 object dispatch |
| Batch stats | get_pitch_stats_direct() |
Returns all statistics in one call |
| Combined ops | sound_extract_and_pitch() |
Combines extraction and analysis in one call |
Summary
- No breaking changes - existing code works
- Update deprecated functions - simple renames
- Adopt new APIs - parallel processing and Direct API skip R6 dispatch overhead
-
Read new docs - see
vignette("performance-optimization")