From da1bf2650188781588f10cd492dc880711a5a117 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 28 Jul 2014 21:59:51 -0700 Subject: [PATCH] Add OGG decoding --- project/Build.xml | 10 ++ project/src/ExternalInterface.cpp | 17 +++ project/src/format/OGG.cpp | 204 ++++++++++++++++++++++++++++++ project/src/format/WAV.cpp | 6 +- 4 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 project/src/format/OGG.cpp diff --git a/project/Build.xml b/project/Build.xml index 90ca8a7cf..587032dc9 100644 --- a/project/Build.xml +++ b/project/Build.xml @@ -59,6 +59,16 @@ +
+ + + + + + + +
+
diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 8ca8b75a3..aed83757a 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -15,6 +15,7 @@ #include #endif #include +#include #include #include #include @@ -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 (); } diff --git a/project/src/format/OGG.cpp b/project/src/format/OGG.cpp new file mode 100644 index 000000000..5135e2aab --- /dev/null +++ b/project/src/format/OGG.cpp @@ -0,0 +1,204 @@ +#include +#include +#include + + +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; + + } + + +} \ No newline at end of file diff --git a/project/src/format/WAV.cpp b/project/src/format/WAV.cpp index 2767f604b..24454d71f 100644 --- a/project/src/format/WAV.cpp +++ b/project/src/format/WAV.cpp @@ -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; }