#!/bin/bash

# rgbpm - Copyright (c) 2019 Matthias C. Hormann
# apply replay gain (mp3gain2) and BPM (bpm-calc) to all folders below and including specified one
# For correct album replay gain, we assume all files of one album are in the same folder.
# 2019-07-07 - new version looks for loudgain
# 2019-07-10 - new version compatible with loudgain v0.2.6/0.2.7
#            - added -k (clipping prevention) option to loudgain commands
# 2019-07-31 - add support for *.m4a (AAC audio) files (requires loudgain 0.4.0+)
# 2019-08-05 - add support for *.mp2 (MPEG-1 layer 2) audio files
#              (requires loudgain 0.5.2+ and new bpm-calc)
# 2019-08-06 - add support for *.opus (Opus) files (requires loudgain 0.5.3+)
#              Note: Currently not supported by bpm-calc!
# 2019-08-13 - v0.8:
#            - MacOS-compatible version (no xargs -i, -r); rename to "rgbpm" (w/o ".sh")
#            - added getopts for -h, -v and -b
# 2019-09-01 - v0.9:
#            - add ASF/WMA support
# 2019-09-02 - v0.10:
#            - add WAV support
# 2ß10-09-03 - v0.11:
#            - add additional file types (Ogg and WavPack)
# 2019-09-04 - v0.12:
#            - add AIFF support (*.aif and *.aiff)
# 2019-09-06 - v0.13:
#            - add APE (Monkey’s Audio) support

# define me
me=`basename "$0"`
version="0.13"
#MUSICDIR="$HOME/Musik/Today/"
MUSICDIR=""

# check if we have loudgain available
LOUDGAIN=true
command -v loudgain >/dev/null 2>&1 || LOUDGAIN=false

# if loudgain not installed, we need mp3gain2, metaflac and vorbisgain, go check
if [ "$LOUDGAIN" != true ] ; then
  # check if mp3gain2 installed
  command -v mp3gain2 >/dev/null 2>&1 || { echo >&2 "$me requires \"mp3gain2\" but it's not installed. Aborting."; exit 2; }

  # check if metaflac installed
  command -v metaflac >/dev/null 2>&1 || { echo >&2 "$me requires \"metaflac\" but it's not installed. Aborting."; exit 2; }

  # check if vorbisgain installed
  command -v vorbisgain >/dev/null 2>&1 || { echo >&2 "$me requires \"vorbisgain\" but it's not installed. Aborting."; exit 2; }
else
  LOUDGAINVER=$(loudgain --version | head -n1 | awk '{print $2}')
  # we have the greatest and latest, yay!
  echo "$me is using 'loudgain' v${LOUDGAINVER} instead of mp3gain2, metaflac and vorbisgain."
fi

# check if bpm-calc installed
BPMCALC=true
#command -v bpm-calc >/dev/null 2>&1 || { echo >&2 "$me requires \"bpm-calc\" but it's not installed. Aborting."; exit 2; }
command -v bpm-calc >/dev/null 2>&1 || BPMCALC=false
if [ "$BPMCALC" != true ] ; then
  echo "$me: No 'bpm-calc' found, BPM calculation will be skipped!"
fi

# option handling

usage() {
cat <<EOF
Usage: ${me} [OPTIONS] FOLDER ...

$me assumes one music album per folder, all tracks of the same file type.
It will then traverse from (and including) the starting folder(s) to all
folders below and add the recommended replay gain track & album tags to
audio files.

If using 'loudgain', $me currently supports files of type:
  *.flac, *.ogg, *.mp2, *.mp3, *.m4a, *.opus, *.asf, *.wma, *.wav, *.wv, *.aiff, *.ape
EOF
if [ "$BPMCALC" = true ] ; then
cat <<EOF

BPM calculation (and tagging) can be done for files of type:
  *.mp2, *.mp3, *.flac
EOF
fi
cat <<EOF

Options:
  -h  Show this help.
  -v  Show version number of this script.
  -b  Disable BPM calculation (and tagging).
EOF
}

while getopts "bhv" option ; do
  case "${option}" in
    v)
      echo "$me $version"
      exit 0;
      ;;
    h)
      usage
      exit 0;
      ;;
    b)
      if [ "$BPMCALC" = true ] ; then
        echo "$me: BPM calculation (and tagging) disabled"
        BPMCALC=false
      fi
      ;;
    *)
      exit 1;
      ;;
  esac
done
shift $((OPTIND-1))

# default to MUSICDIR if no path(s) given
if [ "$1" = "" ] ; then
  # (re-)set arguments
  set -- "${@}" "$MUSICDIR"
fi

if [ -z "$1" ] ; then
  usage
  exit 1;
fi

# go process each path
while [ "$1" != '' ] ; do

  # build an array with all folders within $1
  # need to change IFS (internal field separator), otherwise content would be split by space, tab, newline
  IFS=$'\n'
  FOLDERLIST=( $(find "$1" -depth -type d -print0 | xargs -0 -I{} echo {}) )
  unset $IFS
  echo "${#FOLDERLIST[@]} folders found in $1"

  for FOLDER in ${FOLDERLIST[@]} ; do
    echo ""
    echo "Working on $FOLDER ..."

    # calculate replay gain for all FLAC in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.flac" -type f -exec loudgain -a -k -s e {} +
    else
      find "$FOLDER" -maxdepth 1 -iname "*.flac" -type f -exec metaflac --add-replay-gain {} +
    fi

    # calculate replay gain for all Ogg Vorbis in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.ogg" -type f -exec loudgain -a -k -s e {} +
    else
      find "$FOLDER" -maxdepth 1 -iname "*.ogg" -type f -exec vorbisgain -a {} +
    fi

    # calculate replay gain for all Ogg FLAC in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.oga" -type f -exec loudgain -a -k -s e {} +
    else
      find "$FOLDER" -maxdepth 1 -iname "*.oga" -type f -exec vorbisgain -a {} +
    fi

    # calculate replay gain for all Ogg Speex in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.spx" -type f -exec loudgain -a -k -s e {} +
    fi

    # calculate replay gain for all Ogg Opus in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.opus" -type f -exec loudgain -a -k -s e {} +
    fi

    # calculate replay gain for all MP2 in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.mp2" -type f -exec loudgain -I3 -S -L -a -k -s e {} +
    fi

    # calculate replay gain for all MP3 in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.mp3" -type f -exec loudgain -I3 -S -L -a -k -s e {} +
    else
      find "$FOLDER" -maxdepth 1 -iname "*.mp3" -type f -exec mp3gain2 {} +
    fi

    # calculate replay gain for all M4A in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.m4a" -type f -exec loudgain -L -a -k -s e {} +
    fi

    # calculate replay gain for all WMA in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.wma" -type f -exec loudgain -L -a -k -s e {} +
    fi

    # calculate replay gain for all ASF in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.asf" -type f -exec loudgain -L -a -k -s e {} +
    fi

    # calculate replay gain for all WAV in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.wav" -type f -exec loudgain -I3 -L -a -k -s e {} +
    fi

    # calculate replay gain for all AIFF in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.aiff" -type f -exec loudgain -I3 -L -a -k -s e {} +
    fi

    # calculate replay gain for all AIF in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.aif" -type f -exec loudgain -I3 -L -a -k -s e {} +
    fi

    # calculate replay gain for all WavPack in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.wv" -type f -exec loudgain -S -a -k -s e {} +
    fi

    # calculate replay gain for all APE in this folder
    if [ "$LOUDGAIN" = true ] ; then
      find "$FOLDER" -maxdepth 1 -iname "*.ape" -type f -exec loudgain -S -a -k -s e {} +
    fi

    # calculate BPM for all MP2, MP3 or FLAC in this folder
    echo ""
    if [ "$BPMCALC" = true ] ; then
      find "$FOLDER" -maxdepth 1 -type f \( -iname "*.mp2" -or -iname "*.mp3" -or -iname "*.flac" \) -exec bpm-calc {} +
    else
      echo "Skipping BPM calculation ..."
    fi
  done

  shift
done
