| getSpecEnv | R Documentation |
Calculates a smoothed envelope of a magnitude spectrum or of each column of
a spectrogram. This is good for removing the fine structure produced by
harmonics of f0 and leaving only the overall spectral contour produced by
resonances (formants). This is the source-filter separation step used by
shiftFormants. All methods except "peak" smooth the
log-magnitude spectrum and return the envelope on the original linear scale,
with the same dimensions as the input.
getSpecEnv(
spec,
freqs = NULL,
freqWindow = NULL,
freqWindow_bins = NULL,
method = c("cepstral", "gauss", "movavg", "peak"),
plot = FALSE
)
spec |
numeric vector (magnitude spectrum of one frame) or matrix (rows
= frequency bins, columns = time frames), such as a spectrogram returned by
|
freqs |
frequency labels corresponding to |
freqWindow, freqWindow_bins |
the width of the smoothing window, in Hz
(not kHz!) or frequency bins (>0): for example, if we are trying to smooth
away the harmonics of f0 and leave only formants, |
method |
the method of smoothing: "cepstral" = Gaussian liftering of the real cepstrum (default), "gauss" = Gaussian blur of the log spectrum, "movavg" = moving average of the log spectrum, "peak" = moving maximum (upper envelope) |
plot |
if TRUE, produces a simple plot of the original spectrum and the extracted envelope |
The amount of smoothing is controlled by freqWindow_bins, which should
normally equal the expected spacing between harmonics (f0, in bins): spectral
details that vary on a faster scale are treated as source fine structure and
removed, while slower variations (formants) are retained. For high-pitched or
variable calls, increase freqWindow_bins to smooth more. Methods:
"cepstral" (default): Gaussian low-pass liftering of the real cepstrum
(FFT of the log spectrum). The harmonic ripple, which has a period of
freqWindow_bins bins, is attenuated to ~exp(-4) = 2
amplitude, while the formant envelope is preserved. By the convolution
theorem, this is equivalent to Gaussian smoothing of the log spectrum with
SD = freqWindow_bins / 2, but computed in the quefrency domain.
"gauss": Gaussian blur of the log spectrum along the frequency axis
with SD = freqWindow_bins / 2 - the same low-pass filter as
"cepstral", but with explicit edge padding instead of circular (wrap-around)
filtering.
"movavg": moving average of the log spectrum with a rectangular window of
width freqWindow_bins (rounded up to an odd number).
"peak": moving maximum (morphological dilation), i.e. the upper
envelope of the spectrum with a window of width freqWindow_bins.
Much slower than the other methods on long inputs.
The edges of the spectrum are handled by padding (repeating the edge values)
before smoothing and trimming afterwards, so the output always has the same
length as the input. If spec is a matrix (rows = frequency bins,
columns = time frames), all frames are smoothed at once.
The spectral envelope on the original (linear magnitude) scale, as a
numeric vector or matrix with the same dimensions as spec.
getEnv for the temporal envelope of a waveform;
shiftFormants, which uses getSpecEnv to shift formants
# Synthetic spectrum: three formants plus harmonics 20 bins apart
N = 512
freq = 1:N
true_envelope = exp(-.5 * ((freq - 100) / 20)^2) +
exp(-.5 * ((freq - 250) / 30)^2) +
exp(-.5 * ((freq - 400) / 40)^2)
spectrum = true_envelope * (0.5 + 0.5 * abs(sin(pi * freq / 20)))
plot(freq, spectrum, type = 'l', log = 'y',
main = 'Spectral envelope', xlab = 'Frequency, bins')
lines(freq, true_envelope, col = 'grey60', lwd = 4)
lines(getSpecEnv(spectrum, freqWindow_bins = 20, method = 'cepstral'),
col = 'red', lwd = 2)
lines(getSpecEnv(spectrum, freqWindow_bins = 20, method = 'gauss'),
col = 'orange', lwd = 2, lty = 2)
lines(getSpecEnv(spectrum, freqWindow_bins = 20, method = 'movavg'),
col = 'blue', lwd = 2, lty = 3)
lines(getSpecEnv(spectrum, freqWindow_bins = 20, method = 'peak'),
col = 'green', lwd = 2, lty = 4)
legend('bottom',
legend = c('raw', 'truth', 'cepstral', 'gauss', 'movavg', 'peak'),
col = c('black', 'grey60', 'red', 'orange', 'blue', 'green'),
lwd = c(1, 4, 2, 2, 2, 2), lty = c(1, 1, 1, 2, 3, 4), bty = 'n')
# Smoothed spectral envelope of a single vowel
data(speechEx, package = 'soundgen')
spec = spectrum(speechEx, from = .15, to = .3, plot = FALSE)
env = getSpecEnv(spec, freqWindow = 500, plot = TRUE)
# Smooth a whole spectrogram at once (matrix input):
spec = stft_simple(speechEx@left[1:16000],
samplingRate = speechEx@samp.rate,
wl = 512, step = 256)
spec = Mod(spec[1:(nrow(spec) %/% 2 + 1), ])
env = getSpecEnv(spec, freqWindow = 500, plot = TRUE)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.