[Add] Sound System [Phase 1] Cleaned up and made a few fixed ready for [phase 2.]
This commit is contained in:
parent
65e25f6ce0
commit
6870dd2057
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -6,6 +6,7 @@ void music_kill(void);
|
||||
|
||||
// Init/Exit.
|
||||
int music_init(void);
|
||||
int music_makeList(void);
|
||||
void music_exit(void);
|
||||
|
||||
// Music control.
|
||||
|
130
src/sound.c
130
src/sound.c
@ -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);
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user