libvorbis audio decode from memory in C++

后端 未结 2 899
失恋的感觉
失恋的感觉 2021-02-20 08:42

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 w

相关标签:
2条回答
  • 2021-02-20 09:06

    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

    0 讨论(0)
  • 2021-02-20 09:19

    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).

    0 讨论(0)
提交回复
热议问题