Created
March 15, 2021 14:08
-
-
Save carlwilson/958e4c7945d6608781898c5ffb69f22e to your computer and use it in GitHub Desktop.
MUX shell script for Zaireeka
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# | |
# Script to mix multiple CDs (< 10) into all combinations (order considered unimportant). | |
# Mixing to a set of 2 channel mixes where all lefts are combined to the final left | |
# channel and all right channels are combined to the final right. | |
# | |
# While I've tried to make it reasonably forgiving failure to follow these rules | |
# may have unexpected results. | |
# | |
# CD Directory rules: | |
# - each ripped CD Directory must share a single parent dir. | |
# - only one disc number in each CD Directory name. | |
# - disc number can be any number above zero (64bit int limit?) | |
# - CD Directory names must consistently start OR end with their disc number | |
# NO digits in the middle, no mix and matching | |
# - NO duplicate disc numbers | |
# | |
# Track file rules: | |
# - all track files must share the same CD Diretory parent | |
# - files are mixed across all combinations of CD | |
# - NO duplicate track numbers | |
# - to be mixable track files must have the same sample rate, and format | |
# formats could vary between different tracks, but not across copies of the | |
# same track (matched by track number) | |
# - if mixed track files have different duration, result will truncate at the shortest | |
# | |
combine() { | |
# Create the combinations for mixing the discs | |
# Thanks to 'Nominal Animal' on Linux Questions | |
# Taken from https://www.linuxquestions.org/questions/programming-9/strings-combinations-945160/ | |
local limit=$[ 1 << $# ] | |
local args=("$@") | |
for ((value = 1; value < limit; value++)); do | |
local parts=() | |
for ((i = 0; i < $#; i++)); do | |
[ $[(1<<i) & value] -ne 0 ] && parts[${#parts[@]}]="${args[i]}" | |
done | |
# If we have combinations then mix the discs | |
if [ "${#parts[@]}" -gt 1 ]; then | |
mix_discs "${parts[@]}" | |
fi | |
done | |
} | |
mix_discs() { | |
# Perform the mixing from the combos | |
local args=("$@") | |
# Create combo disk number from the array parts | |
discno=`quick_join '' "$@"` | |
# Get the pre/post fix info and create the ouput directory name | |
discindex="${args[0]} - 1" | |
[[ "${fixtype[$discindex]}" =~ post ]] && primesrc=`echo "${args[0]}""${fixes[$discindex]}"` || primesrc=`echo "${fixes[$discindex]}""${args[0]}"` | |
[[ "${fixtype[$discindex]}" =~ post ]] && destdir=`echo "MUXED""${discno}""${fixes[$discindex]}"` || destdir=`echo "MUXED""${fixes[$discindex]}""${discno}"` | |
# Make the output dir if it doesn't exist | |
[[ -d $destdir ]] || mkdir "$destdir" | |
# Loop through the tracks and grab the track number | |
find "${primesrc}" -type f -print0 | while IFS= read -r -d '' track; do | |
# Grap the track number | |
trackname=${track##*/} | |
if [[ ${trackname} =~ ^[0-9] ]]; then | |
# Assume it's a track (it starts with a number | |
# Start building the ffmpeg command | |
local ffmpegcmd=(ffmpeg -i "${track}") | |
# grab the track number | |
trackno=`grep -o '^[0-9]\+' <<< ${trackname}` | |
for (( i=1; i<${#args[@]}; i++ )); | |
# Loop through the to be muxed directory entries | |
do | |
supdiscidx="${args[$i]} - 1" | |
[[ "${fixtype[$supdiscidx]}" =~ post ]] && suppsrc=`echo "${args[$i]}""${fixes[$supdiscidx]}"` || suppsrc=`echo "${fixes[$supdiscidx]}""${args[$i]}"` | |
suptrack=`ls ${suppsrc}/${trackno}*` | |
# If we find the track add the input file | |
ffmpegcmd+=(-i "${suptrack}") | |
done | |
# add input and filter stuff, keep it stereo for now | |
ffmpegcmd+=(-filter_complex amerge=inputs=${#args[@]} -ac 2 "${destdir}/${trackname}") | |
echo "${ffmpegcmd[@]}" | |
# Execute the ffmpeg command for this MUX | |
"${ffmpegcmd[@]}" < /dev/null | |
fi | |
done | |
} | |
# Quick efficient array join | |
# Courtesy of https://dev.to/meleu/how-to-join-array-elements-in-a-bash-script-303a | |
quick_join () { local IFS="$1"; shift; echo "$*"; } | |
# EXECUTION STARTS HERE | |
# Use param as root dir or use current directory if no param | |
rootdir="." | |
[[ ! -z "$1" ]] && rootdir=$1 | |
# Go to root, bail if it doesn't exist | |
cd $rootdir || exit | |
# Get the directory listing, looking for the individual disc dirs | |
dirs=(*) | |
for (( i=0; i<${#dirs[@]}; i++ )); | |
# Loop through directory entries | |
do | |
if [[ -d ${dirs[$i]} ]] && [[ ! ${dirs[$i]} =~ ^MUXED ]] && ([[ ${dirs[$i]} =~ ^[0-9] ]] || [[ ${dirs[$i]} =~ [0-9]$ ]]); then | |
# if it's a directory, it doesn't start with MUXED (previous output) and | |
# it's name starts or ends with a number, work out the prefix/postfix type | |
[[ ${dirs[$i]} =~ ^[0-9] ]] && fixtype[$i]="post" || fixtype[$i]="pre" | |
# Get the Disc number | |
cdnums[$i]=`grep -o '[0-9]\+' <<< ${dirs[$i]}` | |
# grab the pre/post fix value | |
fixes[$i]=`grep -o '[^0-9]\+' <<< ${dirs[$i]}` | |
fi | |
done | |
# Let the combination fun begin... | |
combine "${cdnums[@]}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment