Add OGG decoding
This commit is contained in:
@@ -59,6 +59,16 @@
|
||||
|
||||
</section>
|
||||
|
||||
<section if="LIME_OGG">
|
||||
|
||||
<compilerflag value="-I${NATIVE_TOOLKIT_PATH}/ogg/include/" />
|
||||
<compilerflag value="-I${NATIVE_TOOLKIT_PATH}/vorbis/include/" />
|
||||
<compilerflag value="-DLIME_OGG" />
|
||||
|
||||
<file name="src/format/OGG.cpp" />
|
||||
|
||||
</section>
|
||||
|
||||
<section if="LIME_OPENAL">
|
||||
|
||||
<compilerflag value="-I${NATIVE_TOOLKIT_PATH}/openal/include/" />
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <graphics/Font.h>
|
||||
#endif
|
||||
#include <format/JPEG.h>
|
||||
#include <format/OGG.h>
|
||||
#include <format/PNG.h>
|
||||
#include <format/WAV.h>
|
||||
#include <graphics/Image.h>
|
||||
@@ -227,6 +228,14 @@ namespace lime {
|
||||
|
||||
}
|
||||
|
||||
#ifdef LIME_OGG
|
||||
if (OGG::Decode (&resource, &sound)) {
|
||||
|
||||
return sound.Value ();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
return alloc_null ();
|
||||
|
||||
}
|
||||
@@ -244,6 +253,14 @@ namespace lime {
|
||||
|
||||
}
|
||||
|
||||
#ifdef LIME_OGG
|
||||
if (OGG::Decode (&resource, &sound)) {
|
||||
|
||||
return sound.Value ();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
return alloc_null ();
|
||||
|
||||
}
|
||||
|
||||
204
project/src/format/OGG.cpp
Normal file
204
project/src/format/OGG.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
#include <format/OGG.h>
|
||||
#include <utils/FileIO.h>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
|
||||
|
||||
namespace lime {
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
unsigned char* data;
|
||||
ogg_int64_t size;
|
||||
ogg_int64_t pos;
|
||||
|
||||
} OAL_OggMemoryFile;
|
||||
|
||||
|
||||
static size_t OAL_OggBufferRead (void* dest, size_t eltSize, size_t nelts, OAL_OggMemoryFile* src) {
|
||||
|
||||
size_t len = eltSize * nelts;
|
||||
|
||||
if ((src->pos + len) > src->size) {
|
||||
|
||||
len = src->size - src->pos;
|
||||
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
|
||||
memcpy (dest, (src->data + src->pos), len);
|
||||
src->pos += len;
|
||||
|
||||
}
|
||||
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int OAL_OggBufferSeek (OAL_OggMemoryFile* src, ogg_int64_t pos, int whence) {
|
||||
|
||||
switch (whence) {
|
||||
|
||||
case SEEK_CUR:
|
||||
|
||||
src->pos += pos;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
|
||||
src->pos = src->size - pos;
|
||||
break;
|
||||
|
||||
case SEEK_SET:
|
||||
|
||||
src->pos = pos;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (src->pos < 0) {
|
||||
|
||||
src->pos = 0;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (src->pos > src->size) {
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int OAL_OggBufferClose (OAL_OggMemoryFile* src) {
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static long OAL_OggBufferTell (OAL_OggMemoryFile *src) {
|
||||
|
||||
return src->pos;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static ov_callbacks OAL_CALLBACKS_BUFFER = {
|
||||
|
||||
(size_t (*)(void *, size_t, size_t, void *)) OAL_OggBufferRead,
|
||||
(int (*)(void *, ogg_int64_t, int)) OAL_OggBufferSeek,
|
||||
(int (*)(void *)) OAL_OggBufferClose,
|
||||
(long (*)(void *)) OAL_OggBufferTell
|
||||
|
||||
};
|
||||
|
||||
|
||||
bool OGG::Decode (Resource *resource, Sound *sound) {
|
||||
|
||||
OggVorbis_File oggFile;
|
||||
|
||||
if (resource->path) {
|
||||
|
||||
FILE *file;
|
||||
|
||||
#ifdef ANDROID
|
||||
FileInfo info = AndroidGetAssetFD (resource->path);
|
||||
file = lime::fdopen (info.fd, "rb");
|
||||
lime::fseek (file, info.offset, 0);
|
||||
#else
|
||||
file = lime::fopen (resource->path, "rb");
|
||||
#endif
|
||||
|
||||
if (!file) {
|
||||
|
||||
//LOG_SOUND("FAILED to read sound file, file pointer as null?\n");
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
ov_open (file, &oggFile, NULL, info.length);
|
||||
#else
|
||||
ov_open (file, &oggFile, NULL, 0);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
OAL_OggMemoryFile fakeFile = { resource->data->Bytes (), resource->data->Size (), 0 };
|
||||
|
||||
if (ov_open_callbacks (&fakeFile, &oggFile, NULL, 0, OAL_CALLBACKS_BUFFER) != 0) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 0 for Little-Endian, 1 for Big-Endian
|
||||
#ifdef HXCPP_BIG_ENDIAN
|
||||
#define BUFFER_READ_TYPE 1
|
||||
#else
|
||||
#define BUFFER_READ_TYPE 0
|
||||
#endif
|
||||
|
||||
int bitStream;
|
||||
long bytes = 1;
|
||||
int totalBytes = 0;
|
||||
|
||||
#define BUFFER_SIZE 32768
|
||||
|
||||
vorbis_info *pInfo = ov_info (&oggFile, -1);
|
||||
|
||||
if (pInfo == NULL) {
|
||||
|
||||
//LOG_SOUND("FAILED TO READ OGG SOUND INFO, IS THIS EVEN AN OGG FILE?\n");
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
sound->channels = pInfo->channels;
|
||||
sound->sampleRate = pInfo->rate;
|
||||
|
||||
//default to 16? todo
|
||||
sound->bitsPerSample = 16;
|
||||
|
||||
// Seem to need four times the read PCM total
|
||||
sound->data->Resize (ov_pcm_total (&oggFile, -1) * 4);
|
||||
|
||||
while (bytes > 0) {
|
||||
|
||||
if (sound->data->Size () < totalBytes + BUFFER_SIZE) {
|
||||
|
||||
sound->data->Resize (totalBytes + BUFFER_SIZE);
|
||||
|
||||
}
|
||||
|
||||
// Read up to a buffer's worth of decoded sound data
|
||||
bytes = ov_read (&oggFile, (char *)sound->data->Bytes () + totalBytes, BUFFER_SIZE, BUFFER_READ_TYPE, 2, 1, &bitStream);
|
||||
totalBytes += bytes;
|
||||
|
||||
}
|
||||
|
||||
sound->data->Resize (totalBytes);
|
||||
ov_clear (&oggFile);
|
||||
|
||||
#undef BUFFER_SIZE
|
||||
#undef BUFFER_READ_TYPE
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -63,7 +63,7 @@ namespace lime {
|
||||
|
||||
if (!file) {
|
||||
|
||||
LOG_SOUND ("FAILED to read sound file, file pointer as null?\n");
|
||||
//LOG_SOUND ("FAILED to read sound file, file pointer as null?\n");
|
||||
return false;
|
||||
|
||||
}
|
||||
@@ -72,7 +72,7 @@ namespace lime {
|
||||
|
||||
if ((riff_header.chunkID[0] != 'R' || riff_header.chunkID[1] != 'I' || riff_header.chunkID[2] != 'F' || riff_header.chunkID[3] != 'F') || (riff_header.format[0] != 'W' || riff_header.format[1] != 'A' || riff_header.format[2] != 'V' || riff_header.format[3] != 'E')) {
|
||||
|
||||
LOG_SOUND ("Invalid RIFF or WAVE Header!\n");
|
||||
//LOG_SOUND ("Invalid RIFF or WAVE Header!\n");
|
||||
return false;
|
||||
|
||||
}
|
||||
@@ -158,7 +158,7 @@ namespace lime {
|
||||
|
||||
if ((riff_header.chunkID[0] != 'R' || riff_header.chunkID[1] != 'I' || riff_header.chunkID[2] != 'F' || riff_header.chunkID[3] != 'F') || (riff_header.format[0] != 'W' || riff_header.format[1] != 'A' || riff_header.format[2] != 'V' || riff_header.format[3] != 'E')) {
|
||||
|
||||
LOG_SOUND ("Invalid RIFF or WAVE Header!\n");
|
||||
//LOG_SOUND ("Invalid RIFF or WAVE Header!\n");
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user