С учетом закодированного буфера в C ++, каковы будут шаги с использованием структур oggvorbis для декодирования уже находящихся в памяти данных?
OggVorbis_File не может быть использован, потому что ресурсы находятся в сжатых архивах.
Я пытаюсь исследовать необходимые структуры и методы, но я довольно плохо знаком с кодированием и декодированием звука.
Любые ресурсы, которые могут помочь моему чтению, также приветствуются!
Я должен уточнить, я намерен использовать декодированные данные для потоковой передачи в OpenAL.
Благодарю.
Отвечая на мой собственный вопрос.
Это может быть сделано путем предоставления пользовательских обратных вызовов 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 за большую часть помощи в этом, он может
смотреть на: Вот
Вы также не можете изобретать велосипед и использовать fmemopen
как это:
FILE* memfile = fmemopen(data, len, "r");
куда data
это указатель на начало памяти и len
длина ваших данных. Тогда пройдите memfile
в ov_open
как обычный FILE
объект.
Однако есть и обратная сторона: эта функция кажется специфичной для linux (но ее можно найти в arduino, так что я немного запутался в ее состоянии), так что ее нет в других системах. Но есть некоторые реализации для них (проверьте libconfuse для окна или для ОС Apple).