Batch Normalize and add Fades to Audio Files

norm_fade

A new project I have just started has had me editing a lot of relatively long audio files.  I have to cut them up separating the noise from the spoken word, normalize each file, and add fades to the beginning and end.  Then, I have to export them.  I was using Audacity, which is a great (though ugly) audio editor.  However, there are some problems with batch work in Audacity that ended cost me a lot of time and ultimately making it unsuitable for my purposes.  Finding no app for mac to quickly batch normalize, add fades, and save as a 48k/24-bit file, I decided I would bite the bullet and try to *assemble a bash script to do the tedious work for me.

The actual program that does the audio processing is called SoX.  SoX is a great command-line utility (Mac, Linux) for digital signal processing.  If you are on a gnu-linux machine, chances are your distro has a sox package you can easily install.  If you are on a mac, you can just grab this package and install it wherever you want.

You can download the script from here.

It is based on this script by Ben McDowell.  I have commented it rather heavily so you know (as much as I do) what is going on in the file.  Here’s what it looks like.

#!/bin/sh

#  Script.sh
#
#
#  Created by scacinto on 1/31/13.
#
#  For now, only put audio files in the working directory - working on a fix

# This is the directory to the source soundfiles that need to be
# normalized and faded (the first argument on the command line.)
src=$1
# This is the directory to write the normalized and faded files to
# (The second path you must supply on the command line.)
dest=$2
#  This is the sox binary directory.  Please set this to your sox path.
#  As it is now, this assumes that the sox binary is in the same directory
#  as the script.
SOX=./sox

#enable for loops over items with spaces in their name
IFS=$'\n'

#  This is the 'for' loop - it will run for each file in your directory.
for original_file in `ls "$src/"`
do
# Get the base filename of the current wav file
base_filename=`basename "$original_file" .wav`

# We need a temp file name to save the intermediate file as
temp_file="${base_filename}-temp.wav"

# And we need the output WAV file
wav_file="${base_filename}-nf.wav"

# Convert all spaces to hyphens in the output file name
wav_file=`echo $wav_file | tr -s " " "-"`

#Print a progress message
echo "Processing: \"$original_file\". Saving as \"$wav_file\" ..."

# We need the length of the audio file
original_file_length=`$SOX $src/"$original_file" 2>&1 -n stat | grep Length | cut -d : -f 2 | cut -f 1`

# Use sox to add perform the fade-in and fade-out
# saving the result as our temp_file.  Adjust the 0.1s to your desired fade
# times.
$SOX $src/"$original_file" $src/"$temp_file" fade t 0.1 $original_file_length 0.1

# If files have readable headers, you can skip the above operation to get the
# file length and just use 0 as below.
#$SOX $src/"$original_file" $src/"$temp_file" fade t 0.5 0 0.5

# normalize and write to the output wave file
$SOX $src/"$temp_file" $dest/"$wav_file" norm -0.5

# Delete that temp file
rm $src/$temp_file

done

To get the script to work on a Mac, either alter the beginning of the file above (in red) to supply the path to your sox installation or simply put it in run it from the sox directory you downloaded.  On GNU Linux just supply your sox path after installing from your distro.  Then, from the command line do:

$ sh norm_fade.sh /path/to/original/audiofiles /path/to/write/to

The ‘sh’ tells bash to run the script, ‘norm_fade.sh’ is the script, the first path should be to the files you want to add fades to and normalize, and the second path should be the output directory where you want the files written to.

**EDIT:**
I found it necessary to comment out (or remove) the following line from the script)

IIFS=$'\n'

from the file on my Ubuntu laptop.  Instead of skipping over spaces it just removes all the ‘n’s from the paths and files…   More as I learn it!

Now, a couple caveats.  First, the first path must be to a FOLDER not a file.  If you want to run the script on a single file, put it in a directory and supply the directory path.  Second, the script expects .wav files.   If you throw an .aif in there, SoX will handle it, but the script has it writing out a file with the .wav extension.  The files will play, but your mileage may vary…  Be warned!

If you have questions or a way to make the code better/more efficient, please post to the comments!

Cheers, and happy normalization!

_

_

_

*I didn’t so much write it as assemble it from bits of code I found with a small amount of my own ‘code glue.’