From 9316232c7f46be1fe9247e2895e0c78cb31b69db Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 9 Sep 2002 01:59:14 +0000 Subject: [PATCH] Vaclav Slavik - Sun Sep 8 18:57:38 PDT 2002 * Added support for loading Ogg Vorbis samples as an audio chunk --- CHANGES | 2 + Makefile.am | 2 + load_ogg.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++ load_ogg.h | 29 ++++++++++ mixer.c | 8 +++ 5 files changed, 193 insertions(+) create mode 100644 load_ogg.c create mode 100644 load_ogg.h diff --git a/CHANGES b/CHANGES index 9e31e74d..cf1ab0ec 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,7 @@ 1.2.5: +Vaclav Slavik - Sun Sep 8 18:57:38 PDT 2002 + * Added support for loading Ogg Vorbis samples as an audio chunk Martin Storsjö - Tue Jul 16 10:38:12 PDT 2002 * Fixed to start playing another sample immediately when one finishes Martin Storsjö - Tue May 28 13:08:29 PDT 2002 diff --git a/Makefile.am b/Makefile.am index 563a848d..3c894197 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,6 +14,8 @@ libSDL_mixer_la_SOURCES = \ load_aiff.h \ load_voc.c \ load_voc.h \ + load_ogg.c \ + load_ogg.h \ mixer.c \ music.c \ music_cmd.c \ diff --git a/load_ogg.c b/load_ogg.c new file mode 100644 index 00000000..52c6df8a --- /dev/null +++ b/load_ogg.c @@ -0,0 +1,152 @@ +/* + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + This is the source needed to decode an Ogg Vorbis into a waveform. + This file by Vaclav Slavik (vaclav.slavik@matfyz.cz). +*/ + +/* $Id$ */ + +#ifdef OGG_MUSIC + +#include +#include +#include +#include + +#include "SDL_mutex.h" +#include "SDL_endian.h" +#include "SDL_timer.h" + +#include "SDL_mixer.h" +#include "load_ogg.h" + +static size_t sdl_read_func(void *ptr, size_t size, size_t nmemb, void *datasource) +{ + return SDL_RWread((SDL_RWops*)datasource, ptr, size, nmemb); +} + +static int sdl_seek_func(void *datasource, ogg_int64_t offset, int whence) +{ + return SDL_RWseek((SDL_RWops*)datasource, offset, whence); +} + +static int sdl_close_func_freesrc(void *datasource) +{ + return SDL_RWclose((SDL_RWops*)datasource); +} + +static int sdl_close_func_nofreesrc(void *datasource) +{ + return SDL_RWseek((SDL_RWops*)datasource, 0, SEEK_SET); +} + +static long sdl_tell_func(void *datasource) +{ + return SDL_RWtell((SDL_RWops*)datasource); +} + + +/* don't call this directly; use Mix_LoadWAV_RW() for now. */ +SDL_AudioSpec *Mix_LoadOGG_RW (SDL_RWops *src, int freesrc, + SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) +{ + OggVorbis_File vf; + ov_callbacks callbacks; + vorbis_info *info; + Uint8 *buf; + int bitstream = -1; + long samplesize; + long samples; + int read, to_read; + int must_close = 1; + int was_error = 1; + + if ( (!src) || (!audio_buf) || (!audio_len) ) /* sanity checks. */ + goto done; + + callbacks.read_func = sdl_read_func; + callbacks.seek_func = sdl_seek_func; + callbacks.tell_func = sdl_tell_func; + callbacks.close_func = freesrc ? + sdl_close_func_freesrc : sdl_close_func_nofreesrc; + + if (ov_open_callbacks(src, &vf, NULL, 0, callbacks) != 0) + { + SDL_SetError("OGG bitstream is not valid Vorbis stream!"); + goto done; + } + + must_close = 0; + + info = ov_info(&vf, -1); + + *audio_buf = NULL; + *audio_len = 0; + memset(spec, '\0', sizeof (SDL_AudioSpec)); + + spec->format = AUDIO_S16; + spec->channels = info->channels; + spec->freq = info->rate; + spec->samples = 4096; /* buffer size */ + + samples = ov_pcm_total(&vf, -1); + + *audio_len = spec->size = samples * spec->channels * 2; + *audio_buf = malloc(*audio_len); + if (*audio_buf == NULL) + goto done; + + buf = *audio_buf; + to_read = *audio_len; + for (read = ov_read(&vf, buf, to_read, 0/*LE*/, 2/*16bit*/, 1/*signed*/, &bitstream); + read > 0; + read = ov_read(&vf, buf, to_read, 0, 2, 1, &bitstream)) + { + if (read == OV_HOLE || read == OV_EBADLINK) + break; /* error */ + + to_read -= read; + buf += read; + } + + ov_clear(&vf); + was_error = 0; + + /* Don't return a buffer that isn't a multiple of samplesize */ + samplesize = ((spec->format & 0xFF)/8)*spec->channels; + *audio_len &= ~(samplesize-1); + +done: + if (src && must_close) + { + if (freesrc) + SDL_RWclose(src); + else + SDL_RWseek(src, 0, SEEK_SET); + } + + if ( was_error ) + spec = NULL; + + return(spec); +} /* Mix_LoadOGG_RW */ + +/* end of load_ogg.c ... */ + +#endif diff --git a/load_ogg.h b/load_ogg.h new file mode 100644 index 00000000..da97ef45 --- /dev/null +++ b/load_ogg.h @@ -0,0 +1,29 @@ +/* + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + This is the source needed to decode an Ogg Vorbis into a waveform. + This file by Vaclav Slavik (vaclav.slavik@matfyz.cz). +*/ + +/* $Id$ */ + +#ifdef OGG_MUSIC +/* Don't call this directly; use Mix_LoadWAV_RW() for now. */ +SDL_AudioSpec *Mix_LoadOGG_RW (SDL_RWops *src, int freesrc, + SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len); +#endif diff --git a/mixer.c b/mixer.c index 56346c76..efa25c9a 100644 --- a/mixer.c +++ b/mixer.c @@ -33,11 +33,13 @@ #include "SDL_mixer.h" #include "load_aiff.h" #include "load_voc.h" +#include "load_ogg.h" /* Magic numbers for various audio file formats */ #define RIFF 0x46464952 /* "RIFF" */ #define WAVE 0x45564157 /* "WAVE" */ #define FORM 0x4d524f46 /* "FORM" */ +#define OGGS 0x5367674f /* "OggS" */ static int audio_opened = 0; static SDL_AudioSpec mixer; @@ -429,6 +431,12 @@ Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc) loaded = Mix_LoadAIFF_RW(src, freesrc, &wavespec, (Uint8 **)&chunk->abuf, &chunk->alen); break; +#ifdef OGG_MUSIC + case OGGS: + loaded = Mix_LoadOGG_RW(src, freesrc, &wavespec, + (Uint8 **)&chunk->abuf, &chunk->alen); + break; +#endif default: loaded = Mix_LoadVOC_RW(src, freesrc, &wavespec, (Uint8 **)&chunk->abuf, &chunk->alen);