#!/bin/bash

#########################################################
# A [pseudo] multithreaded WAV to MP3 encoder		#
#########################################################
# By Christopher A. Wadge, 09/04/2010			#
#							#
# http://files.tuxhelp.org/scripts/mp3-o-matic.sh	#
#							#
# Licensed under the GPL version 3. A copy of the GPL	#
# version 3 is included with this script.  If the file, #
# COPYING, is not included, you can find the GPL 	#
# version 3 at the following URL online:		#
#							#
# http://www.gnu.org/licenses/gpl-3.0.html		#
#########################################################

# This script's name:
PROGRAM_NAME="mp3-o-matic.sh"
# Date of last revision:
PROGRAM_DATE="12/30/11"

## VARIABLES ##
# The following are pre-determined variables that are not answered by the script.
#####

## Executable Paths ##

# lame/twolame/toolame binary locale:
MP3ENCODER="/usr/bin/lame"
# normalize-audio binary locale:
NORMAUDIO="/usr/bin/normalize-audio"

## Encoder Variables ##

# Nice priority level (19 to -20, 19 being the lowest):
PROCNICE="10"
# You can append additional values to the $MP3ENCODER encoding process if you wish:
XTRAOPTS="--vbr-new -h -V 0"
# Whether we should normalize the volume level of the original file before encoding:
NORMALIZE="false"
# Max number of encoder threads to use (leave blank for auto-detection):
THREADMAX=""

## !!! Attention Users: Editing below this line is not advised unless you really know what you're doing.

## FUNCTIONS ##
# Define each function that we will call in scripting later
#####

Error ()
{
	echo "[FATAL] Unfortunately we've encountered an unrecoverable error. Now quitting."
	exit 1
}

Print_Help ()
{
	echo ""
	echo "==== $PROGRAM_NAME ($PROGRAM_DATE) ===="
	echo ""
	echo "Description:   A multi-threaded front-end for popular MP3 encoders."
	echo ""
	echo "Usage:         $0 <path to '.wav' file(s) or directory>"
	echo "               You may also specify a wildcard, e.g. '*.wav'."
	echo "               Sans arguments, it will search the current directory."
	echo ""
	echo "Dependencies:  - At least one of: 'lame', 'twolame', or 'toolame'"
	echo "               - The Bourne Again SHell (aka 'BASH')"
	echo "               + Optional: 'normalize-audio'"
	echo ""
	exit 1
}

Detect_Threads ()
{
if [ -z $THREADMAX ] ; then
	if [ `uname -a | grep -c Linux` = 1 ] ; then
		THREADMAX=`cat /proc/cpuinfo | grep -c processor`
        elif [ `uname -a | egrep -c '(BSD|Darwin)'` = 1 ] ; then
                THREADMAX=`sysctl -a | grep hw.ncpu | grep -v "=" | cut -d " " -f2`
	fi
elif  (( "$THREADMAX" >= "1" )) ; then
        THREADMAX="$THREADMAX"
else
	echo "[WARNING] Unable to detect maximum supported CPU threads; falling back to 1 thread to be safe."
	echo "          You can specify the thread count manually in the 'VARIABLES' section of this script."
	THREADMAX="1"
fi
}

Sanity_Check ()
{
if [ ! -e /bin/bash ] ; then
	echo "[ERROR] It doesn't appear that you have the Bourne Again SHell (aka 'BASH')!"
	echo "        The [over-hyped] 'DASH' shell is too primitive to interpret this script."
	echo "        Please use your package manager to install 'bash' and try again."
	NOTSANE=1
fi
if [ ! -e $MP3ENCODER ] ; then
	echo "[ERROR] The MP3 Encoder binary is not in the expected location: '$MP3ENCODER'"
	echo "        If no lame-compatible encoder is installed, try installing one with your package manager."
	echo "        Otherwise, you can correct the path by editing the VARIABLES section of this script."
	NOTSANE=1
fi
if [ " $NORMALIZE " = " true " ] ; then
	if [ ! -e $NORMAUDIO ] ; then
		echo "[WARNING] The normalize-audio binary is not in the expected location: '$NORMAUDIO'"
		echo "          This is a non-critical error. However, normalization is currently enabled."
		echo "          If you no longer wish to see this error, set the 'NORMALIZE' variable to 'false'."
		NORMALIZE="false"
	fi
fi
if [ ! -z $NOTSANE ] ; then
	echo "[ERROR] Missing dependencies prevent this script from proceeding!"
	Error
fi
}

MP3_Encode ()
{
for file; do
[ -r "$file" ] || { echo '[ERROR] Unable to read file: \"$file\"' >&1 ; Error ; }
FILEOUT=$(echo "$file" | sed s'/[.][wW][aA][vV]//')
	if [ " $NORMALIZE " = " true " ] ; then 
		$NORMAUDIO --quiet "$file" || echo "[WARNING] Normalization failed for $file"
	fi
$MP3ENCODER --quiet $XTRAOPTS \
"$file" "$FILEOUT".mp3 || { echo "[ERROR] Transcoding failed for '$file'" >&1 ; Error ; } ; done
}

## SCRIPTING ##
# Here's where we actually do all the work
#####

if [ " $1 " = " --help " ] ; then
	Print_Help
fi
Sanity_Check
Detect_Threads
export MP3ENCODER
if [ " $NORMALIZE " = " true " ] ; then
	export NORMAUDIO
fi
export NORMALIZE
export XTRAOPTS
export -f Error
export -f MP3_Encode
find "${@}" -maxdepth 1 -name '*[.][wW][aA][vV]' -print0 | xargs -0 -n 1 -P $THREADMAX nice -n $PROCNICE bash -c 'MP3_Encode "$@"' --
exit 0