AudioFormatManager opening without checking extension?


#1

Recently a user complain that he couldn’t open a wav file with my software while it should be possible.
After some probing it appears that his wav file was in fact an aiff file with the wrong extension.

The behavior of the AudioFormatManager was correct as there was a problem with the file extension even use with “registerBasicFormats()” but it would be interesting to have an option to not filter the file type by the extension but by the header of the file ?


#2

You could do this manually. Open each one and do some detection, then return the correct format loader as a result.

would be nice to have.


#3

Or just use the method that takes an InputStream, that obviously doesn’t do any extension checking.


#4

Obviously I can do it myself, I just thought it would be interesting to have directly in juce.


#5

Well I guess you could see the method that takes a file as an automatic optimisation in that it will be a lot quicker to just pattern match the file extension rather than try and open every reader, some of which have time-consuming constructors to read metadata etc. In 99.9% of cases this is a perfectly valid assumption that files should have the right extension.

I guess it depends on what stance you take as to what a valid file is. Personally I think that if a file has a .wav extension but actually contains aiff data then the file is invalid and should not return a valid reader for it. You might want to notify the user that the file has the wrong extension or similar. If JUCE did this automatically there would be no way of knowing this peculiarity as all the readers are private, they only expose the base class implementation.

Having said that it is often nice to just go ahead and read the file anyway but in this instance what your saying is that the file is invalid but the stream of data the file refers to is valid. In this case I would just provide an additional method that uses AudioFormatManager::createReaderFor (InputStream* audioFileStream) as a backup. I would say that most applications have some container class for file reading etc. which might deliver other, optimised readers (like MemoryMappedAudioFormatReader) where possible, so you could just modify your reader creator method to something like:

[code]AudioFormatReader* createReader (const File& audioFile)
{
if (AudioFormatReader* reader = manager.createReaderFor (audioFile))
return reader;

if (AudioFormatReader* reader = manager.createReaderFor (audioFile.createInputStream()))
    return reader;

}
[/code]