#!/usr/bin/env bash
#
# Encode directories with audio files to other formats.
# Date: 2024-01-30, v3.2
# Copyright (C), Grozdan "microchip" Nikolov <neutrino8@gmail.com>
# License: GNU GPLv2+

if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
	echo "Usage: $(basename $0) [mp3/aac/opus/vorbis/ogg/ac3/eac3/dts/flac/alac/wavpack/aiff/wav] {indir} {outdir}"
	exit 1
fi

INDIR="$(realpath "$2")"
OUTDIR="$(realpath "$3")"

if [ ! -d "$INDIR" ]; then
	echo "-> No such input directory!" 
	exit 1
fi
if [ ! -d "$OUTDIR" ]; then
	mkdir -p "$OUTDIR" 2>/dev/null
	if [ $? != 0 ]; then
		echo "-> Failed to create output directory!"
		exit 1
	fi
fi
if [ "$INDIR" = "$OUTDIR" ]; then
	echo "-> Input directory matches output directory!"
	exit 1
fi

case "$1" in
	mp3)
	printf "Select the Encoding Mode [abr/cbr/vbr - default is vbr]: "
	read mode
	case "$mode" in
		vbr|"")
		printf "Specify the Quality Value [0(high)-9(low) - default is 2]: "
		read qv
		test -z "$qv" && qual="2" || qual="$qv"
		params="-q:a $qual"
		;;
		abr|cbr)
		printf "Specify the Bitrate in kbps [default is 256]: "
		read br
		test -z "$br" && bitrate="256" || bitrate="$br"
		case "$mode" in
			abr)	abr="-abr 1" ;;
		esac
		params="-b:a ${bitrate}k $abr"
		;;
	esac
	;;
	aac)
	printf "Select the AAC Profile [lc/he1/he2 - default is lc]: "
	read prof
	case "$prof" in
		lc|"")	profile="-profile:a aac_low" ;;
		he1)	profile="-profile:a aac_he" ;;
		he2)	profile="-profile:a aac_he_v2" ;;
	esac
	printf "Select the Encoding Mode [(b)itrate/(q)uality - default is b]: "
	read mode
	case "$mode" in
		b|"")
		printf "Specify the Bitrate in kbps [default is 224]: "
		read br
		test -z "$br" && bitrate="224" || bitrate="$br"
		params="-b:a ${bitrate}k $profile"
		;;
		q)
		case "$prof" in
			he1|he2)
			echo "-> VBR encoding not supported by AAC Profile!"
			exit 1
			;;
		esac
		printf "Specify the Quality Value [1(low)-5(high) - default is 5]: "
		read qv
		test -z "$qv" && qual="5" || qual="$qv"
		params="-vbr $qual $profile"
		;;
	esac
	;;
	vorbis|ogg)
	printf "Select the Encoding Mode [(b)itrate/(q)uality - default is q]: "
	read mode
	case "$mode" in
		q|"")
		printf "Specify the Quality Value [-1(low)-10(high) - default is 7]: "
		read qv
		test -z "$qv" && qual="7" || qual="$qv"
		params="-q:a $qual"
		;;
		b)
		printf "Specify the Bitrate in kbps [default is 224]: "
		read br
		test -z "$br" && bitrate="224" || bitrate="$br"
		params="-b:a ${bitrate}k"
		;;
	esac
	;;
	opus)
	printf "Select the Encoding Mode [cbr/vbr - default is vbr]: "
	read mode
	case "$mode" in
		vbr|"")	vbr="-vbr on" ;;
		cbr)	vbr="-vbr off" ;;
	esac
	printf "Specify the Bitrate in kbps [default is 160]: "
	read br
	test -z "$br" && bitrate="160" || bitrate="$br"
	params="-b:a ${bitrate}k $vbr"
	;;
	ac3|eac3|dts)
	case "$1" in
		dts)	defbr="754" ;;
		*)	defbr="384" ;;
	esac
	printf "Specify the Bitrate in kbps [default is $defbr]: "
	read br
	test -z "$br" && bitrate="$defbr" || bitrate="$br"
	params="-b:a ${bitrate}k"
	;;
	flac)
	printf "Specify the Compression Level [0(low)-12(high) - default is 5]: "
	read cl
	test -z "$cl" && complev="5" || complev="$cl"
	params="-compression_level $complev"
	;;
	alac|wavpack)
	true
	;;
	aiff|wav)
	case "$1" in
		aiff)	en="be" ;;
		wav)	en="le" ;;
	esac
	printf "Select the Bit Depth [16/24/32 - default is 16]: "
	read bd
	case "$bd" in
		16|"")	codec="pcm_s16$en" ;;
		24)	codec="pcm_s24$en" ;;
		32)	codec="pcm_s32$en" ;;
	esac
	;;
	*)
	echo "-> Unsupported audio codec!"
	exit 1
	;;
esac

printf "Resample the Audio Files? [y/N]: "
read ares
if [ "$ares" = "y" -o "$ares" = "Y" ]; then
	printf "Specify the Sample Rate in Hertz [default is 44100]: "
	read srhz
	test -z "$srhz" && hertz="44100" || hertz="$srhz"
	case "$1" in
		opus)
		# Minimum for Opus is 48 kHz
		if [[ $hertz -lt 48000 ]]; then
			hertz="48000"
		fi
		;;
	esac
fi

hz_func() {
	if [ ! -z "$hertz" ]; then
		HZ="$(ffprobe -i "$i" -v quiet -show_entries stream=sample_rate -of default=noprint_wrappers=1:nokey=1)"
		if [ "$HZ" != "$hertz" ]; then
			resample="-af aresample=${hertz}:filter_type=kaiser"
		fi
	fi
	case "$1" in
		opus)	cutoff="-cutoff 20000" ;;
		""|*)	cutoff="-cutoff 18000" ;;
	esac
}

cd "$INDIR"

# Common audio extensions
audext="*.flac *.mp3 *.aac *.m4a *.alac *.aiff *.wma *.ogg *.opus *.ac3 *.eac3 *.ac4 *.thd *.dts *.mp1 *.mp2 *.atrac *.oma *.at3 *.at9 *.atp *.aa3 *.hma *.omg *.ape *.mp4a *.wav *.wave *.pcm *.midi *.mid *.amr *.ra *.dtshd *.fla *.cdda *.au *.wv *.wvc *.tta *.mka *.mpc *.mpp *.oga *.mlp *.shn *.weba *.awb *.dsf"

case "$1" in
	mp3)
	for i in $audext; do
		if [ -f "$i" ]; then
			hz_func
			nice -n 19 ffmpeg -i "$i" -map 0 -c:v copy -c:a libmp3lame $params $cutoff $resample "$OUTDIR/${i%.*}.mp3"
		fi
	done
	;;
	aac)
	for i in $audext; do
		if [ -f "$i" ]; then
			hz_func
			nice -n 19 ffmpeg -i "$i" -map 0 -c:v copy -c:a libfdk_aac $params -afterburner 1 -movflags +faststart $cutoff $resample "$OUTDIR/${i%.*}.m4a"
		fi
	done
	;;
	vorbis|ogg)
	for i in $audext; do
		if [ -f "$i" ]; then
			hz_func
			nice -n 19 ffmpeg -i "$i" -map 0 -vn -c:a libvorbis $params $cutoff $resample "$OUTDIR/${i%.*}.ogg"
		fi
	done
	;;
	opus)
	for i in $audext; do
		if [ -f "$i" ]; then
			hz_func opus
			nice -n 19 ffmpeg -i "$i" -map 0 -vn -c:a libopus $params $cutoff $resample "$OUTDIR/${i%.*}.opus"
		fi
	done
	;;
	ac3|eac3)
	for i in $audext; do
		if [ -f "$i" ]; then
			hz_func
			nice -n 19 ffmpeg -i "$i" -map 0 -vn -c:a $1 $params $cutoff $resample "$OUTDIR/${i%.*}.$1"
		fi
	done
	;;
	dts)
	for i in $audext; do
		if [ -f "$i" ]; then
			hz_func
			nice -n 19 ffmpeg -i "$i" -map 0 -vn -c:a dca -strict -2 $params $cutoff $resample "$OUTDIR/${i%.*}.dts"
		fi
	done
	;;
	flac)
	for i in $audext; do
		if [ -f "$i" ]; then
			hz_func
			nice -n 19 ffmpeg -i "$i" -map 0 -c:v copy -c:a flac $params $resample "$OUTDIR/${i%.*}.flac"
		fi
	done
	;;
	alac)
	for i in $audext; do
		if [ -f "$i" ]; then
			hz_func
			nice -n 19 ffmpeg -i "$i" -map 0 -c:v copy -c:a alac -movflags +faststart $resample "$OUTDIR/${i%.*}.m4a"
		fi
	done
	;;
	wavpack)
	for i in $audext; do
		if [ -f "$i" ]; then
			hz_func
			nice -n 19 ffmpeg -i "$i" -map 0 -vn -c:a wavpack $resample "$OUTDIR/${i%.*}.wv"
		fi
	done
	;;
	aiff)
	for i in $audext; do
		if [ -f "$i" ]; then
			hz_func
			nice -n 19 ffmpeg -i "$i" -map 0 -c:v copy -c:a $codec -write_id3v2 1 $resample "$OUTDIR/${i%.*}.aiff"
		fi
	done
	;;
	wav)
	for i in $audext; do
		if [ -f "$i" ]; then
			hz_func
			nice -n 19 ffmpeg -i "$i" -f wav -map 0 -vn -c:a $codec -bitexact $resample "$OUTDIR/${i%.*}.wav"
		fi
	done
	;;
esac

exit $?
