libvorbis audio decode from memory in C++

本秂侑毒 提交于 2019-12-21 08:17:08

问题


Given an encoded buffer in C++, what would be the steps using oggvorbis structs to decode the already in-memory data?

OggVorbis_File cannot be used, because assets are within compressed archives.

I'm trying to research the necessary structs and methods, but I'm fairly new to audio encoding and decoding.

Any resources that can help further my reading are appreciated as well!

I should clarify, I intend to use the decoded data to stream into OpenAL.

Thanks.


回答1:


Answering my own question.

This can be done by providing custom callbacks to vorbis.

struct ogg_file
{
    char* curPtr;
    char* filePtr;
    size_t fileSize;
};

size_t AR_readOgg(void* dst, size_t size1, size_t size2, void* fh)
{
    ogg_file* of = reinterpret_cast<ogg_file*>(fh);
    size_t len = size1 * size2;
    if ( of->curPtr + len > of->filePtr + of->fileSize )
    {
        len = of->filePtr + of->fileSize - of->curPtr;
    }
    memcpy( dst, of->curPtr, len );
    of->curPtr += len;
    return len;
}

int AR_seekOgg( void *fh, ogg_int64_t to, int type ) {
    ogg_file* of = reinterpret_cast<ogg_file*>(fh);

    switch( type ) {
        case SEEK_CUR:
            of->curPtr += to;
            break;
        case SEEK_END:
            of->curPtr = of->filePtr + of->fileSize - to;
            break;
        case SEEK_SET:
            of->curPtr = of->filePtr + to;
            break;
        default:
            return -1;
    }
    if ( of->curPtr < of->filePtr ) {
        of->curPtr = of->filePtr;
        return -1;
    }
    if ( of->curPtr > of->filePtr + of->fileSize ) {
        of->curPtr = of->filePtr + of->fileSize;
        return -1;
    }
    return 0;
}

int AR_closeOgg(void* fh)
{
    return 0;
}

long AR_tellOgg( void *fh )
{
    ogg_file* of = reinterpret_cast<ogg_file*>(fh);
    return (of->curPtr - of->filePtr);
}

Usage

ov_callbacks callbacks;
ogg_file t;
t.curPtr = t.filePtr = compressedData;
t.fileSize = compressedDataSize;

OggVorbis_File* ov = new OggVorbis_File;
mOggFile = ov;
memset( ov, 0, sizeof( OggVorbis_File ) );

callbacks.read_func = AR_readOgg;
callbacks.seek_func = AR_seekOgg;
callbacks.close_func = AR_closeOgg;
callbacks.tell_func = AR_tellOgg;

int ret = ov_open_callbacks((void *)&t, ov, NULL, -1, callbacks);

vorbis_info* vi = ov_info(ov, -1);
assert(vi);

/* compressed data is available to use, to uncompress look into ov_read */

A Special thanks to the Doom3 GPL source for most of the help with this, it can be viewed at : here




回答2:


You also can don't reinvent the wheel and use fmemopen like this:

FILE* memfile = fmemopen(data, len, "r");

Where data is pointer to memory beginning and len is length of your data. Then pass memfile to ov_open like regular FILE object.

However, there is downside: this function seems linux-specific (but it can be found in arduino, so I'm a bit confused about its status), so you don't have it on other systems. But there is some implementations for them (check libconfuse for window or for apple OSes).



来源:https://stackoverflow.com/questions/13437422/libvorbis-audio-decode-from-memory-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!