How to sort audio files according to their cut-off frequency (real bitrate) in kHz?
I have some music collection and I want to sort/filter them easily according to their cut-off frequency (real bitrate, usually in kHz. I used to use Spek for showing me this information, but Spek doesn't provide any possibility to use it in terminal or for multiple files operations. I've already found some ways, but all of them just list bit-rate in which audio file is saved in kbps, not the actual cut-off frequency in kHz, which I need. I want to find a simple solution to filter the whole collection using e.g bash, python, existing simple tool, etc. Do you know any solution?
Clarification: I'm not looking for bitrate or sampling rate, I'm looking for frequency cut-off!
Solution 1:
I've been looking for something similar, since I'm trying to de-dupe a large music archive, would like to keep the highest quality files, but don't trust the bitrates used.
I've found fakeflac which seems like a good start. Don't let the name fool you, it's not FLAC-specific since it converts the given file to wav and operates on that using a Python script. It scans down the frequency spectrum until it finds the cutoff, based on a couple of heuristics (125% increase in magnitude across a 220 Hz range, with the lower magnitude no higher than 110% of that at 44100Hz).
It writes out a "score", which is how far up the frequency spectrum the cutoff appears (i.e. if the claimed frequency is 44100Hz but it cuts off at 22050Hz, the score will be 50).
I had to fiddle with it a little to make it work, e.g. I replaced sndfile-convert foo bar
with ffmpeg -i foo bar
, but it's very straightforward and seems to be just what I'm after.
You can use fakeflac
in a loop to get the scores for a collection of files, then sort them using standard shell tools (sort
, cut
, etc.).
Solution 2:
Not the most elegant of the solutions, has a few drawbacks, but here's what I got:
find . -type f -name "*.wav" -printf "***%p\n" -exec file {} \; | awk '/\*\*\*/{printf $0"|"};{gsub(/\,/,"");for(i=1;i<=NF;i++) if($i~/Hz/) printf " "$(i-1)"|"$i"\n" }' | sort --field-separator="|" --numeric -k 2
Basically, we use find
command to search for files with ".wav" extension, inside /my/audio/folder
. We print path to each file, padding it with three wildcard signs, and execute file
command on each one of them. The stdout
output goes through pipe to the lengthy awk
code, which reads each line; if the line has three asterisks - that's filename, print it; if a filed in a line contains Hz
in it, we print number before that field, and the field itself. Everything is printed in such manner so as to have output in format ***/path/to/file | number | (k)Hz
. Finally, the output is piped to sort command, which sorts numerically based on column 2 (the number).
The big limitation is that it works OK with same type of files, but if you mix mp3
and wav
, then you notice that mp3 files list their frequency as 44.1 kHz and that breaks the sort.
Sample output that I have , for example:
***./test.wav| 8000|Hz
***./odeath.wav| 44100|Hz
***./Front_Center.wav| 48000|Hz