Prepend title of mp3 file using `say`

Try this: Convert the target .mp3 also into the same format you're converting. Rewriting your steps with a few modifications and be-careful's:

mkdir -p backup/
mkdir -p working/
for file in ./*.mp3; do
    BASE="$(basename "$file" .mp3)"
    say "[[volm 0.4]] $BASE" -o "${BASE}-pre.aiff"
    ffmpeg -i "${BASE}-pre.aiff" -f mp3 -acodec libmp3lame -ab 192000 -ar 44100 "${BASE}-pre.mp3"
    ffmpeg -i "$file" -f mp3 -acodec libmp3lame -ab 192000 -ar 44100 "${BASE}-bak.mp3"
    rm "${BASE}-pre.aiff"
    mv "$file" backup/
    mp3cat -o "$file" "${BASE}-pre.mp3" "${BASE}-bak.mp3"
    mv "${BASE}-pre.mp3" working/
    mv "${BASE}-bak.mp3" working/
done

Modified your script to use ffmpeg. As always, backup your files before running the scripts to avoid losing data.

Option 1

Slower, will re-encode the files, but preserves metadata:

for file in ./*.mp3; do
    BASE="$(basename "$file" .mp3)"
    mv "${file}" "${BASE}-bak.mp3"
    say "[[volm 0.4]] ${BASE}" -o "${BASE}-pre.aiff"
    ffmpeg -i "${BASE}-pre.aiff" -f mp3 -acodec libmp3lame -ab 192000 -ar 44100 "${BASE}-pre.mp3"
    rm "${BASE}-pre.aiff"
    ffmpeg -i "${BASE}-pre.mp3" -i "${BASE}-bak.mp3" -filter_complex [0:a][1:a]concat=n=2:v=0:a=1 -map_metadata 1 "${file}"
    rm "${BASE}-pre.mp3"
done

Option 2:

Fast, no re-encoding, metadata will be lost:

for file in ./*.mp3; do
    BASE="$(basename "$file" .mp3)"
    mv "${file}" "${BASE}-bak.mp3"
    say "[[volm 0.4]] ${BASE}" -o "${BASE}-pre.aiff"
    ffmpeg -i "${BASE}-pre.aiff" -f mp3 -acodec libmp3lame -ab 192000 -ar 44100 "${BASE}-pre.mp3"
    rm "${BASE}-pre.aiff"
    echo "file '${BASE}-pre.mp3'" >temp
    echo "file '${BASE}-bak.mp3'" >>temp
    ffmpeg -f concat -safe 0 -i temp "${file}"
    rm "${BASE}-pre.mp3"
    rm temp
done

Either way the resulting files seem to work fine using QuickTime, and it plays the entire file properly.