I need to extract the envelope from a Wav sound file.
Is there a way to achieve that from the command-line using SoX or ffmpeg?
Super User is a question and answer site for computer enthusiasts and power users. It only takes a minute to sign up.Sign up to join this community
This can be approximated with SoX. An envelope detector basically needs to rectify the signal (i.e. take the absolute value of every sample, "folding over" the negative-going side of the signal so it is positive-going instead) and then run a very drastic lowpass filter over it, extracting a low frequency positive-going signal approximating the amplitude envelope of the original signal.
The main obstacle is that SoX does not give us an easy way to do the rectification step. I will present a couple ways to work around this.
The first is that instead of rectifying the signal we can just throw away the negative-going side of it by applying the
dcshift filter twice. This isn't perfect but provides accurate-enough output for most audio input.
sox $infile out.wav dcshift -1 dcshift +1 lowpass 20
(You will see something like
sox WARN dcshift: dcshift clipped 123987 samples; decrease volume?, but clipping samples is what we wanted it to do.)
The second trick we can use is to construct a square-law detector (also called a product detector) instead of a rectifying envelope detector. The relationship between the detected envelope and the input signal is different for this kind of detector, so you'll have to confirm which way works better for you. In the square-law detector, the input signal is multiplied with itself instead of rectified, and we can do that with SoX by specifying the same input twice with
sox --combine multiply $infile $infile out.wav lowpass 20
In either case, you can adjust the
20 to control the cutoff frequency of the lowpass and control how closely your detected envelope tracks the input/how much higher-frequency content is kept.
If you want to visualize the envelope, that's easy enough to do with ffmpeg, e.g.:
ffmpeg -i out.wav -filter_complex "showwavespic=s=640x120" -frames:v 1 out.png
Interestingly, this ffmpeg visualization will appear to show the signal as a bipolar one centered around 0, though it is now actually a monopolar signal in the range 0..+1. I think ffmpeg is silently removing any DC offset when it processes this visual.