# NOT RUN {
sound = soundgen(sylLen = 300, pitch = c(500, 400, 600),
noise = list(time = c(0, 300), value = c(-40, 0)),
temperature = 0.001,
addSilence = 50) # NB: always have some silence before and after!!!
# playme(sound, 16000)
a = analyze(sound, samplingRate = 16000, plot = TRUE)
str(a$detailed) # frame-by-frame
a$summary # summary per sound
# }
# NOT RUN {
# For maximum processing speed (just basic spectral descriptives):
a = analyze(sound, samplingRate = 16000,
plot = FALSE, # no plotting
pitchMethods = NULL, # no pitch tracking
loudness = NULL, # no loudness analysis
novelty = NULL, # no novelty analysis
roughness = NULL, # no roughness analysis
nFormants = 0 # no formant analysis
)
sound1 = soundgen(sylLen = 900, pitch = list(
time = c(0, .3, .9, 1), value = c(300, 900, 400, 2300)),
noise = list(time = c(0, 300), value = c(-40, 0)),
temperature = 0.001, samplingRate = 44100, pitchSamplingRate = 44100)
# improve the quality of postprocessing:
a1 = analyze(sound1, samplingRate = 44100, priorSD = 24,
plot = TRUE, pathfinding = 'slow', ylim = c(0, 5))
median(a1$pitch, na.rm = TRUE)
# (can vary because postprocessing is stochastic)
# compare to the true value:
median(getSmoothContour(anchors = list(time = c(0, .3, .8, 1),
value = c(300, 900, 400, 2300)), len = 1000))
# the same pitch contour, but harder to analyze b/c of
# subharmonics and jitter
sound2 = soundgen(sylLen = 900, pitch = list(
time = c(0, .3, .8, 1), value = c(300, 900, 400, 2300)),
noise = list(time = c(0, 900), value = c(-40, -20)),
subDep = 10, jitterDep = 0.5,
temperature = 0.001, samplingRate = 44100, pitchSamplingRate = 44100)
# playme(sound2, 44100)
a2 = analyze(sound2, samplingRate = 44100, priorSD = 24,
plot = TRUE, pathfinding = 'fast', ylim = c(0, 5))
# Fancy plotting options:
a = analyze(sound1, samplingRate = 44100, plot = TRUE,
xlab = 'Time, ms', colorTheme = 'seewave',
contrast = .5, ylim = c(0, 4), main = 'My plot',
pitchMethods = c('dom', 'autocor', 'spec', 'hps', 'cep'),
priorMean = NA, # no prior info at all
pitchDom = list(col = 'red', domThres = .25),
pitchPlot = list(col = 'black', pch = 9, lty = 3, lwd = 3),
extraContour = list(x = 'peakFreq', type = 'b', pch = 4, col = 'brown'),
osc = 'dB', heights = c(2, 1))
# Different options for summarizing the output
a = analyze(sound1, 44100,
summaryFun = c('mean', 'range'))
a$summary # one row per sound
# ...with custom summaryFun, eg time of peak relative to duration (0 to 1)
timePeak = function(x) which.max(x) / length(x) # without omitting NAs
timeTrough = function(x) which.min(x) / length(x)
a = analyze(sound2, samplingRate = 16000,
summaryFun = c('mean', 'timePeak', 'timeTrough'))
colnames(a$summary)
# Analyze a selection rather than the whole sound
a = analyze(sound1, samplingRate = 16000, from = .4, to = .8, plot = TRUE)
# Use only a range of frequencies when calculating spectral descriptives
# (ignore everything below 100 Hz and above 8000 Hz as irrelevant noise)
a = analyze(sound1, samplingRate = 16000, cutFreq = c(100, 8000))
## Amplitude and loudness: analyze() should give the same results as
# dedicated functions getRMS() / getLoudness()
# Create 1 kHz tone
samplingRate = 16000; dur_ms = 50
sound3 = sin(2*pi*1000/samplingRate*(1:(dur_ms/1000*samplingRate)))
a1 = analyze(sound3, samplingRate = samplingRate, scale = 1,
windowLength = 25, overlap = 50,
loudness = list(SPL_measured = 40),
pitchMethods = NULL, plot = FALSE)
a1$detailed$loudness # loudness per STFT frame (1 sone by definition)
getLoudness(sound3, samplingRate = samplingRate, windowLength = 25,
overlap = 50, SPL_measured = 40, scale = 1)$loudness
a1$detailed$ampl # RMS amplitude per STFT frame
getRMS(sound3, samplingRate = samplingRate, windowLength = 25,
overlap = 50, scale = 1)$detailed
# or even simply: sqrt(mean(sound3 ^ 2))
# The same sound as above, but with half the amplitude
a_half = analyze(sound3 / 2, samplingRate = samplingRate, scale = 1,
windowLength = 25, overlap = 50,
loudness = list(SPL_measured = 40),
pitchMethods = NULL, plot = FALSE)
a1$detailed$ampl / a_half$detailed$ampl # rms amplitude halved
a1$detailed$loudness/ a_half$detailed$loudness
# loudness is not a linear function of amplitude
# Analyzing ultrasounds (slow but possible, just adjust pitchCeiling)
s = soundgen(sylLen = 100, addSilence = 10,
pitch = c(25000, 35000, 30000),
formants = NA, rolloff = -12, rolloffKHz = 0,
pitchSamplingRate = 350000, samplingRate = 350000, windowLength = 5,
pitchCeiling = 45000, invalidArgAction = 'ignore')
# s is a bat-like ultrasound inaudible to humans
a = analyze(s, 350000, plot = TRUE,
pitchCeiling = 45000, priorMean = NA,
windowLength = 2, overlap = 0,
nFormants = 0, loudness = NULL)
# NB: ignore formants and loudness estimates for such non-human sounds
# download 260 sounds from Anikin & Persson (2017)
# http://cogsci.se/publications/anikin-persson_2017_nonlinguistic-vocs/260sounds_wav.zip
# unzip them into a folder, say '~/Downloads/temp'
myfolder = '~/Downloads/temp' # 260 .wav files live here
s = analyze(myfolder) # ~ 10-20 minutes!
# s = write.csv(s, paste0(myfolder, '/temp.csv')) # save a backup
# Check accuracy: import manually verified pitch values (our "key")
# pitchManual # "ground truth" of mean pitch per sound
# pitchContour # "ground truth" of complete pitch contours per sound
files_manual = paste0(names(pitchManual), '.wav')
idx = match(s$file, files_manual) # in case the order is wrong
s$key = pitchManual[idx]
# Compare manually verified mean pitch with the output of analyze:
cor(s$key, s$summary$pitch_median, use = 'pairwise.complete.obs')
plot(s$key, s$summary$pitch_median, log = 'xy')
abline(a=0, b=1, col='red')
# Re-running analyze with manually corrected contours gives correct
pitch-related descriptives like amplVoiced and harmonics (NB: you get it "for
free" when running pitch_app)
s1 = analyze(myfolder, pitchManual = pitchContour)
plot(s$summary$harmonics_median, s1$summary$harmonics_median)
abline(a=0, b=1, col='red')
# Save spectrograms with pitch contours plus an html file for easy access
s2 = analyze('~/Downloads/temp', savePlots = '',
showLegend = TRUE,
width = 20, height = 12,
units = 'cm', res = 300, ylim = c(0, 5))
# }
Run the code above in your browser using DataLab