analyzers.lib
Analyzers library. Its official prefix is an
.
Amplitude Tracking
(an.)abs_envelope_rect
Absolute value average with movingaverage algorithm.
Usage
_ : abs_envelope_rect(period) : _;
Where:
period
: sets the averaging frame in seconds
(an.)abs_envelope_tau
Absolute value average with onepole lowpass and tau response. (See maths.lib.)
Usage
_ : abs_envelope_tau(period) : _;
Where:
period
: (time to decay by 1/e) sets the averaging frame in secs
(an.)abs_envelope_t60
Absolute value average with onepole lowpass and t60 response. (See maths.lib.)
Usage
_ : abs_envelope_t60(period) : _;
Where:
period
: (time to decay by 60 dB) sets the averaging frame in secs
(an.)abs_envelope_t19
Absolute value average with onepole lowpass and t19 response. (See maths.lib.)
Usage
_ : abs_envelope_t19(period) : _;
Where:
period
: (time to decay by 1/e^2.2) sets the averaging frame in secs
(an.)amp_follower
Classic analog audio envelope follower with infinitely fast rise and exponential decay. The amplitude envelope instantaneously follows the absolute value going up, but then floats down exponentially.
amp_follower
is a standard Faust function.
Usage
_ : amp_follower(rel) : _
Where:
rel
: release time = amplitudeenvelope timeconstant (sec) going down
Reference
 Musical Engineer's Handbook, Bernie Hutchins, Ithaca NY, 1975 Electronotes Newsletter, Bernie Hutchins
(an.)amp_follower_ud
Envelope follower with different up and down timeconstants (also called a "peak detector").
Usage
_ : amp_follower_ud(att,rel) : _
Where:
att
: attack time = amplitudeenvelope time constant (sec) going uprel
: release time = amplitudeenvelope time constant (sec) going down
Note
We assume rel >> att. Otherwise, consider rel ~ max(rel,att).
For audio, att is normally faster (smaller) than rel (e.g., 0.001 and 0.01).
Use amp_follower_ar
below to remove this restriction.
Reference
 "Digital Dynamic Range Compressor Design  A Tutorial and Analysis", by Dimitrios Giannoulis, Michael Massberg, and Joshua D. Reiss
 https://www.eecs.qmul.ac.uk/~josh/documents/2012/GiannoulisMassbergReissdynamicrangecompressionJAES2012.pdf
(an.)amp_follower_ar
Envelope follower with independent attack and release times. The
release can be shorter than the attack (unlike in amp_follower_ud
above).
Usage
_ : amp_follower_ar(att,rel) : _;
 Author Jonatan Liljedahl, revised by RM
(an.)ms_envelope_rect
Mean square with movingaverage algorithm.
Usage
_ : ms_envelope_rect(period) : _;
Where:
period
: sets the averaging frame in secs
(an.)ms_envelope_tau
Mean square average with onepole lowpass and tau response. (See maths.lib.)
Usage
_ : ms_envelope_tau(period) : _;
Where:
period
: (time to decay by 1/e) sets the averaging frame in secs
(an.)ms_envelope_t60
Mean square with onepole lowpass and t60 response. (See maths.lib.)
Usage
_ : ms_envelope_t60(period) : _;
Where:
period
: (time to decay by 60 dB) sets the averaging frame in secs
(an.)ms_envelope_t19
Mean square with onepole lowpass and t19 response. (See maths.lib.)
Usage
_ : ms_envelope_t19(period) : _;
Where:
period
: (time to decay by 1/e^2.2) sets the averaging frame in secs
(an.)rms_envelope_rect
Root mean square with movingaverage algorithm.
Usage
_ : rms_envelope_rect(period) : _;
Where:
period
: sets the averaging frame in secs
(an.)rms_envelope_tau
Root mean square with onepole lowpass and tau response. (See maths.lib.)
Usage
_ : rms_envelope_tau(period) : _;
Where:
period
: (time to decay by 1/e) sets the averaging frame in secs
(an.)rms_envelope_t60
Root mean square with onepole lowpass and t60 response. (See maths.lib.)
Usage
_ : rms_envelope_t60(period) : _;
Where:
period
: (time to decay by 60 dB) sets the averaging frame in secs
(an.)rms_envelope_t19
Root mean square with onepole lowpass and t19 response. (See maths.lib.)
Usage
_ : rms_envelope_t19(period) : _;
Where:
period
: (time to decay by 1/e^2.2) sets the averaging frame in secs
(an.)zcr
Zerocrossing rate (ZCR) with onepole lowpass averaging based on the tau constant. It outputs an index between 0 and 1 at a desired analysis frame. The ZCR of a signal correlates with the noisiness [Gouyon et al. 2000] and the spectral centroid [HerreraBoyer et al. 2006] of a signal. For sinusoidal signals, the ZCR can be multiplied by ma.SR/2 and used as a frequency detector. For example, it can be deployed as a computationally efficient adaptive mechanism for automatic Larsen suppression.
Usage
_ : zcr(tau) : _;
Where:
tau
: (time to decay by e^1) sets the averaging frame in seconds.
SpectrumAnalyzers
Spectrumanalyzers split the input signal into a bank of parallel signals, one for
each spectral band. They are related to the MthOctave FilterBanks in filters.lib
.
The documentation of this library contains more details about the implementation.
The parameters are:
M
: number of bandslices per octave (>1)N
: total number of bands (>2)ftop
= upper bandlimit of the Mthoctave bands (<SR/2)
In addition to the Mthoctave output signals, there is a highpass signal containing frequencies from ftop to SR/2, and a "dc band" lowpass signal containing frequencies from 0 (dc) up to the start of the Mthoctave bands. Thus, the N output signals are:
highpass(ftop), MthOctaveBands(M,N2,ftop), dcBand(ftop*2^(M*(N1)))
A SpectrumAnalyzer is defined here as any bandsplit whose bands span the relevant spectrum, but whose bandsignals do not necessarily sum to the original signal, either exactly or to within an allpass filtering. Spectrum analyzer outputs are normally at least nearly "power complementary", i.e., the power spectra of the individual bands sum to the original power spectrum (to within some negligible tolerance).
Increasing Channel Isolation
Go to higher filter orders  see Regalia et al. or Vaidyanathan (cited below) regarding the construction of more aggressive recursive filterbanks using elliptic or Chebyshev prototype filters.
References
 "Treestructured complementary filter banks using allpass sections", Regalia et al., IEEE Trans. Circuits & Systems, CAS34:14701484, Dec. 1987
 "Multirate Systems and Filter Banks", P. Vaidyanathan, PrenticeHall, 1993
 Elementary filter theory: https://ccrma.stanford.edu/~jos/filters/
(an.)mth_octave_analyzer
Octave analyzer.
mth_octave_analyzer[N]
are standard Faust functions.
Usage
_ : mth_octave_analyzer(O,M,ftop,N) : par(i,N,_); // Othorder Butterworth
_ : mth_octave_analyzer6e(M,ftop,N) : par(i,N,_); // 6thorder elliptic
Also for convenience:
_ : mth_octave_analyzer3(M,ftop,N) : par(i,N,_); // 3dorder Butterworth
_ : mth_octave_analyzer5(M,ftop,N) : par(i,N,_); // 5throder Butterworth
mth_octave_analyzer_default = mth_octave_analyzer6e;
Where:
O
: order of filter used to split each frequency band into twoM
: number of bandslices per octaveftop
: highest bandsplit crossover frequency (e.g., 20 kHz)N
: total number of bands (including dc and Nyquist)
MthOctave Spectral Level
Spectral Level: Display (in bar graphs) the average signal level in each spectral band.
(an.)mth_octave_spectral_level6e
Spectral level display.
Usage:
_ : mth_octave_spectral_level6e(M,ftop,NBands,tau,dB_offset) : _;
Where:
M
: bands per octaveftop
: lower edge frequency of top bandNBands
: number of passbands (including highpass and dc bands),tau
: spectral display averagingtime (time constant) in seconds,dB_offset
: constant dB offset in all band level meters.
Also for convenience:
mth_octave_spectral_level_default = mth_octave_spectral_level6e;
spectral_level = mth_octave_spectral_level(2,10000,20);
(an.)[thirdhalf]_octave_[analyzerfilterbank]
A bunch of special cases based on the different analyzer functions described above:
third_octave_analyzer(N) = mth_octave_analyzer_default(3,10000,N);
third_octave_filterbank(N) = mth_octave_filterbank_default(3,10000,N);
half_octave_analyzer(N) = mth_octave_analyzer_default(2,10000,N);
half_octave_filterbank(N) = mth_octave_filterbank_default(2,10000,N);
octave_filterbank(N) = mth_octave_filterbank_default(1,10000,N);
octave_analyzer(N) = mth_octave_analyzer_default(1,10000,N);
Usage
See mth_octave_spectral_level_demo
in demos.lib
.
ArbritaryCrossover FilterBanks and Spectrum Analyzers
These are similar to the Mthoctave analyzers above, except that the bandsplit frequencies are passed explicitly as arguments.
(an.)analyzer
Analyzer.
Usage
_ : analyzer(O,freqs) : par(i,N,_); // No delay equalizer
Where:
O
: bandsplit filter order (ODD integer required for filterbank[i])freqs
: (fc1,fc2,...,fcNs) [in numerically ascending order], where Ns=N1 is the number of octave bandsplits (total number of bands N=Ns+1).
If frequencies are listed explicitly as arguments, enclose them in parens:
_ : analyzer(3,(fc1,fc2)) : _,_,_
Fast Fourier Transform (fft) and its Inverse (ifft)
Sliding FFTs that compute a rectangularly windowed FFT each sample.
(an.)gortzelOpt
Optimized Goertzel filter.
Usage
_ : goertzelOpt(freq,N) : _;
Where:
freq
: frequency to be analyzedN
: the Goertzel block size
Reference
(an.)gortzelComp
Complex Goertzel filter.
Usage
_ : goertzelComp(freq,N) : _;
Where:
freq
: frequency to be analyzedN
: the Goertzel block size
Reference
(an.)goertzel
Same as goertzelOpt
.
Usage
_ : goertzel(freq,N) : _;
Where:
freq
: frequency to be analyzedN
: the Goertzel block size
Reference
(an.)fft
Fast Fourier Transform (FFT).
Usage
si.cbus(N) : fft(N) : si.cbus(N);
Where:
si.cbus(N)
is a bus of N complex signals, each specified by real and imaginary parts: (r0,i0), (r1,i1), (r2,i2), ...N
is the FFT size (must be a power of 2: 2,4,8,16,...)fft(N)
performs a lengthN
FFT for complex signals (radix 2) The output is a bank of N complex signals containing the complex spectrum over time: (R0, I0), (R1,I1), ...
 The dc component is (R0,I0), where I0=0 for real input signals.
FFTs of Real Signals:
 To perform a sliding FFT over a real input signal, you can say
process = signal : an.rtocv(N) : an.fft(N);
where an.rtocv
converts a real (scalar) signal to a complex vector signal having a zero imaginary part.

See
an.rfft_analyzer_c
(inanalyzers.lib
) and related functions for more detailed usage examples. 
Use
an.rfft_spectral_level(N,tau,dB_offset)
to display the power spectrum of a real signal. 
See
dm.fft_spectral_level_demo(N)
indemos.lib
for an example GUI drivingan.rfft_spectral_level()
.
Reference
(an.)ifft
Inverse Fast Fourier Transform (IFFT).
Usage
si.cbus(N) : ifft(N) : si.cbus(N);
Where:
 N is the IFFT size (power of 2)
 Input is a complex spectrum represented as interleaved real and imaginary parts: (R0, I0), (R1,I1), (R2,I2), ...
 Output is a bank of N complex signals giving the complex signal in the time domain: (r0, i0), (r1,i1), (r2,i2), ...