Tracktion / choc

A collection of header only classes, permissively licensed, to provide basic useful tasks with the bare-minimum of dependencies.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

OggAudioFileFormat fails to load content

atsushieno opened this issue · comments

I have been trying choc these days for some audio code. I noticed that AudioReader from OggAudioFileFormat<supportWriting> cannot read file at all in my app. It is probably IF the input is seekable.

I think I figured out why. In choc_AudioFileFormat_Ogg.h (line 59558 at 24556f4, cannot put permalink as the file is too large):

        bool fillCache (uint64_t frameIndex)
        {
            if (ov_pcm_tell (std::addressof (oggfile)) != static_cast<int64_t> (frameIndex))
                if (! ov_pcm_seek (std::addressof (oggfile), static_cast<int64_t> (frameIndex)))
                    return false;

It returns false when ov_pcm_seek() returns 0, but this function returns 0 for SUCCESS. Therefore, it never succeeds when our code reaches there.

Partial repro code:

class SeekableByteBuffer : public std::streambuf {
public:
    SeekableByteBuffer(uint8_t* data, std::size_t size) {
        setg(reinterpret_cast<char*>(data), reinterpret_cast<char*>(data), reinterpret_cast<char*>(data) + size);
    }

    std::streampos seekoff(std::streamoff off, std::ios_base::seekdir dir, std::ios_base::openmode which) override {
        if (dir == std::ios_base::cur) {
            gbump(static_cast<int>(off));
        } else if (dir == std::ios_base::end) {
            setg(eback(), egptr() + off, egptr());
        } else if (dir == std::ios_base::beg) {
            setg(eback(), eback() + off, egptr());
        }
        return gptr() - eback();
    }
};

void repro(uint8_t *data, int dataLength, const char *filename) {
    choc::audio::OggAudioFileFormat<false> format{};

    if (format.filenameSuffixMatches(filename)) {
        SeekableByteBuffer buffer(data, dataLength);
        auto stream = std::make_shared<std::istream>(&buffer);
        auto reader = format.createReader(stream);
        reader->loadFileContent();
    }
}

Thanks for the great bug report!
I can't really figure out what your stream class was supposed to be doing, and it seemed to behave oddly when I tried it, but I added a simpler test that seemed to be triggering the same bug, and fixed it, so it should be fine now. Let me know if you still have any problems with it

Oops, yes the streambuf hack would be odd. I hoped to use std::basic_spanstream with span alternative in choc, but it requires C++23 (of course). So I resorted to some hacky workaround. The fix worked. Thanks!