Skip to content

Instantly share code, notes, and snippets.

@arrjay
Last active December 27, 2021 20:10
Show Gist options
  • Select an option

  • Save arrjay/3837fb1eca6d87f61d54741f9cf93a8d to your computer and use it in GitHub Desktop.

Select an option

Save arrjay/3837fb1eca6d87f61d54741f9cf93a8d to your computer and use it in GitHub Desktop.
okay, linux script to wrangle files so I can dump them on m-crew
#!/usr/bin/env bash
#set -x
scratchfolder="$(mktemp -d)"
# initially, we created two passes for mono v stereo.
# this proved to be a pain in the ass to keep straight.
# so...everything on the disc is mono.
#mkdir -p "${scratchfolder}/stereo"
#mkdir -p "${scratchfolder}/mono"
# get the song time and truncate it
get_trktime () {
local trktime
trktime="$(ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "${1}" 2>/dev/null)"
printf '%s\n' "${trktime}"
}
# this is fed into bc...
DISCEXP='0'
get_disctime () {
echo "${DISCEXP}+0" | bc
}
add_disctime () {
local time="${1}"
DISCEXP="${DISCEXP}+${time}"
}
# pick files in random order
sources=(${HOME}/Downloads/Season\ */*)
# okay, we *always* start with this track
songs=("${HOME}/Downloads/Nokia 3310 - Classic Monophonic RINGTONE (2017).mp4")
add_disctime "$(get_trktime "${songs[0]}")"
# now walk through our sources array and do something
selections=()
maxct="${#sources[@]}"
pad="${#maxct}"
while true ; do
# are we out of time? 4200 is 70 minutes in seconds.
dtime=$(get_disctime)
dtime="${dtime%.*}"
[[ "${dtime}" -gt 4200 ]] && break
# have we chosen 254 tracks?
[[ "${#songs[@]}" -ge 254 ]] && break
# have we chosen all the possible songs?
[[ ${#selections[@]} -ge ${#sources[@]} ]] && break
# pick a random track we have not played before.
select=false
while [[ "${select}" == "false" ]] ; do
chosen=$(($RANDOM % ${#sources[@]}))
selected=$(printf "%0${pad}d" "${chosen}")
case "${selections[*]}" in
*" ${selected} "*) : ;;
*) select=true ;;
esac
done
selections=("${selections[@]}" "${selected}")
# is the song between 4 and 23 seconds? (mcrew needs 6sec and we will _get_ there...)
songtime=0
songtime=$(get_trktime "${sources[${chosen}]}")
[[ "${songtime%.*}" -le 23 ]] || continue
[[ "${songtime%.*}" -ge 4 ]] || continue
# does the song only differ in extension?
case "${songs[*]}" in
*" ${sources[${chosen}]%.*}"*) continue ;;
esac
# add to disc timing, add to song list.
add_disctime "${songtime}"
songs=("${songs[@]}" "${sources[${chosen}]}")
done
# process the selected songs...
titles=("BANGRS${1}") # add the disc title
songct="${#songs[@]}"
printf '#EXTM3U: TITLE=%s%s TRACKS=%s\n' 'BANGRS' "${1}" "${songct}" > "${scratchfolder}/BANGRS${1}.M3U"
destpad="${#songct}"
# note this is pulling out indexes
for index in "${!songs[@]}" ; do
file="${songs[${index}]}"
# first, figure out a workable title. we're limiting to 7 characters...
title="$(basename "${file}")"
# remove extension and the first word (prefix)
title="${title%.*}"
title="${title#* }"
# uppercase everything
title="${title^^}"
# remove all spaces
title="${title// /}"
# remove years from the end
title="${title%([0-9][0-9][0-9][0-9])}"
# remove any dashes, parens et al.
title="${title//[()-.]/}"
# grab the last 7 characters...
title="${title: -7}"
titleidx=1
while true ; do
# handle pathological file titles
[[ "${titleidx}" -gt 36 ]] && exit 1
case "${titles[*]}" in
*" ${title} "*) : ;;
*) break ;;
esac
# grab the first 5 and do ~X appending
title="${title:0:5}"
# steal the _last_ character of bc output.
idxb36="$(bc <<< "obase=36; ${titleidx}")"
title="${title}~${idxb36: -1}"
# up and again (if we run again)
((titleidx++))
done
# add title to pool of used title names, update playlist
titles=("${titles[@]}" "${title}")
printf '#EXTINF:0, original="%s" %s\n' "${file#${HOME}/}" "${title}"
# decode the file.
ffmpeg -y -i "${file}" "${scratchfolder}/dec.wav" < /dev/null
# we're getting the length and channel config here.
channels="$(soxi -c "${scratchfolder}/dec.wav")"
case "${channels}" in
1) chtext='mono' ;;
*) chtext='stereo' ;;
esac
rate="$(soxi -r "${scratchfolder}/dec.wav")"
samples="$(soxi -s "${scratchfolder}/dec.wav")"
runlength="$((rate * 6))"
destfile="$(printf "%0${destpad}d_${chtext}" "$((index + 1))").WAV"
# PCLK-MN10A manual, page 50.
printf '%s\n' "${title}" >> "${scratchfolder}/TITLES.TXT"
# pad to six seconds if needed
if [[ "${samples}" -lt "${runlength}" ]] ; then
padding="$((runlength - samples))"
sox "${scratchfolder}/dec.wav" "${scratchfolder}/${destfile}" pad 0 "${padding}"s
rm "${scratchfolder}/dec.wav"
else
mv "${scratchfolder}/dec.wav" "${scratchfolder}/${destfile}"
fi
printf '%s\n' "${destfile}"
done >> "${scratchfolder}/BANGRS${1}.M3U"
# convert the title files, m3u to windows/dos format.
for expdir in mono stereo '' ; do
[[ -f "${scratchfolder}/${expdir}/TITLES.TXT" ]] && unix2dos "${scratchfolder}/${expdir}/TITLES.TXT"
done
unix2dos "${scratchfolder}/BANGRS${1}.M3U"
# copy the running file to the scratch folder too
cp "$0" "${scratchfolder}/$(basename "${0}")"
# compress scratch into a zip
here="$(pwd)"
( cd "${scratchfolder}" && zip -r "${here}/BANGRS${1}.ZIP" . )
# drop scratch
[[ "${scratchfolder}" != "/" ]] && {
rm -rf "${scratchfolder}"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment