Juce reports as length 0 WAV files that itunes can read


#1

Hello, Jucey people, from Berlin, home of exciting music and arts, where I am this summer.

We’ve received a couple of reports from people who have .WAV files that play in iTunes but not in our application, where we report that these files have length 0, because (you see it coming) that’s what Juce tells us.

Both users have an RCA digital recorder. The sample I got from one is an 8KHz, mono 8-bit ALaw 2:1 WAV audio file and you can see it here - and indeed, it works fine in iTunes but not our application.

Unlike the previous example of an audio edge case file I reported here, I think this one seems to fit firmly into the WAV spec - the header is fine, something goes on after the header is read that I haven’t yet tracked down in the debugger but that sets the size to 0.


#2

FWIW, view my post [here].

As far as I’ve had time to test, JUCE only supports the standard, uncompressed, PCM WAV format.


#3

While this may be a bug/feature lacking in the JUCE WavAudioFormat do the native audio formats (CoreAudioFormat, WindowsMediaAudioFormat) read the file ok?

I was thinking a work around could be either setting one of those to the default reader or if WavAudioFormat returns a length of 0 try to use the native reader?

If as jrlanglois suggests the WavAudioFormat was not designed to read compressed wav streams perhaps it should fail to open the stream and return a nullptr instead. This way the native codecs will be used automatically.


#4

Unfortunately, CoreAudioReader at least has bad results - or at least, I think it does, perhaps it’s my code which isn’t handling mono quite right?? But it does get some sort of non-zero length anyway…

The result is that I get the whole thing running at some large multiple of the original speed and correspondingly pitched up. Interestingly enough, one of the people reporting the issue reports that when she converts the .wav file with iTunes, she gets the same result, but I don’t see that with itunes…


#5

Nope, CoreAudioFormat works fine, after that the error was in my code.

In fact, I’m going to propose the following change to juce::AudioFormatManager::registerBasicFormats():

[code] #if JUCE_MAC || JUCE_IOS
registerFormat (new CoreAudioFormat(), true);

#elif JUCE_USE_WINDOWS_MEDIA_FORMAT
registerFormat (new WindowsMediaAudioFormat(), true);

#else
// Use software codecs if there isn’t an OS-specific codec.
registerFormat (new WavAudioFormat(), true);
registerFormat (new AiffAudioFormat(), false);
#if JUCE_USE_MP3AUDIOFORMAT
registerFormat (new MP3AudioFormat(), false);
#endif
#endif
[/code]

The idea is that the “native” audio format, if it exists, always supersedes the Juce-provided ones.

There are two reasons for this proposed change:

[list]
[]the rule of “least surprise” where your program works the same as most other programs on that platform, [/]
[]and the fact that the native version is likely to support more features than the home-rolled one since the larger companies have incomparably larger resources.[/][/list]


#6

One more tiny detail - when I’m looking at the resulting AudioFormatReader from CoreAudioFormat, I see that the bitsPerSample is always zero.

Strangely enough, everything else works fine (except my code, and it does what I’d expect, it just doesn’t handle such samples correctly yet).


#7

The bitsPerSample member is set to whatever CoreAudio reports the source audio format bits per sample to be. Thinking about it now though this should probably be hard coded to 32 as the reader converts the source format to 32-bit float anyway.


#8

Further development here!

It turns out that the code sample I posted is not “correct” - in specific, that it likely prevents you from saving files because neither CoreAudioFormat nor WindowsMediaAudioFormat actually allows writing of files.

The long-term game plan should of course to allow these two formats to write data!

But in the short term, I’m going to create two AudioFormatManagers - a reader manager, which prefers Core and WindowsMedia, and a writer manager, which prefers the software codecs.


#9

But when you’re writing a file, you’d create your own format object rather than using the ones that were registered in the format manager, so I don’t really see that as a problem.

My main objection would be that for simple format like wav, the juce classes are probably actually faster than going via the OS APIs, so should probably be used in preference, with the OS formats as a fall-back if they fail to parse a file.

What I’d suggest is just making the wav format a bit smarter, so it knows when it failed to open the file, e.g. this little tweak:

[code]AudioFormatReader* WavAudioFormat::createReaderFor (InputStream* sourceStream,
const bool deleteStreamIfOpeningFails)
{
ScopedPointer r (new WavAudioFormatReader (sourceStream));

if (r->sampleRate > 0 && r->numChannels > 0)
    return r.release();

[/code]


#10

Good point, thanks.