diff options
author | taw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5> | 2008-06-21 22:44:23 +0000 |
---|---|---|
committer | taw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5> | 2008-06-21 22:44:23 +0000 |
commit | 64da6785055883485f3a5387f5ab88939df21c1f (patch) | |
tree | 4d46ff7930d0c84f3cd736c409910c988f14a142 /src | |
parent | 9a20ad0fc1a844371054cd8a1fa350d8949b5b1d (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')
-rw-r--r-- | src/audio.c | 128 | ||||
-rw-r--r-- | src/types.h | 8 |
2 files changed, 131 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); } diff --git a/src/types.h b/src/types.h index e997a6a..5b4b0a6 100644 --- a/src/types.h +++ b/src/types.h @@ -143,8 +143,16 @@ typedef struct { } RenderContext; +#define AUDIO_MAX_SOUNDS 16 typedef struct { + struct sound { + Uint8 *data; + int dpos; + int dlen; + int inuse; + int repeat; + } sounds[AUDIO_MAX_SOUNDS]; } AudioContext; |