I think the thing to take away is: Don't use 'ls' for this purpose. I might have said that before ;-)

One way to debug your problem (should you feel that avoiding 'ls' is not enough) might be this:

1. Create a function to display the arguments:

_ffmpeg() { printf "ffmpeg %s %s %sn" "${@}"; }

2. Run your pipeline thus:

ls *.mp3|while read i;do _ffmpeg -i "${i}" "${i}.wav" 2&gt;&amp;1;done

I tested things like this:

$ cd /tmp
$ touch {a..f}.mp3
$ ls *.mp3|while read i;do _ffmpeg -i "${i}" "${i}.wav" 2&gt;&amp;1;done
ffmpeg -i a.mp3 a.mp3.wav
ffmpeg -i b.mp3 b.mp3.wav
ffmpeg -i c.mp3 c.mp3.wav
ffmpeg -i d.mp3 d.mp3.wav
ffmpeg -i e.mp3 e.mp3.wav
ffmpeg -i f.mp3 f.mp3.wav

The names like 'a.mp3' are all coloured blue.

If I use the real 'ffmpeg' I get (output heavily truncated with only one file shown):

ffmpeg version 4.0.2-2 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 8 (Debian 8.2.0-7)
  configuration: --prefix=/usr --extra-version=2 --toolchain=hardened 

[snip]

  libswresample   3.  1.100 /  3.  1.100
  libpostproc    55.  1.100 / 55.  1.100
?[0m?[00;36ma.mp3?[0m: No such file or directory

The codes before and after 'a.mp3' are colour on/off codes.

Your environment will certainly be different of course, so your failures may not be the same.

Clear?