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?


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 --combine multiply:

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.

| improve this answer | |
  • Thank you Tony for this very clever solution! My digital signal processing skills are a little bit rusty, but you reminded me a thing or two ;) – Sylvain Leroux Nov 22 '19 at 15:47
  • 1
    Interesting. Could you perhaps show how to actually generate the envelope image based on that? – slhck Nov 22 '19 at 15:48
  • @slhck Added to answer. – tgies Nov 22 '19 at 16:18
  • dcshift and multiply filters are available in FFmpeg too. – Paul B. Mahol Nov 25 '19 at 21:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.