1

I'm trying to use sox to resample a series of tracks that should be played back gaplessly. If I resample each track individually, I can sometimes end up with clicks at the track boundaries due to the individual resampling not quite lining up. The solution seems conceptually simple: concatenate all of the tracks, resample them as a single unit, and split them again. However, I'm not sure how to go about that in an automated fashion. The concatenation step is easy (just pass all the files to a single sox invocation) but how do I split the result again with the same durations as the original tracks?

1 Answer 1

0

I ended up making a script to handle this:

#!/usr/bin/env bash set -o errexit -o pipefail -o nounset # Can be changed to point to, e.g., a DSD-enabled SoX build. SOX="sox" TRACKS=() while [[ $# -gt 0 ]]; do case $1 in -b|--bits) # Use the specified number of bits-per-sample for the output BITS="$2" shift 2 ;; -o|--out) # Output template for resampled tracks OUT="$2" shift 2 ;; -r|--rate) # The sample rate of the output RATE="$2" shift 2 ;; -*|--*) echo "Unknown option $1" >&2 exit 1 ;; *) TRACKS+=("$1") # positional arg shift ;; esac done if [[ -z ${OUT+x} ]]; then echo "Option --out is required" >&2 exit 1 fi if [[ -z ${RATE+x} ]]; then echo "Option --rate is required" >&2 exit 1 fi if [[ ${#TRACKS[@]} -eq 0 ]]; then echo "No input files provided" >&2 exit 1 fi if [[ -n ${BITS+x} ]]; then BITS_ARG=(-b "$BITS") else BITS_ARG=() fi if [[ ${#TRACKS[@]} -eq 1 ]]; then TRIM_ARGS=() else # Get lengths of all tracks except the last one LENGTHS=($("$SOX" --i -D "${TRACKS[@]:0:${#TRACKS[@]}-1}")) TRIM_ARGS=(trim 0 "${LENGTHS[0]}" : newfile) for length in "${LENGTHS[@]:1}"; do TRIM_ARGS+=(: trim 0 "$length" : newfile) done fi # --guard resamples to a temporary file with added headroom, then writes the # output as close to the original level as possible without clipping. # Remove to write directly to the output files at the originally level, with the # possibility of some samples clipping if the input has insufficient headroom. "$SOX" --guard "${TRACKS[@]}" "${BITS_ARG[@]}" -t wav - rate -v "$RATE" | "$SOX" - "$OUT" "${TRIM_ARGS[@]}" 

Sample usage:

Resamples flac files to 48kHz with the same number of bits per sample (tags aren't copied):

$ resample.sh -o output.flac -r 48k ../96kHz/*.flac 

Convert DSD audio to 48kHz, 24-bit FLAC (requires DSD enabled SoX):

$ resample.sh -o output.flac -r 48k -b 24 ../DSD/*.dsf 

Output files will be named output001.flac, output002.flac, et cetera.

Adding additional options to the script (e.g., the ability to specify dither when creating 16-or-less-bit files) left as an exercise for the reader. 🙂

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.