Juce_string.cpp assertion failure while trying to create an AudioFormatReader

I’m a beginner programmer. I’m trying to build a program to read all the metadata from my sound libraries. I’ve been getting a runtime error constantly for some specific files. I stripped down my code and isolated the error to the line where im creating an AudioFormatReader. This code runs well for most of the files till it hits some of them and just crashes. I have no idea why its behaving this way

juce::File searchPath("/Volumes/LACIE SHARE/Sound Library");
juce::AudioFormatManager formatManager;
formatManager.registerBasicFormats();
//juce::DirectoryIterator iter (searchPath,true,"*.wav");
juce::SortedSet<juce::String> bwavMetaKeys;
juce::Time startTime = juce::Time::getCurrentTime();
int countFiles = 0;
//auto testreader = formatManager.createReaderFor(testPath);
for(juce::DirectoryEntry iter : juce::RangedDirectoryIterator(searchPath,true, "*.wav")) {
    std::cout << "before" << std::endl;
    std::cout << iter.getFile().getFileName() << std::endl;
    std::cout << "after" << std::endl;
    auto rawreader = formatManager.createReaderFor(iter.getFile());
    std::unique_ptr<juce::AudioFormatReader> reader(rawreader);
    //        if(reader->metadataValues["bwav description"].isNotEmpty())
    //        std::cout << reader->metadataValues["bwav description"] << std::endl;

// if(reader) {
// for (juce::String key : reader->metadataValues.getAllKeys()) {
// //DBG ("Key: " + key + " value: " + reader->metadataValues.getValue (key, “unknown”));
// bwavMetaKeys.add(key);
// }
// }
// delete rawreader;
}

Doesn’t a std::unique_ptr require using std::make_unique to create it safely? Haven’t used (or researched) those much, but every instance I have does so.

make_unique can’t be used here because the unique_ptr needs to be constructed from a raw pointer since that is what the Juce AudioFormatManager returns. make_unique is used when you have the constructor arguments to construct the object.

It is possible you have files that the Juce AudioFormat code isn’t able to handle. Have you looked with the debugger what has happened when you get the jassert/crash?

Hey yeah its caused by some specific files. The debugger shows the crash is caused by juce::String::fromUTF8 function. I found out a few files which were causing this crash but they didnt have anything different from the other normals audio files. Just another wav file from what i could observe. Even other files from same library dont cause this issue. It plays back fine. I tried importing them to other DAW’s n stuff.

Hmm. Looks like it’s asserting on the name of the file for some reason. I can’t see the full stack listing (it’s cut off on the right side of that column). Is there something special about those file names or paths? When you get that assertion break, I’d suggest checking out what is happening at each level of the call stack, to see what’s getting passed to fromUTF8() and at each level. There should be a clue there someplace.

1 Like

Maybe there’s a non-ASCII character or something else wrong in the metadata? (The code ends up in the String method that fails, from a function that has something to do with the BWAV chunk.)

1 Like

Yeah, i would suppose there might be a non-ascii character in the metadata.
This is the call stack

I’m quite to new to debugging so yeah I did miss to check the call stack and variables. This is what I found was being passed to the string method. I’m not very thorough with ASCII characters but i can’t find anything weird in there

Ok I think i found the non ASCII character in origindate in BWAVCHUNK.



i still dont know how to fix this error though. :sweat_smile:

1 Like

I’m getting this same error, did you figure out a solution to this? Just bad metadata crashing Audio Format Reader…

The good news is it’s just an assertion. In a release build you just get a string in the metadata with invalid characters. Whatever happens subsequently depends on the calling code.

Unfortunately I think there is no easy fix. You can turn the

jassert (CharPointer_UTF8::isValidString (buffer, bufferSizeBytes));

into an if to catch it, but there is no way to know the actual encoding if it’s not UTF8.
Something like this could work:

if (CharPointer_UTF8::isValidString (buffer, bufferSizeBytes));
    return String (CharPointer_UTF8 (buffer), CharPointer_UTF8 (buffer + bufferSizeBytes));
else
    return String (buffer, bufferSizeBytes); // constructs from raw ascii

But I am not sure if it’s the right thing to do…