First post, by Akuma
BIN/CUE to ISO/CUE converter v1.09, supports : FLAC,MP3,OGG,OPUS
Copyright (c) 2020 by Akuma under GNU General Public License 2.0
Features:
*Converts BIN/CUE to ISO/WAV
*Encodes WAV to FLAC,MP3,OGG,OPUS
*Parallel Encoding (credit krcroft)
*Presets and presetfiles
*Writes a new CUE sheet
*Skips existing files
*Dependency checks
Step 1. The script will first use bchunk to convert BIN/CUE to
ISO/WAV. Files will be placed in a newly created folder with the
basename of the CUE file. So for /my/games/mygame.cue it will be
placed in: /my/games/mygame.
The bchunk process is logged to:
/my/games/mygame/bchunk.log
Step 2. Then it encodes all WAV files with the preset to:
/my/games/mygame/[preset]/trackXX.[codec] (XX=02-99)
The encoding process is logged to:
/my/games/mygame/[preset]/trackXX.log
Step 3. A CUE sheet is created for the new files and is
written to the [preset] folder: /my/games/mygame/[preset]/cdrom.cue
Step 4. A batch file is created to use with DOSBox
written to the [preset] folder: /my/games/mygame/[preset]/cdrom.bat
Usage:
usage: dbx-conv [-f] [-s] <cue/cdrom> <preset/file> [options]
eg:
dbx-conv myfile.cue ogg (default preset)
dbx-conv myfile.cue opus_music_simple_mono (advanced preset)
dbx-conv myfile.cue myfile.preset (preset file)
dbx-conv myfile.cue mp3 -b 192 (custom mp3)
(optional)
* -f : force overwrite
(optional) binchunker:
* -s : swap byte order in audio tracks
codecs/default presets:
* flac
* mp3
* ogg
* opus
advanced presets: (mp3/ogg/opus)
* <codec>_music_simple_mono
* <codec>_music_simple_stereo
* <codec>_music_moderate_mono
* <codec>_music_moderate_stereo
* <codec>_music_complex_mono
* <codec>_music_complex_stereo
* <codec>_speech_simple_mono
* <codec>_speech_simple_stereo
* <codec>_speech_moderate_mono
* <codec>_speech_moderate_stereo
* <codec>_speech_complex_mono
* <codec>_speech_complex_stereo
* <codec>_filler_simple_mono
* <codec>_filler_simple_stereo
* <codec>_filler_moderate_mono
* <codec>_filler_moderate_stereo
* <codec>_filler_complex_mono
* <codec>_filler_complex_stereo
available presets: (flac)
* flac_max
options:
* codec options passthrough
(see codec manpage/manual)
#!/bin/bash# BIN/CUE to ISO/CUE converter v$version, supports : FLAC,MP3,OGG,OPUS"# Copyright (c) 2020 by Akuma under GNU General Public License 2.0"#[spdx-license-identifier]-----------------------------------------------------# GPL-2.0-only @ https://spdx.org/licenses/GPL-2.0-only.html#[dependencies]----------------------------------------------------------------# bchunk cdrdao flac lame opus-tools vorbis-tools## *BinChunker (CUE/WAV) http://he.fi/bchunk/# *CdrDao (CUE/BIN) http://cdrdao.sourceforge.net/# *Free Lossless Audio Codec (FLAC) https://xiph.org/flac/# *The LAME Project Codec (MP3) https://lame.sourceforge.io/# *The Ogg container Codec (OGG) https://xiph.org/ogg/# *Opus Interactive Audio Codec (OPUS) https://opus-codec.org/##[versioning]------------------------------------------------------------------version=1.09self="$(readlink -f "$0")"#[global settings]-------------------------------------------------------------set -euo pipefailOLDIFS=$IFS;IFS=$'\t\r\n' #\r for WIN/DOS cue-filestrap "result" 0 1 3 15#[functions]-------------------------------------------------------------------result(){case $? in0) echo -e "\nSuccess";;100) usage;;101) echo "error: '$file' file not found";;102) echo "error: unknown preset '${preset}'";;103) echo "error: already in ISO format";;104) echo "error: no audio tracks found";;105) echo "error: merge files to a single bin/cue first";;106) echo "error: '$file' dependency not found";;107) echo "error: encoding failed, see logs";;108) echo "error: cdrom.bin/cue already exist";;109) echo "error: cdrdao failed to image cdrom";;110) echo "error: toc2cue failed to convert toc-file to cue-file'";;111) echo "presetfile: error, tracknumber out of range '$track'";;112) echo -e "presetfile: '$presetfile'\nerror: unknown preset '$preset'";;esacechoIFS=$OLDIFS}usage(){ cat <<EOFusage: dbx-conv [-f] [-s] <cue/cdrom> <preset/file> [options]eg:dbx-conv myfile.cue ogg (default preset)dbx-conv myfile.cue opus_music_simple_mono (advanced preset)dbx-conv myfile.cue myfile.preset (preset file)dbx-conv myfile.cue mp3 -b 192 (custom mp3)
(optional)* -f : force overwrite(optional) binchunker:* -s : swap byte order in audio trackscodecs/default presets:* flac* mp3* ogg* opusadvanced presets: (mp3/ogg/opus)* <codec>_music_simple_mono* <codec>_music_simple_stereo* <codec>_music_moderate_mono* <codec>_music_moderate_stereo* <codec>_music_complex_mono* <codec>_music_complex_stereo* <codec>_speech_simple_mono* <codec>_speech_simple_stereo* <codec>_speech_moderate_mono* <codec>_speech_moderate_stereo* <codec>_speech_complex_mono* <codec>_speech_complex_stereo* <codec>_filler_simple_mono* <codec>_filler_simple_stereo* <codec>_filler_moderate_mono* <codec>_filler_moderate_stereo* <codec>_filler_complex_mono* <codec>_filler_complex_stereoavailable presets: (flac)* flac_maxoptions:* codec options passthrough(see codec manpage/manual)EOF}checkfile(){ file="$1";[[ -f "$file" ]] || exit 101;}getbin(){ grep -Po '.*?"\K[^"]+(?=")' "$1";}checkapp(){ file="$1";command -v "$file" >/dev/null 2>&1 || exit 104;}dumpcdrom(){workdir="$PWD"bin="$workdir/cdrom.bin"cue="${bin%.*}.cue"local cdrom="$1" toc="${bin%.*}.toc" log="${bin%.*}.log"[[ -f "$bin" ]] && exit 108echo " *Dumping: \"$cdrom\" to BIN/TOC/CUE"if [[ -f "$bin" && "$overwrite" = "false" ]]; thencheckapp "cdrdao"[[ "$overwrite" = "true" ]] && echo " ! overwrite enabled"echo " > ${bin##*/}"cdrdao read-cd --datafile "$bin" --driver generic-mmc:0x20000\--device "$cdrom" --read-raw "$toc" >"$log" 2>&1 || exit 109elseecho " - ${bin##*/} exists"fiif [[ -f "$cue" && "$overwrite" = "false" ]]; thencheckapp "toc2cue"[[ "$overwrite" = "true" ]] && echo " ! overwrite enabled"echo " > ${cue##*/}"toc2cue "$toc" "$cue" || exit 110elseecho " - ${cue##*/} exists"fi}range(){ seq ${1%-*} ${1#*-};}queue(){local workdir="$1" outdir="$2" codec="$3"shift 3local options=$@local codec options infile outfile trackfor infile in "$workdir"/*.wav;dooutfile="${infile##*/}";outfile="$outdir/${outfile%.*}.$codec"track="${infile##*/}";track="${track:5:2}"queue+=([10#$track]="compress \"$infile\" \"$outfile\" $codec $options")done}queue_presetfile(){local workdir="$1" outdir="$2" presetfile="$3" que="$4"local codec options infile outfile track tracks saveifssaveifs=$IFStotal=$(grep -c TRACK "$que")while read line;doIFS='=';set -- $linepreset=${1:-}grep -q "^$preset=" "$presets" || exit 112codec=${1:-};codec=${codec/_*}options=${!1:-}tracks=${2:-}IFS=$' \t\r\n'tracks=$(for track in $tracksdo case $track indefault) range 2-$total;; #fill queue with the default preset*-*) range $track;; #change preset for range eg: 12-20[0-9]*) echo $track;; #change preset per track eg: 13*) exit 130;; #presetfile script erroresacdone)for track in $tracks;do[[ $track -ge 2 && $track -le $total ]] || exit 111infile=$(printf "$workdir/track%02i.wav" $track)outfile=$(printf "$outdir/track%02i.$codec" $track)queue+=([$track]="compress \"$infile\" \"$outfile\" $codec $options")donedone < <(grep '^[^#].*=' "$presetfile") #grep presets from presetfileIFS=$saveifs}compress(){ #infile outfile codec optionslocal infile="$1" outfile="$2" codec=$3; shift 3; options=$@local log="${outfile%.*}.log"trap "rm \"$outfile\";exit 106" 2IFS=$' \t\r\n'case "$codec" inflac) set flac $options "$infile" -o "$outfile";;ogg) set oggenc $options "$infile" -o "$outfile";;opus) set opusenc $options "$infile" "$outfile";;mp3) set lame $options "$infile" "$outfile";;esacIFS=$'\t\r\n'checkapp $1echo $@ >"$log"; $@ >>"$log" 2>&1 || exit 112;}to_frames(){ set ${1//:/ }; echo $(((60*10#$1+10#$2)*75+10#$3));}to_time(){\printf "%02d:%02d:%02d" $(((10#$1/75)/60)) $(((10#$1/75)%60)) $((10#$1%75));}makecue(){ #cue outdirlocal cue="$1" outdir="$2" line file type c zero offset timeIFS=$' \t\r\n'while read line;doset $linecase "$1" inFILE)unset offset #reset offset on new file;;TRACK)c=$(printf "%02d" $((10#$2)))for file in "$outdir"/track$c.*;docase "${file##*.}" iniso) type=BINARY;;mp3|ogg|flac|opus) type=${file##*.};type="${type^^}";;*) unset type zero;; #reset index zero on new trackesac[[ -n "${type:=}" ]] && {printf "FILE \"${file##*/}\" $type\n"printf "${line/MODE*/MODE1\/2048}\n"}done;;INDEX)time="00:00:00"[[ -n "${zero:=}" ]] && {offset="$(to_frames $3)"time="$(to_time $((offset-zero)))"}[[ $2 -eq 0 ]] && zero="$(to_frames $3)"printf "${line/??:??:??/$time}\n";;*)printf "$line\n";;esacdone < <(cat "$cue")IFS=$'\t\r\n'}#[title]-----------------------------------------------------------------------echo "BIN/CUE to ISO/CUE converter v$version, supports : FLAC,MP3,OGG,OPUS"echo "Copyright (c) 2020 by Akuma under GNU General Public License 2.0"echo#[codec presets]---------------------------------------------------------------presets="${self%.*}.presets"checkfile "$presets"source "$presets"#[commandline arguments]-------------------------------------------------------#usage: self [-f] [-s] cue-file preset/presetfile/codec [codec-options]#optionsbyteswap=""overwrite=falsewhile :; docase ${1:-} in-f) overwrite="true";; #set overwrite flag-s) byteswap="-s";; #bchunk: swap byteorder in audiotracks*) break;;esacshiftdone#2+ arguments remaining else show usage[[ $# -ge 2 ]] || exit 100#if cdrom then create bin/cue and set cueif [[ -b "$1" ]]; thendumpcdromelsecue="$(readlink -f "$1")"fi#check cue-filecheckfile "$cue"grep -q 'MODE2/2048' "$cue" && exit 103grep -q 'TRACK.*AUDIO' "$cue" || exit 104[[ $(grep -c 'FILE' "$cue") -eq 1 ]] || exit 105bin="${cue%/*}/$(getbin $cue)"checkfile "$bin"shift#[workdir]---------------------------------------------------------------------workdir="${cue%.*}"[[ -d "$workdir" ]] || mkdir -p "$workdir"#[queue]-----------------------------------------------------------------------case $# in0) exit 100;;1) if [[ -f "$1" ]]; thenpresetfile="$(readlink -f $1)"checkfile "$presetfile"outdir="$workdir/presetfile"queue_presetfile "$workdir" "$outdir" "$presetfile" "$cue"encoding="${presetfile##*/}"elsepreset="${1,,}"grep -q "^$preset=" "$presets" || exit 102outdir="$workdir/$preset"codec="${preset/_*}"options="${!preset}"queue "$workdir" "$outdir" "$codec" "$options"encoding="$preset"fi;;*) outdir="$workdir/custom"queue "$workdir" "$outdir" $@encoding="CUSTOM: $@";;esac[[ -d "$outdir" ]] || mkdir -p "$outdir"set --#[conversion]------------------------------------------------------------------cd "$workdir"echo " *Converting BIN/CUE to ISO/WAV"outfile="$workdir/track01.iso"if [[ -f "$outfile" ]]; thenecho " - ${outfile##*/} exists"elseecho " > ${outfile##*/}"checkapp bchunk[[ -n "${byteswap:-}" ]] && echo " > swapping byte order in audio tracks"bchunk $byteswap -w "$bin" "$cue" track >> "bchunk.log" 2>&1fisymlink="$outdir/${outfile##*/}"[[ -h "$symlink" ]] || ln -s "../${outfile##*/}" "$symlink" >/dev/null 2>&1[[ -f "${outfile%.*}.ugh" ]] && mv "${outfile%.*}.ugh" "${outfile}"#[encoding]--------------------------------------------------------------------echo " *Encoding WAV with: \"$encoding\""[[ -d "$outdir" ]] || mkdir -p "$outdir"[[ "$overwrite" = "true" ]] && echo " ! overwrite enabled"nproc="$(nproc)"for command in "${!queue[@]}"; doIFS='"';set -- ${queue[$command]}outfile="$4";IFS=$' \t\r\n'if [[ -f "$outfile" && "$overwrite" = "false" ]]; thenecho " - ${outfile##*/} exists";continueelseecho " > ${outfile##*/}"( set -e; eval ${queue[$command]} ) &[[ $? -eq 0 ]] || exit 107while [[ "$(jobs -p | wc -l)" -gt "$nproc" ]]; do sleep 0.3; donefidone#[cuesheet]--------------------------------------------------------------------echo " *Writing CUE sheet"outfile="$outdir/cdrom.cue"[[ -f "$outfile" ]] && rm "$outfile"if [[ -f "$outfile" ]]; thenecho " - ${outfile##*/} exists"elseecho " > ${outfile##*/}"makecue "$cue" "$outdir" >"$outfile"fi#[cdrom.bat]-------------------------------------------------------------------echo " *Writing BAT file"outfile="$outdir/cdrom.bat"if [[ -f "$outfile" ]]; thenecho " - ${outfile##*/} exists"elseecho " > ${outfile##*/}"echo imgmount d -t cdrom cdrom.cue >"$outfile"fiexit 0
# BIN/CUE to ISO/CUE converter v$version, supports : FLAC,MP3,OGG,OPUS# Copyright (c) 2020 by Akuma & krcroft under GNU General Public License 2.0# This preset file can be customized to your needs#FLAC: (flac 1.3.3-1 libflac8 1.3.3-1)# flac <preset> "$infile" -o "$outfile"flac="-8 -b 512 -P=4096 -S=1s"flac_max="-8 -e -p -b 512 -P=4096 -S=1s"#OGG: (vorbis-tools 1.4.0-11, libogg0 1.3.4-0)# oggenc <preset> "$infile" -o "$outfile"ogg=""ogg_speech_simple_mono="--advanced-encode-option lowpass_frequency=13000 --bitrate 44 --downmix"ogg_speech_moderate_mono="--advanced-encode-option lowpass_frequency=14000 --bitrate 50 --downmix"ogg_speech_complex_mono="--advanced-encode-option lowpass_frequency=16000 --bitrate 52 --downmix"ogg_speech_simple_stereo="--advanced-encode-option lowpass_frequency=13000 --bitrate 50"ogg_speech_moderate_stereo="--advanced-encode-option lowpass_frequency=14000 --bitrate 56"ogg_speech_complex_stereo="--advanced-encode-option lowpass_frequency=16000 --quality 1.4"ogg_music_simple_mono="--quality 2.2 --downmix"ogg_music_moderate_mono="--quality 2.3 --downmix"ogg_music_complex_mono="--quality 2.5 --downmix"ogg_music_simple_stereo="--quality 3.5"ogg_music_moderate_stereo="--quality 4.3"ogg_music_complex_stereo="--quality 5.0"ogg_filler_simple_mono="--quality -1 --resample 512 --downmix"ogg_filler_moderate_mono="--quality -1 --resample 512 --downmix"ogg_filler_complex_mono="--quality -1 --resample 512 --downmix"ogg_filler_simple_stereo="--quality -1 --resample 512 --downmix"ogg_filler_moderate_stereo="--quality -1 --resample 512 --downmix"ogg_filler_complex_stereo="--quality -1 --resample 512 --downmix"#Opus: (opus-tools 0.1.10-1 libopus0 1.3.1-0)# opusenc <preset> "$infile" "$outfile"opus=""opus_speech_simple_mono="--bitrate 24 --downmix-mono"opus_speech_moderate_mono="--bitrate 28 --downmix-mono"opus_speech_complex_mono="--bitrate 36 --downmix-mono"opus_speech_simple_stereo="--bitrate 32"opus_speech_moderate_stereo="--bitrate 36"opus_speech_complex_stereo="--bitrate 40"opus_music_simple_mono="--bitrate 50 --downmix-mono"opus_music_moderate_mono="--bitrate 56 --downmix-mono"opus_music_complex_mono="--bitrate 72 --downmix-mono"opus_music_simple_stereo="--bitrate 72"opus_music_moderate_stereo="--bitrate 84"opus_music_complex_stereo="--bitrate 96"opus_filler_simple_mono="--bitrate 1 --downmix-mono"opus_filler_moderate_mono="--bitrate 1 --downmix-mono"opus_filler_complex_mono="--bitrate 1 --downmix-mono"opus_filler_simple_stereo="--bitrate 1 --downmix-mono"opus_filler_moderate_stereo="--bitrate 1 --downmix-mono"opus_filler_complex_stereo="--bitrate 1 --downmix-mono"#Mp3: (lame 3.100-3 libmp3lame0 3.100-3)# lame <preset> "$infile" "$outfile"mp3="-q0 -b4 -T"mp3_speech_simple_mono="-V7.0 --lowpass 13000 -mm -q0 -b4 -T"mp3_speech_moderate_mono="-V6.5 --lowpass 14000 -mm -q0 -b4 -T"mp3_speech_complex_mono="-V6.3 --lowpass 15000 -mm -q0 -b4 -T"
mp3_speech_simple_stereo="-V6.0 --lowpass 13000 -q0 -b4 -T"mp3_speech_moderate_stereo="-V5.7 --lowpass 15000 -q0 -b4 -T"mp3_speech_complex_stereo="-V5.5 --lowpass 16000 -q0 -b4 -T"mp3_music_simple_mono="-V6.0 -mm -q0 -b4 -T"mp3_music_moderate_mono="-V5.5 -mm -q0 -b4 -T"mp3_music_complex_mono="-V5.0 -mm -q0 -b4 -T"mp3_music_simple_stereo="-V4.5 -q0 -b4 -T"mp3_music_moderate_stereo="-V3.5 -q0 -b4 -T"mp3_music_complex_stereo="-V2.5 -q0 -b4 -T"mp3_filler_simple_mono="-mm -q0 -b4 -T"mp3_filler_moderate_mono="-mm -q0 -b4 -T"mp3_filler_complex_mono="-mm -q0 -b4 -T"mp3_filler_simple_stereo="-mm -q0 -b4 -T"mp3_filler_moderate_stereo="-mm -q0 -b4 -T"mp3_filler_complex_stereo="-mm -q0 -b4 -T"
# PRESET: example file## comment with ## empty lines allowed# preset=tracknumbers# set default for all filesopus_music_moderate_stereo=default# set rangesmp3_speech_simple_mono=19-61# set individual filesogg_music_moderate_mono=21opus_music_complex_stereo=20 23 27
History:
2020-11-02 1.09 Completely rewritten
2020-10-27 1.08 Added presets file *not released*
2020-10-25 1.07 Implemented parallel encoding + bugfixes
2020-10-22 1.06 First public release version
Changelog:
1.09 Fixed: Completely rewritten (to use a queue)
Added: cdrdao support *buggy*
Added: cdrom.preset file with:
|- multi codec support
|- multi preset support
`- per track support
1.08 Added: presets file, customizable by user
Fixed: commandline options
Added: (suggestions by krcroft)
|- Bash strict-mode
|- Mono option for mono audio to save diskspace
|- Speech option (Jones in the Fast Lane only has voices).
|- variable-bit-rate encodings as a default
`- filler option (unused space at lowest bitrate and in mono)
1.07 Added: (suggestions by krcroft)
|- Bash strict-mode without 'u'
|- Removed unneeded usage text brackets.
|- Options in usage elaborated
|- Renamed 'track.cue' to 'cdrom.cue'
|- Parallel Encoding
|- Double-bracket tests
`- FLAC seekpoints to reduce CPU load
1.06 Fixed: Recalculation defaults to octal instead of decimal
1.05 Added: Index time recalculation
1.04 Added: Parsing CUE sheet instead of generating it
1.03 Added: Set basename to fixed "track" instead of dynamic
1.02 Added: CTRL-C trap and resume
1.01 Added: Codec support for OGG/FLAC/OPUS
1.00 Draft: Initial draft with MP3 and BCHUNK
Dependencies:
*bin/cue to iso/wav : bchunk
*flac encoder : flac
*mp3 encoder : lame
*opus encoder : opus-tools
*ogg encoder : vorbis-tools
*cdripper : cdrdao
** It is probably still a bit buggy, so beware **