aboutsummaryrefslogtreecommitdiff
path: root/src/audio.c
diff options
context:
space:
mode:
authortaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-06-21 22:44:23 +0000
committertaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-06-21 22:44:23 +0000
commit64da6785055883485f3a5387f5ab88939df21c1f (patch)
tree4d46ff7930d0c84f3cd736c409910c988f14a142 /src/audio.c
parent9a20ad0fc1a844371054cd8a1fa350d8949b5b1d (diff)
Basic audio framework
git-svn-id: svn://cook.msm.cam.ac.uk:745/thrust3d/thrust3d@105 84d2e878-0bd5-11dd-ad15-13eda11d74c5
Diffstat (limited to 'src/audio.c')
-rw-r--r--src/audio.c128
1 files changed, 123 insertions, 5 deletions
diff --git a/src/audio.c b/src/audio.c
index 1e807b5..d772f6a 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -13,22 +13,140 @@
#include <config.h>
#endif
+#include <SDL.h>
+#include <SDL_audio.h>
+
#include "types.h"
-/* OpenGL initial setup */
+void audio_mix(void *data, Uint8 *stream, int len) {
+
+ AudioContext *a = data;
+ int i;
+ Uint32 amount;
+ size_t j;
+
+ for ( j=0; j<len; j++ ) {
+ stream[j] = 0;
+ }
+
+ for ( i=0; i<AUDIO_MAX_SOUNDS; i++ ) {
+
+ if ( !a->sounds[i].inuse ) continue;
+
+ amount = (a->sounds[i].dlen - a->sounds[i].dpos);
+ if ( amount > len ) {
+ /* The sound remaining in this channel more than fills the buffer */
+ amount = len;
+ }
+
+ for ( j=0; j<amount; j++ ) {
+ stream[j] += a->sounds[i].data[a->sounds[i].dpos + j];
+ }
+
+ a->sounds[i].dpos += amount;
+ if ( a->sounds[i].dpos == a->sounds[i].dlen ) {
+ if ( a->sounds[i].repeat ) {
+ a->sounds[i].dpos = 0;
+ } else {
+ a->sounds[i].inuse = 0;
+ free(a->sounds[i].data);
+ }
+ }
+
+ }
+
+}
+
+void audio_play(AudioContext *a, char *file, float volume) {
+
+ int idx, i;
+ SDL_AudioSpec wave;
+ Uint8 *data;
+ Uint32 dlen;
+ SDL_AudioCVT cvt;
+ char filename[128];
+
+ /* Look for an empty (or finished) sound slot */
+ for ( idx=0; idx<AUDIO_MAX_SOUNDS; idx++ ) {
+ if ( a->sounds[idx].dpos == a->sounds[idx].dlen ) break;
+ }
+ if ( idx == AUDIO_MAX_SOUNDS ) {
+ fprintf(stderr, "Not enough audio channels to play '%s'\n", file);
+ return;
+ }
+
+ snprintf(filename, 127, "%s%s.wav", DATADIR"/sound/", file);
+
+ /* Load the sound file and convert it to 16-bit stereo at 22kHz */
+ if ( SDL_LoadWAV(filename, &wave, &data, &dlen) == NULL ) {
+ fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
+ return;
+ }
+ SDL_BuildAudioCVT(&cvt, wave.format, wave.channels, wave.freq, AUDIO_S16, 2, 22050);
+ cvt.buf = malloc(dlen*cvt.len_mult);
+ memcpy(cvt.buf, data, dlen);
+ cvt.len = dlen;
+ SDL_ConvertAudio(&cvt);
+ SDL_FreeWAV(data);
+
+ /* Perform volume adjustment here */
+ int16_t *aud = (int16_t *)cvt.buf;
+ for ( i=0; i<dlen/2; i++ ) {
+ float samp = aud[i];
+ samp *= volume;
+ aud[i] = samp;
+ }
+
+ /* Put the sound data in the slot */
+ SDL_LockAudio();
+ a->sounds[idx].data = cvt.buf;
+ a->sounds[idx].dlen = cvt.len_cvt;
+ a->sounds[idx].dpos = 0;
+ a->sounds[idx].inuse = 1;
+ a->sounds[idx].repeat = 1;
+ SDL_UnlockAudio();
+
+}
+
+/* SDL audio initial setup */
AudioContext *audio_setup() {
- AudioContext *ctx;
+ AudioContext *a;
+ SDL_AudioSpec fmt;
+ int i;
+
+ a = malloc(sizeof(AudioContext));
+ if ( a == NULL ) return NULL;
+
+ for ( i=0; i<AUDIO_MAX_SOUNDS; i++ ) {
+ a->sounds[i].inuse = 0;
+ }
+
+ /* Set 16-bit stereo audio at 22Khz */
+ fmt.freq = 22050;
+ fmt.format = AUDIO_S16;
+ fmt.channels = 2;
+ fmt.samples = 512;
+ fmt.callback = audio_mix;
+ fmt.userdata = a;
+ fmt.silence = 0;
- ctx = malloc(sizeof(AudioContext));
- if ( ctx == NULL ) return NULL;
+ /* Open the audio device and start playing sound! */
+ if ( SDL_OpenAudio(&fmt, NULL) < 0 ) {
+ fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError());
+ free(a);
+ return NULL;
+ }
+ SDL_PauseAudio(0);
+ audio_play(a, "moan", 0.4);
- return ctx;
+ return a;
}
void audio_shutdown(AudioContext *ctx) {
+ SDL_CloseAudio();
free(ctx);
}