[Add] Sound System [Phase 1] Cleaned up and made a few fixed ready for [phase 2.]

This commit is contained in:
Allanis 2013-06-04 16:08:59 +01:00
parent 65e25f6ce0
commit 6870dd2057
5 changed files with 112 additions and 30 deletions

View File

@ -128,6 +128,8 @@ int conf_loadConfig(const char* file) {
conf_loadInt("afterburn", input_afterburnSensibility);
// Sound.
conf_loadBool("nosound", i);
nosound = i; i = 0;
conf_loadFloat("sound", d);
if(d) { sound_volume(d); d = 0.; }
conf_loadFloat("music", d);

View File

@ -169,7 +169,6 @@ static int stream_loadBuffer(ALuint buffer) {
// Init/Exit.
int music_init(void) {
music_vorbis_lock = SDL_CreateMutex();
music_find();
music_vorbis.file.end = 0; // Indication that it's not loaded..
SDL_mutexP(sound_lock);
@ -185,6 +184,10 @@ int music_init(void) {
return 0;
}
int music_makeList(void) {
return music_find();
}
void music_exit(void) {
int i;

View File

@ -6,6 +6,7 @@ void music_kill(void);
// Init/Exit.
int music_init(void);
int music_makeList(void);
void music_exit(void);
// Music control.

View File

@ -18,6 +18,37 @@
// right now.
// ==============================================
// ==============================================
// Sound Overview:
// ---------------
//
// We use a priority virtual voice system with
// pre-allocated buffers.
//
// Nameing:
// -- buffer - Sound sample.
// -- source - openal object that plays sound.
// -- voice - Virtual object that wants to play sound.
//
// First we allocate all the buffers based on what
// we find inside the datafile.
// Then we allocate all the possible sources (giving
// the music system what it needs).
// Now we allow the user to dynamically create
// voices, these voices will always try to grab
// a source from the source pool. If they can't,
// they will pretend to play the buffer.
// Every so often we'll check to see if the important
// voices are being played and take away the sources
// from the lesser ones.
// ==============================================
// Sound parameters - TODO: make it variable per source.
#define SOUND_ROLLOFF_FACTOR 1.
#define SOUND_REFERENCE_DIST 500.
#define SOUND_MAX_DIST 1000.
#define SOUND_PREFIX "../snd/sounds/"
#define SOUND_SUFFIX ".wav"
@ -29,6 +60,7 @@ typedef struct alSound_ {
#define VOICE_PLAYING (1<<0) // Voice is playing.
#define VOICE_LOOPING (1<<1) // Voice is looping.
#define VOICE_DONE (1<<2) // Voice is done - must remove.
#define voice_set(v,f) ((v)->flags |= f)
#define voice_is(v,f) ((v)->flags & f)
@ -46,10 +78,18 @@ static SDL_Thread* music_player = NULL;
static alSound* sound_list = NULL;
static int nsound_list = 0;
// Current sources playing.
typedef struct VoiceSource_ {
ALuint source; // Allocated source.
ALuint voice; // Voice id.
} VoiceSource;
static VoiceSource* source_stack = NULL; // And it's stack.
static int source_nstack = 0;
// Virtual voice stack.
static alVoice** voice_stack = NULL;
static int nvoice_stack = 0;
static int mvoice_stack = 0;
static int voice_nstack = 0;
static int voice_mstack = 0;
#define VOICE_CHUNK 64 // Allocate by these chunks.
// Volume.
static ALfloat svolume = 0.3;
@ -60,13 +100,16 @@ static void sound_free(alSound* snd);
static int voice_getSource(alVoice* voc);
int sound_init(void) {
int ret = 0;
int mem, ret = 0;
ALenum err;
ret = 0;
// We'll need a mutex.
sound_lock = SDL_CreateMutex();
SDL_mutexP(sound_lock);
const ALchar* device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
DEBUG("OpenAL using device '%s'", device);
// Open the default device.
al_device = alcOpenDevice(NULL);
if(al_device == NULL) {
@ -99,15 +142,43 @@ int sound_init(void) {
// Set the distance model.
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
// We can unlock now.
SDL_mutexV(sound_lock);
// Load up all the sounds.
sound_makeList();
// Start the music server.
music_init();
music_player = SDL_CreateThread(music_thread, NULL);
// Start allocating the sources - music has already taken this.
alGetError(); // Another error clear.
mem = 0;
while(((err = alGetError()) == AL_NO_ERROR) && (source_nstack < 128)) {
if(mem < source_nstack+1) {
// Allocate more memory.
mem += 32;
source_stack = realloc(source_stack, sizeof(VoiceSource) * mem);
}
alGenSources(1, &source_stack[source_nstack].source);
source_stack[source_nstack].voice = 0;
source_nstack++;
}
// Use minimal ram.
source_stack = realloc(source_stack, sizeof(VoiceSource) * source_nstack);
// Debug magic.
DEBUG("OpenAL: %s", device);
DEBUG("Sources: %d", source_nstack);
DEBUG("Renderer: %s", alGetString(AL_RENDERER));
DEBUG("Version: %s", alGetString(AL_VERSION));
// Load up all the sounds.
sound_makeList();
music_makeList(); // And music.
// Now start the music thread.
music_player = SDL_CreateThread(music_thread, NULL);
return 0;
snderr_act:
@ -120,6 +191,7 @@ snderr_dev:
SDL_mutexV(sound_lock);
SDL_DestroyMutex(sound_lock);
sound_lock = NULL;
ERR("Sound failed to initialize.");
return ret;
}
@ -245,6 +317,7 @@ static void sound_free(alSound* snd) {
SDL_mutexP(sound_lock);
// Free the stuff.
if(snd->name) free(snd->name);
alDeleteBuffers(1, &snd->buffer);
@ -256,11 +329,9 @@ void sound_update(void) {
if(sound_lock == NULL) return;
int i;
// TODO: Prioritize the things.
SDL_mutexP(sound_lock);
for(i = 0; i < nvoice_stack; i++) {
for(i = 0; i < voice_nstack; i++) {
if(voice_is(voice_stack[i], VOICE_PLAYING)) {
// Update position.
alSource3f(voice_stack[i]->source, AL_POSITION,
@ -282,7 +353,7 @@ void sound_volume(const double vol) {
svolume = (ALfloat) vol;
SDL_mutexP(sound_lock);
for(i = 0; i < nvoice_stack; i++)
for(i = 0; i < voice_nstack; i++)
if(voice_set(voice_stack[i], VOICE_PLAYING))
alSourcef(voice_stack[i]->source, AL_GAIN, svolume);
SDL_mutexV(sound_lock);
@ -311,8 +382,9 @@ static int voice_getSource(alVoice* voc) {
alSourcei(voc->source, AL_BUFFER, voc->buffer);
// Distance model.
alSourcef(voc->source, AL_MAX_DISTANCE, 200.);
alSourcef(voc->source, AL_REFERENCE_DISTANCE, 50.);
alSourcef(voc->source, AL_ROLLOFF_FACTOR, SOUND_ROLLOFF_FACTOR);
alSourcef(voc->source, AL_MAX_DISTANCE, SOUND_MAX_DIST);
alSourcef(voc->source, AL_REFERENCE_DISTANCE, SOUND_REFERENCE_DIST);
alSourcei(voc->source, AL_SOURCE_RELATIVE, AL_FALSE);
alSourcef(voc->source, AL_GAIN, svolume);
@ -339,23 +411,22 @@ alVoice* sound_addVoice(int priority, double px, double py, double vx, double vy
(void)vx;
(void)vy;
alVoice* voc;
if(sound_lock == NULL) return NULL;
alVoice* voc;
nvoice_stack++;
if(nvoice_stack > mvoice_stack)
voice_stack = realloc(voice_stack, ++mvoice_stack*sizeof(alVoice*));
voice_nstack++;
if(voice_nstack > voice_mstack)
voice_stack = realloc(voice_stack, ++voice_mstack*sizeof(alVoice*));
voc = malloc(sizeof(alVoice));
voice_stack[nvoice_stack-1] = voc;
voice_stack[voice_nstack-1] = voc;
// Set the data.
voc->priority = priority;
voc->start = SDL_GetTicks();
voc->buffer = buffer;
if(looping) voice_set(voc, VOICE_LOOPING);
if(looping != 0) voice_set(voc, VOICE_LOOPING);
voc->px = px;
voc->py = py;
//voc->vx = vx;
@ -371,21 +442,26 @@ void sound_delVoice(alVoice* voice) {
ALint stat;
int i;
for(i = 0; i < nvoice_stack; i++)
// Linear search.
for(i = 0; i < voice_nstack; i++)
if(voice == voice_stack[i])
break;
// No match found.
if(i >= nvoice_stack) {
if(i >= voice_nstack) {
WARN("Unable to find voice to free from stack");
return;
}
// Source must exist.
if(voice->source) {
SDL_mutexP(sound_lock);
// Stop it if playing.
alGetSourcei(voice->source, AL_SOURCE_STATE, &stat);
if(stat == AL_PLAYING) alSourceStop(voice->source);
// Clear it and get rid of it.
alDeleteSources(1, &voice->source);
voice->source = 0;
@ -393,11 +469,12 @@ void sound_delVoice(alVoice* voice) {
}
free(voice_stack[i]);
nvoice_stack--;
for(; i < nvoice_stack; i++)
voice_nstack--;
for(; i < voice_nstack; i++)
voice_stack[i] = voice_stack[i+1];
}
// Update voice position, should be run once per frame.
void voice_update(alVoice* voice, double px, double py, double vx, double vy) {
(void) vx;
(void) vy;
@ -418,11 +495,12 @@ void sound_listener(double dir, double px, double py, double vx, double vy) {
SDL_mutexP(sound_lock);
// Set orientation.
ALfloat ori[] = { 0., 0., 0., 0., 0., 1. };
ori[0] = cos(dir);
ori[1] = sin(dir);
alListenerfv(AL_ORIENTATION, ori);
alListener3f(AL_POSITION, px, py, 0.);
alListener3f(AL_POSITION, px, py, 1.);
//alListener3f(AL_VELOCITY, vx, vy, 0.);
SDL_mutexV(sound_lock);

View File

@ -2,11 +2,9 @@
#include <AL/al.h>
#include "physics.h"
#define SOUND_REFERENCE_DIST 500.
#define SOUND_MAX_DIST 1000.
// Virtual voice.
typedef struct alVoice_ {
ALuint id; // Unique id for the voice.
ALuint source; // Source itself, 0 if not set.
ALuint buffer; // Buffer.