03 – Using the command line to process audio
The Command Line
Before going further, have a read of this, it talks you through some starting points to working on the commandline:
Check out the SoX pages: sox.sourceforge.net/
1 Managing the terminal
The terminal or shell can be daunting at first. There is no Graphical User Interface (GUI), rather a series of commands you type into the shell in order to perform actions. Without a GUI, you lose some of the reassuring feedback that things are happening as you need them to, but you get the far more important benefit of a huge increase in speed.
Before you can do much with the shell, you need to know how to get into specific directories in order to work.
To get into a directory with sound, if you know the full path, you can simply type
cd ~/Dropbox/sounds, hit enter.
If you have dropbox installed, then this will take you to your dropbox folder and a directory within that place called sounds.
If you don’t know the path, or can’t be bothered to type the path, you can type
cd with a space after it then drag and drop the folder in question. Press enter and the terminal will now be pointing to this particular place.
To find out which directory you are in, type pwd and hit enter.
To list the contents of a directory ls enter.
To list specific files in a directory type ls *.pdf
To open one of the pdf files type open thepdfname.pdf
Can you think of a way to list all the .wav files in a directory?
1.1 Styling the terminal
You’ll see in my own terminal I use a colour scheme I like. Set this up in Terminal:Preferences:Profiles
2 Converting audio using SoX
SoX is a brilliant command line programme for converting between file types and batch processing audio.
2.1 Converting between file types
Converting files from one file type to another is relatively simple.
sox input.wav output.mp3
Will simply convert the wav file called input.wav to the mp3 file called output.mp3
To write the converted files to another directory, first make a directory for the files to live in:
mkdir aifConversions
You’ll see that the file is placed in the directory you specified.
sox input.wav aifConversions/output.aiff
Will convert a wav file to an aiff file and place it in aifConversions folder you just made.
2.2 Converting sample rate
This again is very simply done. Call SoX, open the sound file, change the rate with -r and name the output file:
sox Blister_pack.wav -r 44.1k Blister_pack.aif
This will convert to a very low sample rate and play that converted file back for you right after:
sox Blister_pack.wav -r 8k Blister_pack_lowfi.aiff; play Blister_pack_lowfi.aiff
2.3 Converting bit depth
It’s rare that you’d want to convert bit depth on a file, but sometimes it’s necessary to scale down from 24bit to 16bit files and to do this for all assets, particularly if you’re trying to save space in a game/mobile project.
sox Blister_pack.wav -r 44.1k -b 8 Blister_pack.aif
The above will do this for an individual file, to do this with loads of files, you need to embrace batch processing.
2.4 Batch converting
Writing out the text for each command can be time consuming if you have to this for all assets, so you can use the shell to batch process your conversion processes. The basic rule for this is to ensure that you’re writing new files, rather than writing over your original, pristine sources, so I always make a new directory to write everything to:
mkdir converted
The above will make a directory called converted next to where you’re working.
Then you can run a batch process:
for all files of a certain type in the directory, do something interesting:
for f in *.wav; do sox "$f" "converted/${f%%.wav}.mp3"; done
The above will make you a bunch of mp3 files from source wav files. The quotes around the string converted/${f%%.wav}.mp3 means that we can cope with spaces in file names, but we really don’t want you to have spaces in file names so this is just an extra catch all. The complex-looking thing in the formula above is the bit attending to the file name extension. Basically, we take the first part of the file name and keep it, but swap out the file extension.
How would you batch convert sample rates? How would you batch convert bit depth? How would you batch convert sample rate, bit depth and to aif in one go?
3 Extracting information about your audio
3.1 Making spectrograms
You can render off a spectrogram of your sound file like this
sox input.wav -n spectrogram -t "top label" -c "corner label" -o inputFileName.png
e.g. sox Blister_pack.wav -n spectrogram -t "Blister Pack" -c "Blister Pack" -o Blister_Pack.png
To batch make spectrograms it’s pretty easy:
for f in *.wav; do sox "$f" -n spectrogram -t "$f" -c "$f" -o "${f%%.wav}.png"; done
3.2 dumping data from a set of files to a database/file
It’s straightforward to dump data about a bunch of audio files in a folder to a text file, this can be done with soxi. Soxi gives you file information.
Try this to dump all the data that SoxI can get from all the .wav files in a folder:
soxi *.wav > database.csv
The > in the above command writes the data from soxi to a file called database.csv
If you just want a list of files in a folder, you can use the command line to write a list of files to a text file thus:
ls *.wav > fileList.txt
The above will write you a text file called fileList.txt with the name of all .wav files in the directory.
To make a better set out list of files, follow this tutorial by Owen Green.
If you want to dump the history of whay you’ve been typing on the commandline for future reference, you can dump it all to a text file like this:
history > ~/Documents/thingsIdidOnTheCommandLine.txt
4 Extracting short files from longer files
mkdir renders
sox Blister_pack.wav -c 2 renders/output.wav sinc 0.01k silence 1 0.01 1% trim 0 0.05 fade q 100s 0 100s : newfile : restart
The above will extract a new file when the track detects silence at 1%, it will then trim the file to make it 0.05 seconds long and apply a fade of 100 samples to the beginning and end of the file.
Joining files together (contatenation)
SoX will be very happy to add files together to make a new structure:
sox file1.wav file2.wav file3.wav output.wav
This is super useful if you want to quickly string together several files you know the names of into a single sound file.
Joining files together when you can’t be bothered to find out their names
cd into the directory where the files are
run the following to join all the sound files in-order to create a file called output.wav
sox *.wav output.wav
Joining your extracted files together using a random function
For OS X users, you’ll need to go back to brew and install the coreutils. Head to the commandline and type:
brew install coreutils
This gives you access to some useful list wrangling tools. In this case we want to play with gshuf. Use gshuf to look at all the files in a folder, generate a random list of the files which SoX will then contatenate. This is great, given the simplicity of the code used to generate output:
sox $(ls *.wav | gshuf) output.wav
Linux users probably don’t need the g in front of gshuf. Windows users, sorry, I’ve not got as far as testing this on Windows at time of writing.
You’ll notice if you keep doing the above (changing the ‘output.wav’ name each time) that the file count in the directory will keep growing and the size of each file will be bigger because it will keep on adding EVERY file in the folder to the output. It’s best then to export to a sub directory
mkdir exportedsox $(ls *.wav | gshuf) exported/output.wav
DO NOT have spaces in filenames for the above otherwise you won’t be happy.
4.5 If you’re still following me, which I doubt you are, here’s a killer bit of scripting
Ok, so you’ve automatically made a folder of separate sound files and you want to restructure them into something new and you want to do it plenty of times, well there is a way to get the command line to actually do this for you. By using the seq command, you can litterally run a function on the command line several times, and pass an argument across to change what SoX does each time the sequence is run.
Navigate to a folder of short sound files:
cd folder_of_short_sound_files
Make a directory in there called outputs:
mkdir outputs
When you’re in there, run the following line. It will create 20 random structures from the sound files that are there, place them in a folder called outputs and name each file uniquely.
for i in {1..10}; do sox $(ls *.wav | gshuf) outputs/new_$i.wav; done
The above should make you think carefully before opening your DAW, do you really need a DAW at all? Discuss….
The above line’s genius came from attending to answer 97 on this stack exchange post:
5 Joining channels together
This is obviously useful if you’ve been given 6 separate stems and you want to convert and play all stems on your own 5.1 system. The stems may be in SMTPE format (e.g L C R Ls Rs LFE ) and you might wish to add the channels together to conform to ITU film channel ordering (L R C LFE Ls Rs) for example.
sox -m left.wav right.wav centre.wav sub.wav ls.wav rs.wav ITUsurroundOrderedFile.wav sox -m left.wav right.wav aStereoSoundFile.wav
Some other and repeated features below, continue at will
File Conversion
It’s straightforward when the code is installed. To be able to do loads of file conversion (to ogg, mp3 (via lame) and flac, you’ll need to reinstall sox with these libraries included. The simplest command then is to run this over your current SoX installation. FFMPEG can be used instead of SoX for file conversion, it’s also immensely powerful.
brew reinstall sox --with-lame --with-flac --with-libvorbis
Wav to Aif
sox input.wav output.aif
Wav to MP3
To convert to and from mp3
sox ohYeah_02.wav yes.mp3
With SoX and the lame lib included
sox infile.wav outfile.mp3
Wav to flac
You’ll need ffmpeg or to install flac, or to reinstall SoX with Flac included.
brew install flac
Then run
flac -s sourceFile.wav -o outfile.flac
Or with SoX
sox sourceFile.wav flacFile.flac
Flac to Wav
flac -s sourceFile.flac -o outfile.wav
Or with SoX
sox sourceFile.flac wavFile.wav
Earwax
sox inputfile.wav outputfile-earwaxed.wav earwax
Use with caution, only works with CD audio and stereo files and _will change the sound, worth a try though as it may work well on some material.
Data gathering
sox inputFile.wav -n stat
gives you this kind of data:
Samples read: 29106000 Length (seconds): 330.000000 Scaled by: 2147483647.0 Maximum amplitude: 0.045941 Minimum amplitude: -0.042231 Midline amplitude: 0.001855 Mean norm: 0.002434 Mean amplitude: -0.000001 RMS amplitude: 0.004545 Maximum delta: 0.059067 Minimum delta: 0.000000 Mean delta: 0.000821 RMS delta: 0.002238 Rough frequency: 3456 Volume adjustment: 21.767
Generating waveforms
This can be done with ffmpeg:
ffmpeg -i inputFile.wav -lavfi showwavespic=split_channels=1:s=1024x800 outputWaveform.png
More information on this feature is here:
Batch processing using FFMPEG or SOX
If you’ve been busy making loads of files with automated processes, you might want to look at all of the waveforms, or indeed do some visual sorting. When there are loads of files and you hate typing in files names, you can use batch processes. To generate waveforms for all wav files in a folder, this should help. Note you’ll need to:
mkdir waveforms
before you run this. The code is expecting a folder called waveforms to write to. Note, we’re also swapping the extension .wav for .png with the “${f/%wav/png}”, the quotes should mean that you can cope with file names with spaces, but I think spaces are best avoided in file names if possible.
for f in *.wav; do ffmpeg -i "$f" -lavfi showwavespic=split_channels=1:s=1024x800 waveforms/"${f/%wav/png}"; done
It’s pretty handy as you can check tht your fades have actually worked as you can see them. What you don’t get here is any data on the waveform however and spectrograms might be more useful to you.
To batch render spectrograms, you can use SoX or FFMPEG. To show another way of batching, we’ll use SoX.
First
mkdir spectrogram
This will make a folder called spectrgram in the folder you’re currently working in
Now, you can run something like this
for f in *.wav; do sox "$f" -n spectrogram -t "$f" -c "$f" -o spectrogram/"$f.png"; done
It basically looks for all the files in the folder with a .wav extension, then does the sox command giving title to the image (-t and text at bottom left -c).
It’s good, but better would be to lose the .wav extension from the file names that get rendered. So, try this;
for i in *.wav; do sox $i -n spectrogram -o spectrogram/${i%%.wav}.png; done
Starting with some batch processes using SoX
Batch convert to mp3 when you’ve got the LAME library connected with SoX:
for i in *.WAV; do sox $i exports/${i%%.wav}.mp3; done
How might you batch convert to FLAC or AIFF?
Handy starting point for writing scripts that handle multple files and generate output data
Quick crash course on getting SoX running on your windows or Os X installation;
Thanks UoW:
Here’s a way to get FFMPEG installed on windows 10
Thanks MasimMan