oggvorbis — декодирование аудио libvorbis из памяти в переполнении стека

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

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

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

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

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

Благодарю.

9

Решение

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

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

9

Другие решения

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

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

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

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

1

По вопросам рекламы [email protected]