首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在C++中从内存中解码libvorbis音频

在C++中从内存中解码libvorbis音频
EN

Stack Overflow用户
提问于 2012-11-18 12:13:52
回答 2查看 4.4K关注 0票数 11

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

无法使用OggVorbis_File,因为资产位于压缩存档中。

我正在尝试研究必要的结构和方法,但我对音频编码和解码还是个新手。

任何对我的阅读有帮助的资源,我也非常感谢!

我要澄清的是,我打算使用解码后的数据流到OpenAL中。

谢谢。

EN

回答 2

Stack Overflow用户

发布于 2012-11-19 00:51:51

回答我自己的问题。

这可以通过提供对vorbis的自定义回调来实现。

代码语言:javascript
复制
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);
}

用法

代码语言:javascript
复制
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特别感谢Doom3 GPL源代码在这方面提供的大部分帮助,可以在以下位置查看:here

票数 12
EN

Stack Overflow用户

发布于 2018-08-04 00:17:55

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

代码语言:javascript
复制
FILE* memfile = fmemopen(data, len, "r");

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

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13437422

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档