aboutsummaryrefslogtreecommitdiff
path: root/src/audio.c
diff options
context:
space:
mode:
authortaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-06-30 11:50:04 +0000
committertaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-06-30 11:50:04 +0000
commitf65ea1c43238b6e75c49a87b3aee3156fd00343e (patch)
treee7defa4d9693bd8d0c65909a6414fa6e8079a5e3 /src/audio.c
parent5be16d1333327c22f9e61e03de1d478fa56ae5c5 (diff)
Interface to libvorbis :)
git-svn-id: svn://cook.msm.cam.ac.uk:745/thrust3d/thrust3d@121 84d2e878-0bd5-11dd-ad15-13eda11d74c5
Diffstat (limited to 'src/audio.c')
-rw-r--r--src/audio.c126
1 files changed, 115 insertions, 11 deletions
diff --git a/src/audio.c b/src/audio.c
index c71b995..dc89927 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -13,8 +13,13 @@
#include <config.h>
#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
#include <SDL.h>
#include <SDL_audio.h>
+#include <vorbis/vorbisfile.h>
+#include <vorbis/codec.h>
#include "types.h"
@@ -24,7 +29,7 @@ static void audio_mix(void *data, Uint8 *stream8, int len) {
int i, j, clip_count;
Sint16 *stream = (Sint16 *)stream8;
- len /= 2; /* Samples */
+ len /= 2; /* Number of samples to write */
/* Zero the buffer */
for ( j=0; j<len; j++ ) {
@@ -88,30 +93,27 @@ static void audio_mix(void *data, Uint8 *stream8, int len) {
}
-void audio_play(AudioContext *a, char *file, float volume, int repeat) {
+static void audio_play_wav(AudioContext *a, char *filename, float volume, int repeat) {
int idx;
SDL_AudioSpec wave;
Uint8 *data;
Uint32 dlen;
SDL_AudioCVT cvt;
- char filename[128];
/* Look for an empty sound slot */
for ( idx=0; idx<AUDIO_MAX_SOUNDS; idx++ ) {
if ( !a->sounds[idx].inuse ) break;
}
- if ( a->debug ) printf("AU: Selected channel %i for sound '%s'\n", idx, file);
+ if ( a->debug ) printf("AU: Selected channel %i for sound '%s'\n", idx, filename);
if ( idx == AUDIO_MAX_SOUNDS ) {
- fprintf(stderr, "Not enough audio channels to play '%s'\n", file);
+ fprintf(stderr, "Not enough audio channels to play '%s'\n", filename);
return;
}
- snprintf(filename, 127, "%s%s.wav", DATADIR"/sound/", file);
-
- /* Load the sound file and convert it to 16-bit stereo at 22kHz */
+ /* Load the sound file and convert it to 16-bit stereo at 44.1 kHz */
if ( SDL_LoadWAV(filename, &wave, &data, &dlen) == NULL ) {
- fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
+ fprintf(stderr, "Couldn't load %s: %s\n", filename, SDL_GetError());
return;
}
SDL_BuildAudioCVT(&cvt, wave.format, wave.channels, wave.freq, AUDIO_S16, 2, 44100);
@@ -133,6 +135,107 @@ void audio_play(AudioContext *a, char *file, float volume, int repeat) {
}
+static void audio_play_vorbis(AudioContext *a, char *filename, float volume, int repeat) {
+
+ int idx;
+ char *data;
+ int len;
+ OggVorbis_File vf;
+ vorbis_info *vi;
+ int finished, err, current_section;
+ size_t offs;
+ SDL_AudioCVT cvt;
+
+ /* Look for an empty sound slot */
+ for ( idx=0; idx<AUDIO_MAX_SOUNDS; idx++ ) {
+ if ( !a->sounds[idx].inuse ) break;
+ }
+ if ( a->debug ) printf("AU: Selected channel %i for sound '%s'\n", idx, filename);
+ if ( idx == AUDIO_MAX_SOUNDS ) {
+ fprintf(stderr, "Not enough audio channels to play '%s'\n", filename);
+ return;
+ }
+
+ err = ov_fopen(filename, &vf);
+ if ( err != 0 ) {
+ fprintf(stderr, "Couldn't open Vorbis file '%s' (code %i,%i)\n", filename, err, errno);
+ return;
+ }
+
+ len = ov_pcm_total(&vf, -1); /* Length in samples 'per channel' */
+ if ( a->debug ) printf("AU: Length is %i samples 'per channel'\n", len);
+ vi = ov_info(&vf,-1);
+ if ( a->debug ) printf("AU: %i channels, %li Hz\n", vi->channels, vi->rate);
+ data = malloc(vi->channels*2*len); /* Two bytes per sample per channel */
+
+ offs = 0;
+ finished = 0;
+ if ( a->debug ) printf("AU: Decoding Vorbis stream...\n");
+ while ( finished == 0 ) {
+ long rval;
+ rval = ov_read(&vf, data+offs, 2*2*len, 0, 2, 1, &current_section);
+ if ( rval == 0 ) {
+ finished = 1;
+ } else if ( rval < 0 ) {
+ fprintf(stderr, "Vorbis stream error\n");
+ } else {
+ offs += rval;
+ }
+ }
+
+ /* Convert to 44.1 kHz */
+ SDL_BuildAudioCVT(&cvt, AUDIO_S16, vi->channels, vi->rate, AUDIO_S16, 2, 44100);
+ cvt.buf = malloc(vi->channels*2*len*cvt.len_mult);
+ memcpy(cvt.buf, data, vi->channels*2*len);
+ cvt.len = vi->channels*2*len;
+ SDL_ConvertAudio(&cvt);
+
+ ov_clear(&vf);
+
+ /* Put the sound data in the slot */
+ SDL_LockAudio();
+ a->sounds[idx].data = (Sint16 *)cvt.buf;
+ a->sounds[idx].dlen = cvt.len_cvt / 2;
+ a->sounds[idx].dpos = 0;
+ a->sounds[idx].inuse = 1;
+ a->sounds[idx].repeat = repeat;
+ a->sounds[idx].volume = volume;
+ SDL_UnlockAudio();
+
+}
+
+void audio_play(AudioContext *a, char *name, float volume, int repeat) {
+
+ char filename[128];
+ struct stat statbuf;
+
+ /* Try to find an Ogg/Vorbis file */
+ snprintf(filename, 127, "%s%s.ogg", DATADIR"/sound/", name);
+ if ( stat(filename, &statbuf) == 0 ) {
+ audio_play_vorbis(a, filename, volume, repeat);
+ goto done;
+ }
+
+ /* Try to find a WAV file */
+ snprintf(filename, 127, "%s%s.wav", DATADIR"/sound/", name);
+ if ( stat(filename, &statbuf) == 0 ) {
+ audio_play_wav(a, filename, volume, repeat);
+ goto done;
+ }
+
+ /* Still not found */
+ fprintf(stderr, "Couldn't find file for sound '%s'\n", name);
+ return;
+
+done: /* Success */
+ if ( a->paused == 1 ) {
+ SDL_PauseAudio(0);
+ a->paused = 0;
+ }
+ return;
+
+}
+
/* SDL audio initial setup */
AudioContext *audio_setup(int debug) {
@@ -148,6 +251,7 @@ AudioContext *audio_setup(int debug) {
a->debug = debug;
a->startup = 1;
a->startup_volume = 0.0;
+ a->paused = 1;
for ( i=0; i<AUDIO_MAX_SOUNDS; i++ ) {
a->sounds[i].inuse = 0;
}
@@ -166,9 +270,9 @@ AudioContext *audio_setup(int debug) {
free(a);
return NULL;
}
- SDL_PauseAudio(0);
- audio_play(a, "moan", 0.4, 1);
+ audio_play(a, "kraftwerk", 1.0, 1);
+// audio_play(a, "moan", 0.4, 1);
return a;