I prefer to let computers do the dull work, so starting from flolilo's answer, I ended up with:
ffmpeg -i is_this_stereo.wav -filter_complex 'pan=mono|c0=0.5*FL+-0.5*FR,silenceremove=start_periods=1:detection=peak:window=0' -f null -
This shows a warning "Output file is empty, nothing was encoded" if the input file's channels are exact replicas (which they are for at least one of my CDs). You could relax the silenceremove filter to ignore some noise, for instance silenceremove=start_periods=1:start_threshold=0.02 or start_threshold=-17dB, but that relative amplitude is relative to the PCM capability, not relative to the recording level. For some of my CDs, this value filters out subtle but quite audible stereo; for others, it's about the minimum.
The -f null - part simply suppresses file output, in case the console message is enough, but of course you can let it write the difference file. To check the mono-ness in a script, the best I come up with is:
out=$(ffmpeg -nostdin -loglevel error -i "$infile" -filter_complex 'pan=mono|c0=0.5*FL+-0.5*FR,silenceremove=start_periods=1:detection=peak:window=0' -t 0.00002 -f crc -)
if [ "$out" == 'CRC=0x00000001' ]
then echo "$infile is definitely mono"
fi
In that script fragment:
- Time limit
-t 0.00002 cuts the difference emitted down to a single sample (for standard CD contents at 44,100 samples/second), which greatly speeds up the inspection of stereo files. -frames 1 results in the same, on my system, but I'm not sure it's supposed to because a frame contains more than one sample.
-f crc writes the output as something ASCII, which is way easier to handle in a script. If one 16 bit sample makes it through the silence remover, the 32 bit CRC has to change from its initial value of 1, I think. Could also use -f md5 or -f hash.
- Assigning
out separately, instead of invoking it inside the test expression, ensures that the script stops on error if you use the shell's -e option.