libvorbis аудио декодирует из памяти в С++

Учитывая закодированный буфер в C++, каковы будут шаги с использованием структур oggvorbis для декодирования уже находящихся в памяти данных?

OggVorbis_File использовать нельзя, так как активы находятся в сжатых архивах.

Я пытаюсь исследовать необходимые структуры и методы, но я новичок в кодировании и декодировании звука.

Любые ресурсы, которые могут помочь в моем чтении, также приветствуются!

Я должен уточнить, я намерен использовать декодированные данные для потоковой передачи в OpenAL.

Спасибо.


person DubyaDubyaDubyaDot    schedule 18.11.2012    source источник


Ответы (2)


Отвечая на мой собственный вопрос.

Это можно сделать, предоставив пользовательские обратные вызовы для 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 за большую часть помощи в этом, его можно посмотреть по адресу: здесь

person DubyaDubyaDubyaDot    schedule 18.11.2012
comment
Также вы можете проверить svn.xiph.org/trunk/vorbis/examples/decoder_example. с - person Dawid Drozd; 15.03.2014
comment
Отличный ответ! У вас есть минимальный полный рабочий пример, с которым я могу поиграться? - person Chimera; 02.11.2016

Вы также не можете изобретать велосипед и использовать fmemopen. так:

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

Где data — указатель на начало памяти, а len — длина ваших данных. Затем передайте memfile в ov_open как обычный объект FILE.

Однако есть и обратная сторона: эта функция кажется специфичной для Linux (но ее можно найти в arduino, поэтому я немного запутался в ее статусе), поэтому в других системах ее нет. Но для них есть некоторые реализации (проверьте libconfuse для окна или для ОС Apple).

person val is still with Monica    schedule 03.08.2018
comment
Однако у нас нет этого в Windows. - person HolyBlackCat; 03.08.2018