Given an encoded buffer in C++, what would be the steps using oggvorbis structs to decode the already in-memory data?
OggVorbis_File cannot be used, because assets are within compressed archives.
I'm trying to research the necessary structs and methods, but I'm fairly new to audio encoding and decoding.
Any resources that can help further my reading are appreciated as well!
I should clarify, I intend to use the decoded data to stream into OpenAL.
Thanks.
Answering my own question.
This can be done by providing custom callbacks to 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);
}
Usage
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 Special thanks to the Doom3 GPL source for most of the help with this, it can be viewed at : here
You also can don't reinvent the wheel and use fmemopen
like this:
FILE* memfile = fmemopen(data, len, "r");
Where data
is pointer to memory beginning and len
is length of your data. Then pass memfile
to ov_open
like regular FILE
object.
However, there is downside: this function seems linux-specific (but it can be found in arduino, so I'm a bit confused about its status), so you don't have it on other systems. But there is some implementations for them (check libconfuse for window or for apple OSes).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With