【问题标题】:libvorbis audio decode from memory in C++libvorbis 音频从 C++ 中的内存解码
【发布时间】:2012-11-06 09:47:40
【问题描述】:

给定 C++ 中的编码缓冲区,使用 oggvorbis 结构解码已经在内存中的数据的步骤是什么?

无法使用 OggVorbis_File,因为资产在压缩档案中。

我正在尝试研究必要的结构和方法,但我对音频编码和解码还很陌生。

也感谢任何可以帮助我进一步阅读的资源!

我要澄清一下,我打算使用解码后的数据流入 OpenAL。

谢谢。

【问题讨论】:

    标签: c++ oggvorbis vorbis


    【解决方案1】:

    回答我自己的问题。

    这可以通过向 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);
    }
    

    用法

    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 */
    

    特别感谢 Doom3 GPL 源提供的大部分帮助,它可以 查看地址:here

    【讨论】:

    【解决方案2】:

    你也不能重新发明轮子,像这样使用fmemopen

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

    data 是指向内存开头的指针,len 是数据的长度。然后将memfile 传递给ov_open,就像普通的FILE 对象一样。

    但是,有一个缺点:这个函数似乎是 linux 特有的(但它可以在 arduino 中找到,所以我对它的状态有点困惑),所以你在其他系统上没有它。但是它们有一些实现(检查libconfuse 的窗口或apple OSes)。

    【讨论】:

    • 不过,我们在 Windows 上没有这个功能。
    猜你喜欢
    • 1970-01-01
    • 2013-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-03
    • 1970-01-01
    • 2012-11-30
    相关资源
    最近更新 更多