Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
7 KB
Referenced Files
None
Subscribers
None
diff --git a/util/ogg/LICENSE.TXT b/util/ogg/LICENSE.TXT
new file mode 100644
index 00000000..410e404b
--- /dev/null
+++ b/util/ogg/LICENSE.TXT
@@ -0,0 +1,22 @@
+Copyright (c) 2007 Trent Gamblin
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/util/ogg/logg.c b/util/ogg/logg.c
new file mode 100644
index 00000000..47b9deee
--- /dev/null
+++ b/util/ogg/logg.c
@@ -0,0 +1,269 @@
+#if defined(HAVE_OGG) && defined(USE_ALLEGRO)
+
+#include <string.h>
+#include <allegro.h>
+#include <allegro/internal/aintern.h>
+
+#include "logg.h"
+
+/* XXX requires testing */
+#ifdef ALLEGRO_BIG_ENDIAN
+ const int ENDIANNESS = 1;
+#endif
+#ifdef ALLEGRO_LITTLE_ENDIAN
+ const int ENDIANNESS = 0;
+#endif
+
+static int logg_bufsize = 1024*64;
+
+SAMPLE* logg_load(const char* filename)
+{
+ OggVorbis_File ovf;
+ FILE* file;
+ vorbis_info* vi;
+ SAMPLE* samp;
+ int numRead;
+ int offset = 0;
+ int bitstream;
+ char *buf = malloc(logg_bufsize);
+
+ file = fopen(filename, "rb");
+ if (!file) {
+ uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, "Unable to open file: %s", filename);
+ free(buf);
+ return 0;
+ }
+
+ if (ov_open_callbacks(file, &ovf, 0, 0, OV_CALLBACKS_DEFAULT) != 0) {
+ strncpy(allegro_error, "ov_open_callbacks failed.", ALLEGRO_ERROR_SIZE);
+ fclose(file);
+ free(buf);
+ return 0;
+ }
+
+ vi = ov_info(&ovf, -1);
+
+ samp = (SAMPLE*)_al_malloc(sizeof(SAMPLE));
+ if (!samp) {
+ ov_clear(&ovf);
+ free(buf);
+ return 0;
+ }
+
+ samp->bits = 16;
+ samp->stereo = vi->channels > 1 ? 1 : 0;
+ samp->freq = vi->rate;
+ samp->priority = 128;
+ samp->len = ov_pcm_total(&ovf, -1);
+ samp->loop_start = 0;
+ samp->loop_end = samp->len;
+ samp->data = _al_malloc(sizeof(unsigned short) * samp->len * 2);
+
+ while ((numRead = ov_read(&ovf, buf, logg_bufsize,
+ ENDIANNESS, 2, 0, &bitstream)) != 0) {
+ memcpy((unsigned char*)samp->data+offset, buf, numRead);
+ offset += numRead;
+ }
+
+ ov_clear(&ovf);
+ free(buf);
+
+ return samp;
+}
+
+int logg_get_buffer_size(void)
+{
+ return logg_bufsize;
+}
+
+void logg_set_buffer_size(int size)
+{
+ ASSERT(size > 0);
+ logg_bufsize = size;
+}
+
+static int logg_open_file_for_streaming(struct LOGG_Stream* s)
+{
+ FILE* file;
+ vorbis_info* vi;
+
+ file = fopen(s->filename, "rb");
+ if (!file) {
+ uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, "Unable to open file: %s", s->filename);
+ return 1;
+ }
+
+ if (ov_open_callbacks(file, &s->ovf, 0, 0, OV_CALLBACKS_DEFAULT) != 0) {
+ strncpy(allegro_error, "ov_open_callbacks failed.", ALLEGRO_ERROR_SIZE);
+ fclose(file);
+ return 1;
+ }
+
+ vi = ov_info(&s->ovf, -1);
+
+ s->bits = 16;
+ s->stereo = vi->channels > 1 ? 1 : 0;
+ s->freq = vi->rate;
+ s->len = ov_pcm_total(&s->ovf, -1);
+
+ return 0;
+}
+
+static int read_ogg_data(struct LOGG_Stream* s)
+{
+ int read = 0;
+ int bitstream;
+
+ int page = s->current_page;
+ s->current_page++;
+ s->current_page %= OGG_PAGES_TO_BUFFER;
+
+ memset(s->buf[page], 0, logg_bufsize);
+
+ while (read < logg_bufsize) {
+ int thisRead = ov_read(&s->ovf, s->buf[page]+read,
+ logg_bufsize-read,
+ ENDIANNESS, 2, 0, &bitstream);
+ if (thisRead == 0) {
+ if (s->loop) {
+ ov_clear(&s->ovf);
+ if (logg_open_file_for_streaming(s)) {
+ return -1;
+ }
+ }
+ else {
+ return read;
+ }
+ }
+ read += thisRead;
+ }
+
+ return read;
+}
+
+static int logg_play_stream(struct LOGG_Stream* s)
+{
+ int len;
+ int i;
+
+ s->current_page = 0;
+ s->playing_page = -1;
+
+ len = logg_bufsize / (s->stereo ? 2 : 1)
+ / (s->bits / (sizeof(char)*8));
+
+ s->audio_stream = play_audio_stream(len,
+ s->bits, s->stereo,
+ s->freq, s->volume, s->pan);
+
+ if (!s->audio_stream) {
+ return 1;
+ }
+
+ for (i = 0; i < OGG_PAGES_TO_BUFFER; i++) {
+ s->buf[i] = malloc(logg_bufsize);
+ if (!s->buf[i]) {
+ logg_destroy_stream(s);
+ return 1;
+ }
+ if (read_ogg_data(s) < 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+struct LOGG_Stream* logg_get_stream(const char* filename, int volume, int pan, int loop)
+{
+ struct LOGG_Stream* s = calloc(1, sizeof(struct LOGG_Stream));
+ if (!s) {
+ return 0;
+ }
+
+ s->filename = strdup(filename);
+
+ if (!s->filename) {
+ free(s);
+ return 0;
+ }
+
+ if (logg_open_file_for_streaming(s)) {
+ logg_destroy_stream(s);
+ return 0;
+ }
+
+ s->volume = volume;
+ s->pan = pan;
+ s->loop = loop;
+
+ if (logg_play_stream(s)) {
+ logg_destroy_stream(s);
+ return 0;
+ }
+
+ return s;
+}
+
+int logg_update_stream(struct LOGG_Stream* s)
+{
+ unsigned char* data = get_audio_stream_buffer(s->audio_stream);
+
+ if (!data) {
+ if (s->current_page != s->playing_page) {
+ int read = read_ogg_data(s);
+ if (read < logg_bufsize) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+ }
+ else {
+ return 1;
+ }
+ }
+
+ s->playing_page++;
+ s->playing_page %= OGG_PAGES_TO_BUFFER;
+ memcpy(data, s->buf[s->playing_page], logg_bufsize);
+
+ free_audio_stream_buffer(s->audio_stream);
+
+ return 1;
+}
+
+void logg_stop_stream(struct LOGG_Stream* s)
+{
+ int i;
+
+ stop_audio_stream(s->audio_stream);
+ for (i = 0; i < OGG_PAGES_TO_BUFFER; i++) {
+ free(s->buf[i]);
+ s->buf[i] = 0;
+ }
+}
+
+int logg_restart_stream(struct LOGG_Stream* s)
+{
+ return logg_play_stream(s);
+}
+
+void logg_destroy_stream(struct LOGG_Stream* s)
+{
+ int i;
+
+ if (s->audio_stream) {
+ stop_audio_stream(s->audio_stream);
+ }
+ ov_clear(&s->ovf);
+ for (i = 0; i < OGG_PAGES_TO_BUFFER; i++) {
+ if (s->buf[i]) {
+ free(s->buf[i]);
+ }
+ }
+ free(s->filename);
+ free(s);
+}
+
+#endif
diff --git a/util/ogg/logg.h b/util/ogg/logg.h
new file mode 100644
index 00000000..19622722
--- /dev/null
+++ b/util/ogg/logg.h
@@ -0,0 +1,48 @@
+#ifndef LOGG_H
+#define LOGG_H
+
+#if defined(USE_ALLEGRO) && defined(HAVE_OGG)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <allegro.h>
+#include <vorbis/vorbisfile.h>
+
+#define OGG_PAGES_TO_BUFFER 2
+
+struct LOGG_Stream {
+ char *buf[OGG_PAGES_TO_BUFFER];
+ int current_page;
+ int playing_page;
+ AUDIOSTREAM* audio_stream;
+ OggVorbis_File ovf;
+ int bits;
+ int stereo;
+ int freq;
+ int len;
+ char* filename;
+ int loop;
+ int volume;
+ int pan;
+};
+
+extern SAMPLE* logg_load(const char* filename);
+extern int logg_get_buffer_size();
+extern void logg_set_buffer_size(int size);
+extern struct LOGG_Stream* logg_get_stream(const char* filename,
+ int volume, int pan, int loop);
+extern int logg_update_stream(struct LOGG_Stream* s);
+extern void logg_destroy_stream(struct LOGG_Stream* s);
+extern void logg_stop_stream(struct LOGG_Stream* s);
+extern int logg_restart_stream(struct LOGG_Stream* s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // USE_ALLEGRO
+
+#endif
+

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 11, 12:02 PM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68940
Default Alt Text
(7 KB)

Event Timeline