[Change] Re-wrote entire sound system with SDL_mixer.

This commit is contained in:
Allanis 2013-08-23 20:18:04 +01:00
parent ae1cc7c494
commit 897bc36111
12 changed files with 244 additions and 855 deletions

View File

@ -1,6 +1,6 @@
# OPTIONS. # OPTIONS.
DEBUG = 1 DEBUG = 1
#DEBUG_PARANOID = 0 #DEBUG_PARANOID = 1
OS := LINUX OS := LINUX
#OS := WIN32 #OS := WIN32
@ -22,10 +22,8 @@ CLUA = -I../lib/lua
CSDL = $(shell sdl-config --cflags) CSDL = $(shell sdl-config --cflags)
CXML = $(shell xml2-config --cflags) CXML = $(shell xml2-config --cflags)
CTTF = $(shell freetype-config --cflags) CTTF = $(shell freetype-config --cflags)
CAL = -lopenal $(shell freealut-config --cflags)
CVORBIS =
CGL = CGL =
CFLAGS = $(CLUA) $(CPLUTO) $(CSDL) $(CXML) $(CTTF) $(CGL) $(CAL) $(CVORBIS) $(VERSION) -D$(OS) CFLAGS = $(CLUA) $(CSDL) $(CXML) $(CTTF) $(CGL) $(VERSION) -D$(OS)
ifeq ($(OS),LINUX) ifeq ($(OS),LINUX)
CFLAGS += -D_POSIX_SOURCE CFLAGS += -D_POSIX_SOURCE
endif endif
@ -42,14 +40,12 @@ endif
# LDFLAGS. # LDFLAGS.
LDLUA = ../lib/lua/liblua.a LDLUA = ../lib/lua/liblua.a
LDSDL = $(shell sdl-config --libs) -lSDL_image LDSDL = $(shell sdl-config --libs) -lSDL_image -lSDL_mixer
LDXML = $(shell xml2-config --libs) LDXML = $(shell xml2-config --libs)
LDTTF = $(shell freetype-config --libs) LDTTF = $(shell freetype-config --libs)
LDGL = -lGL LDGL = -lGL
LDAL = -lopenal $(shell freealut-config --libs)
LDVORBIS = -lvorbisfile
LDPNG = -lpng LDPNG = -lpng
LDFLAGS = -lm $(LDLUA) $(LDPLUTO) $(LDSDL) $(LDXML) $(LDTTF) $(LDGL) $(LDPNG) $(LDAL) $(LDVORBIS) LDFLAGS = -lm $(LDLUA) $(LDSDL) $(LDXML) $(LDTTF) $(LDGL) $(LDPNG)
# This is just for gstat to run some analysis on performance. # This is just for gstat to run some analysis on performance.
ifdef DEBUG ifdef DEBUG

View File

@ -261,7 +261,7 @@ void conf_parseCLI(int argc, char** argv) {
music_volume(atof(optarg)); music_volume(atof(optarg));
break; break;
case 's': case 's':
sound_volume(atof(optarg)); /*sound_volume(atof(optarg));*/
break; break;
case 'G': case 'G':
nebu_forceGenerate(); nebu_forceGenerate();

View File

@ -129,12 +129,13 @@ int main(int argc, char** argv) {
gtime = SDL_GetTicks(); gtime = SDL_GetTicks();
/* OpenAL sound. */ /* OpenAL sound. */
if(nosound) if(nosound) {
LOG("Sound is disabled!"); LOG("Sound is disabled!");
else { sound_disabled = 1;
music_disabled = 1;
}
if(sound_init()) WARN("Problem setting up sound!"); if(sound_init()) WARN("Problem setting up sound!");
music_choose("load"); music_choose("load");
}
/* Input. */ /* Input. */
if((indjoystick >= 0) || (namjoystick != NULL)) { if((indjoystick >= 0) || (namjoystick != NULL)) {
@ -301,8 +302,6 @@ void unload_all(void) {
* @brief Split main loop from main() for secondary loop hack in toolkit.c. * @brief Split main loop from main() for secondary loop hack in toolkit.c.
*/ */
void main_loop(void) { void main_loop(void) {
sound_update(); /* Do sound stuff. */
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
fps_control(); /* Everyone loves fps control.. */ fps_control(); /* Everyone loves fps control.. */

View File

@ -1,6 +1,4 @@
#include <AL/al.h> #include <SDL_mixer.h>
#include <AL/alc.h>
#include <vorbis/vorbisfile.h>
#include <SDL.h> #include <SDL.h>
#include "llua.h" #include "llua.h"
@ -12,28 +10,12 @@
#include "pack.h" #include "pack.h"
#include "music.h" #include "music.h"
#define MUSIC_STOPPED (1<<1)
#define MUSIC_PLAYING (1<<2)
#define MUSIC_KILL (1<<9)
#define music_is(f) (music_state & f)
#define music_set(f) (music_state |= f)
#define music_rm(f) (music_state ^= f)
#define MUSIC_PREFIX "../snd/music/" #define MUSIC_PREFIX "../snd/music/"
#define MUSIC_SUFFIX ".ogg" #define MUSIC_SUFFIX ".ogg"
#define BUFFER_SIZE (4096 * 8)
#define soundLock() SDL_mutexP(sound_lock)
#define soundUnlock() SDL_mutexV(sound_lock)
#define musicLock() SDL_mutexP(music_vorbis_lock)
#define musicUnlock() SDL_mutexV(music_vorbis_lock)
#define MUSIC_LUA_PATH "../snd/music.lua" #define MUSIC_LUA_PATH "../snd/music.lua"
/* Gobal sound mutex. */ int music_disabled = 0;
extern SDL_mutex* sound_lock;
/* Global music lua. */ /* Global music lua. */
static lua_State* music_lua = NULL; static lua_State* music_lua = NULL;
@ -41,237 +23,67 @@ static lua_State* music_lua = NULL;
static int musicL_load(lua_State* L); static int musicL_load(lua_State* L);
static int musicL_play(lua_State* L); static int musicL_play(lua_State* L);
static int musicL_stop(lua_State* L); static int musicL_stop(lua_State* L);
static int musicL_get(lua_State* L);
static const luaL_reg music_methods[] = { static const luaL_reg music_methods[] = {
{ "load", musicL_load }, { "load", musicL_load },
{ "play", musicL_play }, { "play", musicL_play },
{ "stop", musicL_stop }, { "stop", musicL_stop },
{ "get", musicL_get },
{0, 0} {0, 0}
}; };
/* Saves the music to ram in this structure. */
typedef struct alMusic_ {
char name[64]; /* Name. */
Packfile file;
OggVorbis_File stream;
vorbis_info* info;
ALenum format;
} alMusic;
/* Song currently playing. */
static SDL_mutex* music_vorbis_lock;
static alMusic music_vorbis;
static ALuint music_buffer[2]; /* Front and back buffer. */
static ALuint music_source = 0;
/* What is available? */ /* What is available? */
static char** music_selection = NULL; static char** music_selection = NULL;
static int nmusic_selection = 0; static int nmusic_selection = 0;
/* Volume */ static void* music_data = NULL;
static ALfloat mvolume = 1.; static SDL_RWops* music_rw = NULL;
static Mix_Music* music_music = NULL;
/* Vorbis suff. */
static size_t ovpack_read(void* ptr, size_t size,
size_t nmemb, void* datasource) {
return (ssize_t) pack_read(datasource, ptr, size*nmemb);
}
static int ovpack_retneg(void) { return -1; } /* Must return -1. */
static int ovpack_retzero(void) { return 0; } /* Must return 0. */
ov_callbacks ovcall = {
.read_func = ovpack_read,
.seek_func = (int(*)(void*, ogg_int64_t, int)) ovpack_retneg,
.close_func = (int(*)(void*))ovpack_retzero,
.tell_func = (long(*)(void*))ovpack_retneg
};
/* Music stuff. */ /* Music stuff. */
static int stream_loadBuffer(ALuint buffer);
static int music_find(void); static int music_find(void);
static int music_loadOGG(const char* filename);
static void music_free(void); static void music_free(void);
/* Lua stuff. */ /* Lua stuff. */
static void music_rechoose(void);
static int music_luaInit(void); static int music_luaInit(void);
static void music_luaQuit(void); static void music_luaQuit(void);
/* The thread. */
static unsigned int music_state = 0;
int music_thread(void* unused) {
(void)unused;
int active; /* Active buffer. */
ALint state;
/* Main loop. */
while(!music_is(MUSIC_KILL)) {
if(music_is(MUSIC_PLAYING)) {
if(music_vorbis.file.end == 0)
music_rm(MUSIC_PLAYING);
else {
music_rm(MUSIC_STOPPED);
musicLock(); /* Lock the mutex. */
soundLock();
/* Start playing current song. */
active = 0; /* Load first buffer. */
if(stream_loadBuffer(music_buffer[active])) music_rm(MUSIC_PLAYING);
alSourceQueueBuffers(music_source, 1, &music_buffer[active]);
/* Start playing with buffer laoaded. */
alSourcePlay(music_source);
active = 1; /* Load the second buffer. */
if(stream_loadBuffer(music_buffer[active])) music_rm(MUSIC_PLAYING);
alSourceQueueBuffers(music_source, 1, &music_buffer[active]);
soundUnlock();
active = 0;
}
while(music_is(MUSIC_PLAYING)) {
soundLock();
alGetSourcei(music_source, AL_BUFFERS_PROCESSED, &state);
if(state > 0) {
/* Refill active buffer. */
alSourceUnqueueBuffers(music_source, 1, &music_buffer[active]);
if(stream_loadBuffer(music_buffer[active])) music_rm(MUSIC_PLAYING);
alSourceQueueBuffers(music_source, 1, &music_buffer[active]);
active = 1 - active;
}
soundUnlock();
SDL_Delay(0);
}
soundLock();
alSourceStop(music_source);
alSourceUnqueueBuffers(music_source, 2, music_buffer);
soundUnlock();
musicUnlock();
}
music_set(MUSIC_STOPPED);
SDL_Delay(0); /* We must not kill resources. */
}
return 0;
}
static int stream_loadBuffer(ALuint buffer) {
int size, section, result;
char dat[BUFFER_SIZE]; /* Buffer to hold the data. */
size = 0;
while(size < BUFFER_SIZE) {
/* Fill up the entire data buffer. */
result = ov_read(
&music_vorbis.stream, /* Stream. */
dat + size, /* Data. */
BUFFER_SIZE - size, /* Amount to read. */
0, /* Big endian?. */
2, /* 16 bit. */
1, /* Signed. */
&section); /* Current bitstream. */
if(result == 0) return 1;
else if(result == OV_HOLE) {
WARN("OGG: Vorbis hole detected in music!");
return 0;
}
else if(result == OV_EBADLINK) {
WARN("OGG: Invalid stream section or corrupt link in music!");
return -1;
}
size += result;
if(size == BUFFER_SIZE) break; /* Buffer is full. */
}
/* Load the buffer. */
alBufferData(buffer, music_vorbis.format, dat, BUFFER_SIZE,
music_vorbis.info->rate);
return 0;
}
/* Init/Exit. */ /* Init/Exit. */
int music_init(void) { int music_init(void) {
music_vorbis_lock = SDL_CreateMutex(); if(music_disabled) return 0;
music_vorbis.file.end = 0; /* Indication that it's not loaded.. */
soundLock(); if(music_find() < 0) return -1;
if(music_luaInit() < 0) return -1;
alGenBuffers(2, music_buffer); music_volume(0.7);
alGenSources(1, &music_source);
alSourcef(music_source, AL_GAIN, mvolume);
alSourcef(music_source, AL_ROLLOFF_FACTOR, 0.);
alSourcei(music_source, AL_SOURCE_RELATIVE, AL_FALSE);
/* Start the lua music stuff. */
music_luaInit();
soundUnlock();
return 0; return 0;
} }
int music_makeList(void) {
return music_find();
}
void music_exit(void) { void music_exit(void) {
int i;
/* Free the music. */
alDeleteBuffers(2, music_buffer);
alDeleteSources(1, &music_source);
music_free(); music_free();
/* Free selection */
for(i = 0; i < nmusic_selection; i++)
free(music_selection[i]);
free(music_selection);
/* Bye bye Lua. */
music_luaQuit();
SDL_DestroyMutex(music_vorbis_lock);
} }
/* Internal music loading ruitines. */ /* Free the current playing music. */
static int music_loadOGG(const char* filename) { static void music_free(void) {
/* Free currently loaded ogg. */ if(music_music != NULL) {
music_free(); Mix_HookMusicFinished(NULL);
Mix_HaltMusic();
musicLock(); Mix_FreeMusic(music_music);
/*SDL_FreeRW(music_rw);*/ /*FreeMusic frees it itself. */
/* Set the new name. */ free(music_data);
strncpy(music_vorbis.name, filename, 64); music_music = NULL;
music_vorbis.name[64-1] = '\0'; music_rw = NULL;
music_data = NULL;
/* Load the new ogg. */ }
pack_open(&music_vorbis.file, DATA, filename);
ov_open_callbacks(&music_vorbis.file, &music_vorbis.stream, NULL, 0, ovcall);
music_vorbis.info = ov_info(&music_vorbis.stream, -1);
if(music_vorbis.info->channels == 1) music_vorbis.format = AL_FORMAT_MONO16;
else music_vorbis.format = AL_FORMAT_STEREO16;
musicUnlock();
return 0;
} }
/* Internal music loading routines. */
static int music_find(void) { static int music_find(void) {
char** files; char** files;
uint32_t nfiles, i; uint32_t nfiles, i;
char tmp[64]; char tmp[64];
int len; int len;
if(music_disabled) return 0;
/* Get the file list. */ /* Get the file list. */
files = pack_listfiles(data, &nfiles); files = pack_listfiles(data, &nfiles);
@ -301,64 +113,45 @@ static int music_find(void) {
return 0; return 0;
} }
static void music_free(void) { /* Music control functions. */
musicLock(); int music_volume(const double vol) {
if(music_disabled) return 0;
if(music_vorbis.file.end != 0) { return Mix_VolumeMusic(MIX_MAX_VOLUME*vol);
ov_clear(&music_vorbis.stream);
pack_close(&music_vorbis.file);
music_vorbis.file.end = 0; /* Somewhat ended. */
}
musicUnlock();
}
void music_volume(const double vol) {
if(sound_lock == NULL) return;
/* Sanity check! */
ALfloat fvol = ABS(vol);
if(fvol > 1.) fvol = 1.;
mvolume = fvol;
/* Only needed if playing! */
if(music_set(MUSIC_PLAYING)) {
soundLock();
alSourcef(music_source, AL_GAIN, fvol);
soundUnlock();
}
} }
/* Music control functions. */ /* Music control functions. */
void music_load(const char* name) { void music_load(const char* name) {
if(sound_lock == NULL) return; unsigned int size;
char filename[PATH_MAX];
int i; if(music_disabled) return;
char tmp[64];
music_stop(); music_free();
while(!music_is(MUSIC_STOPPED)) SDL_Delay(0);
for(i = 0; i < nmusic_selection; i++) /* Load the data. */
if(strcmp(music_selection[i], name)==0) { snprintf(filename, PATH_MAX, MUSIC_PREFIX"%s"MUSIC_SUFFIX, name);
snprintf(tmp, 64, MUSIC_PREFIX"%s"MUSIC_SUFFIX, name); music_data = pack_readfile(DATA, filename, &size);
music_loadOGG(tmp); music_rw = SDL_RWFromMem(music_data, size);
return; music_music = Mix_LoadMUS_RW(music_rw);
} if(music_music == NULL)
WARN("Requested load song '%s' but it can't be found in the music stack",name); WARN("SDL_Mixer: %s", Mix_GetError());
Mix_HookMusicFinished(music_rechoose);
} }
void music_play(void) { void music_play(void) {
if(!music_is(MUSIC_PLAYING)) music_set(MUSIC_PLAYING); if(music_music == NULL) return;
if(Mix_FadeInMusic(music_music, 0, 500) < 0)
WARN("SDL_Mixer: %s", Mix_GetError());
} }
void music_stop(void) { void music_stop(void) {
if(music_is(MUSIC_PLAYING)) music_rm(MUSIC_PLAYING); if(music_music == NULL) return;
}
void music_kill(void) { if(Mix_FadeOutMusic(500) < 0)
if(!music_is(MUSIC_KILL)) music_set(MUSIC_KILL); WARN("SDL_Mixer: %s", Mix_GetError());
} }
/* Music lua stuff. */ /* Music lua stuff. */
@ -411,7 +204,7 @@ int lua_loadMusic(lua_State* L, int read_only) {
} }
int music_choose(char* situation) { int music_choose(char* situation) {
if(sound_lock == NULL) return 0; if(music_disabled) return 0;
lua_getglobal(music_lua, "choose"); lua_getglobal(music_lua, "choose");
lua_pushstring(music_lua, situation); lua_pushstring(music_lua, situation);
@ -423,6 +216,11 @@ int music_choose(char* situation) {
return 0; return 0;
} }
/* Attempt to rechoose the music. */
static void music_rechoose(void) {
music_choose("idle");
}
/* The music lua functions. */ /* The music lua functions. */
static int musicL_load(lua_State* L) { static int musicL_load(lua_State* L) {
char* str; char* str;
@ -448,11 +246,3 @@ static int musicL_stop(lua_State* L) {
return 0; return 0;
} }
static int musicL_get(lua_State* L) {
musicLock();
lua_pushstring(L, music_vorbis.name);
musicUnlock();
return 1;
}

View File

@ -1,17 +1,18 @@
#pragma once #pragma once
#include "lua.h" #include "lua.h"
extern int music_disabled;
/* Thread. */ /* Thread. */
int music_thread(void* unused); int music_thread(void* unused);
void music_kill(void); void music_kill(void);
/* Init/Exit. */ /* Init/Exit. */
int music_init(void); int music_init(void);
int music_makeList(void);
void music_exit(void); void music_exit(void);
/* Music control. */ /* Music control. */
void music_volume(const double vol); int music_volume(const double vol);
void music_load(const char* name); void music_load(const char* name);
void music_play(void); void music_play(void);
void music_stop(void); void music_stop(void);

View File

@ -377,6 +377,9 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
xmlNodePtr node; xmlNodePtr node;
char str[PATH_MAX] = "\0"; char str[PATH_MAX] = "\0";
/* Defaults. */
tmp->u.blt.sound = -1;
node = parent->xmlChildrenNode; node = parent->xmlChildrenNode;
do { do {
/* Load all the things. */ /* Load all the things. */
@ -402,7 +405,7 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
#define MELEMENT(o,s) \ #define MELEMENT(o,s) \
if (o) WARN("Outfit '%s' missing/invalid '"s"' element", tmp->name) if (o) WARN("Outfit '%s' missing/invalid '"s"' element", tmp->name)
MELEMENT(tmp->u.blt.gfx_space==NULL, "gfx"); MELEMENT(tmp->u.blt.gfx_space==NULL, "gfx");
MELEMENT((sound_lock!=NULL) && (tmp->u.blt.sound==0), "sound"); MELEMENT((sound_disabled!=NULL) && (tmp->u.blt.sound==0), "sound");
MELEMENT(tmp->u.blt.delay==0, "delay"); MELEMENT(tmp->u.blt.delay==0, "delay");
MELEMENT(tmp->u.blt.speed==0, "speed"); MELEMENT(tmp->u.blt.speed==0, "speed");
MELEMENT(tmp->u.blt.range==0, "range"); MELEMENT(tmp->u.blt.range==0, "range");
@ -464,7 +467,7 @@ static void outfit_parseSAmmo(Outfit* tmp, const xmlNodePtr parent) {
#define MELEMENT(o,s) if(o) WARN("Outfit '%s' missing '"s"' element", tmp->name) #define MELEMENT(o,s) if(o) WARN("Outfit '%s' missing '"s"' element", tmp->name)
MELEMENT(tmp->u.amm.gfx_space == NULL, "gfx"); MELEMENT(tmp->u.amm.gfx_space == NULL, "gfx");
MELEMENT((sound_lock != NULL) && (tmp->u.amm.sound == 0), "sound"); MELEMENT((sound_disabled != NULL) && (tmp->u.amm.sound == 0), "sound");
MELEMENT(tmp->u.amm.thrust==0, "thrust"); MELEMENT(tmp->u.amm.thrust==0, "thrust");
MELEMENT(tmp->u.amm.turn==0, "turn"); MELEMENT(tmp->u.amm.turn==0, "turn");
MELEMENT(tmp->u.amm.speed==0, "speed"); MELEMENT(tmp->u.amm.speed==0, "speed");

View File

@ -68,7 +68,7 @@ typedef struct Outfit_ {
double damage; /* Damage. */ double damage; /* Damage. */
glTexture* gfx_space; glTexture* gfx_space;
ALuint sound; /* Sound to play. */ int sound; /* Sound to play. */
int spfx; /* Special effect on hit. */ int spfx; /* Special effect on hit. */
} blt; } blt;
struct { /* Beam. */ struct { /* Beam. */
@ -94,7 +94,7 @@ typedef struct Outfit_ {
double damage; /* Damage. */ double damage; /* Damage. */
glTexture* gfx_space; glTexture* gfx_space;
ALuint sound; /* Sound to play. */ int sound; /* Sound to play. */
int spfx; /* Special effect on hit. */ int spfx; /* Special effect on hit. */
} amm; } amm;
struct { /* Modification. */ struct { /* Modification. */
@ -112,7 +112,7 @@ typedef struct Outfit_ {
} mod; } mod;
struct { /* Afterburner. */ struct { /* Afterburner. */
double rumble; /* Percent of rumble. */ double rumble; /* Percent of rumble. */
ALuint sound; /* Sound of the afterburner. */ int sound; /* Sound of the afterburner. */
double thrust_perc, thrust_abs; /* Percent and absolute thrust bonus. */ double thrust_perc, thrust_abs; /* Percent and absolute thrust bonus. */
double speed_perc, speed_abs; /* Percent and absolute speed bonus. */ double speed_perc, speed_abs; /* Percent and absolute speed bonus. */
double energy; /* Energy used while active. */ double energy; /* Energy used while active. */

View File

@ -37,10 +37,12 @@
#define TARGET_WIDTH 128 #define TARGET_WIDTH 128
#define TARGET_HEIGHT 96 #define TARGET_HEIGHT 96
#define PLAYER_RESERVED_CHANNELS 4
#define PLAYER_CHANNEL 0
/* Player stuff. */ /* Player stuff. */
Pilot* player = NULL; /* extern in pilot.h */ Pilot* player = NULL; /* extern in pilot.h */
static Ship* player_ship = NULL; /* Temp ship to hold when naming it. */ static Ship* player_ship = NULL; /* Temp ship to hold when naming it. */
static alVoice* player_voice = NULL; /* Player's voice. */
static double player_px, player_py, player_vx, player_vy, player_dir; static double player_px, player_py, player_vx, player_vy, player_dir;
static int player_credits = 0; /* Temp hack. */ static int player_credits = 0; /* Temp hack. */
@ -147,7 +149,7 @@ static void player_newMake(void);
static void player_newShipMake(char* name); static void player_newShipMake(char* name);
/* Sound. */ /* Sound. */
static void player_initSound(void); static void player_initSound(void);
static void player_playSound(ALuint sound, int once); static void player_playSound(int sound, int once);
static void player_stopSound(void); static void player_stopSound(void);
/* Gui. */ /* Gui. */
static void rect_parse(const xmlNodePtr parent, static void rect_parse(const xmlNodePtr parent,
@ -429,23 +431,17 @@ void player_cleanup(void) {
/* Initializes the player sound. */ /* Initializes the player sound. */
static void player_initSound(void) { static void player_initSound(void) {
if(player_voice == NULL) { sound_reserve(PLAYER_RESERVED_CHANNELS);
player_voice = sound_addVoice(0, /* Max priority. */ sound_createGroup(PLAYER_CHANNEL, 0, PLAYER_RESERVED_CHANNELS);
0., 0., 0., 0., 0., /* No properties. */
VOICE_LOOPING | VOICE_STATIC);
}
} }
/* Play a sound. */ /* Play a sound. */
static void player_playSound(ALuint sound, int once) { static void player_playSound(int sound, int once) {
unsigned int flags = VOICE_STATIC; sound_playGroup(PLAYER_CHANNEL, sound, once);
if(once == 0) flags |= VOICE_LOOPING;
voice_buffer(player_voice, sound, flags);
} }
static void player_stopSound(void) { static void player_stopSound(void) {
voice_stop(player_voice); sound_stopGroup(PLAYER_CHANNEL);
} }
void player_message(const char* fmt, ...) { void player_message(const char* fmt, ...) {
@ -1239,10 +1235,6 @@ void player_think(Pilot* pplayer) {
vect_pset(&pplayer->solid->force, pplayer->thrust * player_acc, vect_pset(&pplayer->solid->force, pplayer->thrust * player_acc,
pplayer->solid->dir); pplayer->solid->dir);
/* Set the listener stuff. */
sound_listener(pplayer->solid->dir,
pplayer->solid->pos.x, pplayer->solid->pos.y,
pplayer->solid->vel.x, pplayer->solid->vel.y);
} }
/* Modify the radar resolution. */ /* Modify the radar resolution. */

View File

@ -52,7 +52,7 @@ typedef struct Ship_ {
char* gui; char* gui;
/* Sound. */ /* Sound. */
ALuint sound; int sound;
/* Characteristics. */ /* Characteristics. */
int crew; int crew;

View File

@ -1,7 +1,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <AL/alc.h>
#include <AL/alut.h>
#include <SDL.h> #include <SDL.h>
#include <SDL_mixer.h>
#include <SDL_thread.h> #include <SDL_thread.h>
#include "lephisto.h" #include "lephisto.h"
@ -10,278 +10,121 @@
#include "music.h" #include "music.h"
#include "sound.h" #include "sound.h"
/* ============================================== */ #define SOUND_CHANNEL_MAX 256 /* Overkill. */
/* sound.c controls the routines for using a */
/* virtual voice wrapper system around the openal */
/* library to get 3D sound. */
/* */
/* We only use position sound and no doppler effect */
/* 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_PREFIX "../snd/sounds/"
#define SOUND_SUFFIX ".wav" #define SOUND_SUFFIX ".wav"
#define soundLock() SDL_mutexP(sound_lock) int sound_disabled = 0; /* Whether sound is disabled. */
#define soundUnlock() SDL_mutexV(sound_lock) static int sound_reserved = 0; /* Amount of reserved channels. */
/* Give the buffers a name. */ /* Give the buffers a name. */
typedef struct alSound_ { typedef struct alSound_ {
char* name; /* Buffers name. */ char* name; /* Buffers name. */
ALuint buffer; /* Associated OpenAL buffer. */ Mix_Chunk* buffer;
} alSound; } alSound;
/* Voice private flags (public in sound.h). */
#define VOICE_PLAYING (1<<0) /* Voice is playing. */
#define VOICE_DONE (1<<1) /* Voice is done - must remove. */
#define voice_set(v,f) ((v)->flags |= f)
#define voice_is(v,f) ((v)->flags & f)
/* Global sound lock. */
SDL_mutex* sound_lock = NULL;
/* Gobal device and context. */
static ALCcontext* al_context = NULL;
static ALCdevice* al_device = NULL;
/* Threads. */
static SDL_Thread* music_player = NULL;
/* List of sounds available (All preloaded into a buffer). */ /* List of sounds available (All preloaded into a buffer). */
static alSound* sound_list = NULL; static alSound* sound_list = NULL;
static int nsound_list = 0; static int sound_nlist = 0;
/* Struct to hold all the sources and currently attached voice. */
static ALuint* source_stack = NULL; /* And it's stack. */
static int source_nstack = 0;
/* Virtual voice. */
struct alVoice {
alVoice* next; /* Yes it's a linked list. */
/*ALuint id; // Unique id for the voice. */
ALuint source; /* Source itself, 0 if not set. */
ALuint buffer; /* Buffer. */
int priority; /* Base priority. */
double px, py; /* Position. */
/*double vx, vy; // Velocity. */
unsigned int start; /* time started in ms. */
unsigned int flags; /* Flags to set properties. */
};
static alVoice* voice_start = NULL;
static alVoice* voice_end = NULL;
/* Volume. */
static ALfloat svolume = 0.3;
static int sound_makeList(void); static int sound_makeList(void);
static int sound_load(ALuint* buffer, char* filename); static Mix_Chunk* sound_load(char* filename);
static void sound_free(alSound* snd); static void sound_free(alSound* snd);
static int voice_getSource(alVoice* voc);
static void voice_init(alVoice* voice);
static int voice_play(alVoice* voice);
static void voice_rm(alVoice* prev, alVoice* voice);
static void voice_parseFlags(alVoice* voice, const unsigned int flags);
/* Init the sound subsystem. */
int sound_init(void) { int sound_init(void) {
int mem, ret; int frequency;
ALenum err; Uint16 format;
int channels;
SDL_version compile_version;
const SDL_version* link_version;
ret = 0; if(sound_disabled) return 0;
/* We'll need a mutex. */ SDL_InitSubSystem(SDL_INIT_AUDIO);
sound_lock = SDL_CreateMutex(); if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024) < 0) {
soundLock(); WARN("SDL_Mixer: %s", Mix_GetError());
return -1;
/* Initialize alut - I think it's worth it. */
alutInitWithoutContext(NULL, NULL);
const ALchar* device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
/* Open the default device. */
al_device = alcOpenDevice(NULL);
if(al_device == NULL) {
WARN("Unable to open default sound device");
ret = -1;
goto snderr_dev;
} }
/* Create the OpenAL context. */ Mix_AllocateChannels(SOUND_CHANNEL_MAX);
al_context = alcCreateContext(al_device, NULL);
if(sound_lock == NULL) {
WARN("Unable to create OpenAL context");
ret = -2;
goto snderr_ctx;
}
/* Clear the errors. */
alGetError();
/* Set active context. */
if(alcMakeContextCurrent(al_context)==AL_FALSE) {
WARN("Failure to set default context");
ret = -4;
goto snderr_act;
}
/* Set the master gain. */
alListenerf(AL_GAIN, 1.);
/* Set the distance model. */
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
/* We can unlock now. */
soundUnlock();
/* Start the music server. */
music_init();
/* 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(ALuint) * mem);
}
alGenSources(1, &source_stack[source_nstack]);
source_nstack++;
}
/* Use minimal ram. */
source_stack = realloc(source_stack, sizeof(ALuint) * source_nstack);
/* Debug magic. */ /* Debug magic. */
DEBUG("OpenAL: %s", device); Mix_QuerySpec(&frequency, &format, &channels);
DEBUG("Sources: %d", source_nstack); MIX_VERSION(&compile_version);
DEBUG("Renderer: %s", alGetString(AL_RENDERER)); link_version = Mix_Linked_Version();
DEBUG("Version: %s", alGetString(AL_VERSION)); DEBUG("SDL_Mixer: %d.%d.%d [compiled: %d.%d.%d]",
compile_version.major, compile_version.minor, compile_version.patch,
link_version->major, link_version->minor, link_version->patch);
DEBUG("Format: %d HZ %s", frequency, (channels == 2) ? "Sterio" : "Mono");
DEBUG();
/* Load up all the sounds. */ /* Load up all the sounds. */
sound_makeList(); sound_makeList();
music_makeList(); /* And music. */ sound_volume(0.3);
/* Now start the music thread. */ /* Init the music. */
music_player = SDL_CreateThread(music_thread, NULL); music_init();
return 0; return 0;
snderr_act:
alcDestroyContext(al_context);
snderr_ctx:
al_context = NULL;
alcCloseDevice(al_device);
snderr_dev:
al_device = NULL;
soundUnlock();
SDL_DestroyMutex(sound_lock);
sound_lock = NULL;
ERR("Sound failed to initialize.");
return ret;
} }
/* Clean up after the sound system. */ /* Clean up after the sound system. */
void sound_exit(void) { void sound_exit(void) {
int i; int i;
/* Free the sounds. */ /* Free the sounds. */
for(i = 0; i < nsound_list; i++)
sound_free(&sound_list[i]); sound_free(&sound_list[i]);
free(sound_list); free(sound_list);
sound_list = NULL; sound_list = NULL;
nsound_list = 0;
/* Must stop the music before killing it, */ sound_nlist = 0;
/* then thread should commit suicide. */
if(music_player) {
music_stop();
music_kill();
SDL_WaitThread(music_player, NULL);
music_exit(); music_exit();
}
/* Clean up the voices. */
while(voice_start != NULL)
voice_rm(NULL, voice_start);
/* Clean up the sources. */
if(source_stack)
alDeleteSources(source_nstack, source_stack);
if(sound_lock) {
soundLock();
if(al_context) {
alcMakeContextCurrent(NULL);
alcDestroyContext(al_context);
}
if(al_device) alcCloseDevice(al_device);
soundUnlock();
SDL_DestroyMutex(sound_lock);
}
/* Cya alut! */
alutExit();
} }
/* Get the buffer to sound of [name]. */ /* Get the buffer to sound of name. */
ALuint sound_get(char* name) { int sound_get(char* name) {
if(sound_lock == NULL) return 0;
int i; int i;
for(i = 0; i < nsound_list; i++)
if(sound_disabled) return 0;
for(i = 0; i < sound_nlist; i++)
if(strcmp(name, sound_list[i].name)==0) if(strcmp(name, sound_list[i].name)==0)
return sound_list[i].buffer; return i;
WARN("Sound '%s' not found in sound list", name); WARN("Sound '%s' not found in sound list", name);
return -1;
}
/* Play the sound. */
int sound_play(int sound) {
int channel;
if(sound_disabled) return 0;
if((sound < 0) || (sound > sound_nlist))
return -1;
channel = Mix_PlayChannel(-1, sound_list[sound].buffer, 0);
if(channel < 0)
DEBUG("SDL_Mixer: %s", Mix_GetError());
return 0; return 0;
} }
/* Make list of available sounds. */ /* Make list of available sounds. */
static int sound_makeList(void) { static int sound_makeList(void) {
if(sound_lock == NULL) return 0;
char** files; char** files;
uint32_t nfiles, i; uint32_t nfiles, i;
char tmp[64]; char tmp[64];
int len; int len;
int mem; int mem;
if(sound_disabled) return 0;
/* Get the file list. */ /* Get the file list. */
files = pack_listfiles(data, &nfiles); files = pack_listfiles(data, &nfiles);
@ -293,9 +136,8 @@ static int sound_makeList(void) {
SOUND_SUFFIX, strlen(SOUND_SUFFIX))==0)) { SOUND_SUFFIX, strlen(SOUND_SUFFIX))==0)) {
/* Expand the selection size. */ /* Expand the selection size. */
nsound_list++; sound_nlist++;
if(nsound_list > mem) { if(sound_nlist > mem) { /* We must grow. */
/* We must grow. */
mem += 32; /* We'll overallocate most likely. */ mem += 32; /* We'll overallocate most likely. */
sound_list = realloc(sound_list, mem*sizeof(alSound)); sound_list = realloc(sound_list, mem*sizeof(alSound));
} }
@ -306,325 +148,122 @@ static int sound_makeList(void) {
tmp[len] = '\0'; tmp[len] = '\0';
/* give it the new name. */ /* give it the new name. */
sound_list[nsound_list-1].name = strdup(tmp); sound_list[sound_nlist-1].name = strdup(tmp);
sound_load(&sound_list[nsound_list-1].buffer, files[i]); sound_list[sound_nlist-1].buffer = sound_load(files[i]);
} }
/* Shrink to minimum ram usage. */ /* Shrink to minimum ram usage. */
sound_list = realloc(sound_list, nsound_list*sizeof(alSound)); sound_list = realloc(sound_list, sound_nlist*sizeof(alSound));
/* Free the char* allocated by pack. */ /* Free the char* allocated by pack. */
for(i = 0; i < nfiles; i++) for(i = 0; i < nfiles; i++)
free(files[i]); free(files[i]);
free(files); free(files);
DEBUG("Loaded %d sound%s", nsound_list, (nsound_list==1)?"":"s"); DEBUG("Loaded %d sound%s", sound_nlist, (sound_nlist==1)?"":"s");
return 0; return 0;
} }
/* Loads a sound into the sound_list. */ /* Set the volume. */
static int sound_load(ALuint* buffer, char* filename) { int sound_volume(const double vol) {
if(sound_lock == NULL) return 0; if(sound_disabled) return 0;
return Mix_Volume(-1, MIX_MAX_VOLUME*vol);
}
/* Loads a sound into the sound_list. */
static Mix_Chunk* sound_load(char* filename) {
void* wavdata; void* wavdata;
unsigned int size; unsigned int size;
ALenum err; SDL_RWops* rw;
Mix_Chunk* buffer;
if(sound_disabled) return NULL;
/* Get the file data buffer from the packfile. */ /* Get the file data buffer from the packfile. */
wavdata = pack_readfile(DATA, filename, &size); wavdata = pack_readfile(DATA, filename, &size);
soundLock(); rw = SDL_RWFromMem(wavdata, size);
/* Bind to OpenAL buffer. */ /* Bind to OpenAL buffer. */
(*buffer) = alutCreateBufferFromFileImage(wavdata, size); buffer = Mix_LoadWAV_RW(rw, 1);
if((*buffer) == AL_NONE) WARN("FAILURE: %s", alutGetErrorString(alutGetError()));
/*alGenBuffers(1, buffer); */
/*alBufferData(*buffer, AL_FORMAT_MONO16, wavdata, size, 22050); */
/* Errors? */ if(buffer == NULL)
if((err = alGetError()) != AL_NO_ERROR) { DEBUG("SDL_Mixer: %s", Mix_GetError());
WARN("OpenAL erro '%d' loading sound '%s'.", err, filename);
return 0;
}
soundUnlock();
/* Finish up. */ /* Finish up. */
free(wavdata); free(wavdata);
return 0; return buffer;
} }
static void sound_free(alSound* snd) { static void sound_free(alSound* snd) {
if(sound_lock) return;
soundLock();
/* Free the stuff. */ /* Free the stuff. */
if(snd->name) free(snd->name); if(snd->name) {
alDeleteBuffers(1, &snd->buffer); free(snd->name);
snd->name = NULL;
soundUnlock();
}
/* Update the sounds and prioritize them. */
void sound_update(void) {
ALint state;
alVoice* voice, *prev, *next;
if(sound_lock == NULL) return; /* Sound system is off. */
if(voice_start == NULL) return; /* No voices. */
soundLock();
/* Update sound. */
prev = NULL;
voice = voice_start;
do {
next = voice->next;
/* Get status. */
state = -1;
if(voice->source != 0)
alGetSourcei(voice->source, AL_SOURCE_STATE, &state);
if(!voice_is(voice, VOICE_DONE)) { /* Still working. */
/* Voice has a source. */
if(voice->source != 0) {
/* Update position. */
alSource3f(voice->source, AL_POSITION,
voice->px, voice->py, 0.);
/*alSource3f(voice->source, AL_VELOCITY,
voice->vx, voice->vy, 0.);*/
} }
prev = voice; Mix_FreeChunk(snd->buffer);
}else { snd->buffer = NULL;
/* Delete them. */
if(state != AL_PLAYING)
voice_rm(prev, voice); /* Do not set prev to voice. */
else
prev = voice;
}
voice = next;
} while(voice != NULL);
soundUnlock();
} }
/* Remove a voice. */ /* Reserve num channels. */
static void voice_rm(alVoice* prev, alVoice* voice) { int sound_reserve(int num) {
ALint state;
if(voice->source != 0) { /* Source must exist. */
/* Stop it if playing. */
alGetSourcei(voice->source, AL_SOURCE_STATE, &state);
if(state == AL_PLAYING) alSourceStop(voice->source);
/* Clear it and get rid of it. */
source_stack[source_nstack++] = voice->source; /* Throw it back. */
}
/* Delete from linked list. */
if(prev == NULL) /* Was the first member. */
voice_start = voice->next;
else /* Not first memmber. */
prev->next = voice->next;
if(voice_end == voice) /* Last voice in linked list. */
voice_end = prev;
free(voice);
}
/* Set all the sounds volume to vol. */
void sound_volume(const double vol) {
if(sound_lock == NULL) return;
svolume = (ALfloat) vol;
}
/* Attempt to alloc a source for a voice. */
static int voice_getSource(alVoice* voc) {
int ret; int ret;
/* Sound system isn't on. */ if(sound_disabled) return 0;
if(sound_lock == NULL) return -1;
ret = 0; /* Default return. */ sound_reserved += num;
ret = Mix_ReserveChannels(num);
soundLock(); if(ret != sound_reserved) {
WARN("Unable to reserve %d channels: %s", sound_reserved, Mix_GetError());
/* Try and grab a source. */ return -1;
if(source_nstack > 0) { /* We have the source. */
/* We must pull it from the free source vector. */
voc->source = source_stack[--source_nstack];
/* Initialize and play. */
voice_init(voc);
ret = voice_play(voc);
} else
voc->source = 0;
soundUnlock();
return ret;
}
/* Must lock becore calling. */
static void voice_init(alVoice* voice) {
/* Distance model. */
alSourcef(voice->source, AL_ROLLOFF_FACTOR, SOUND_ROLLOFF_FACTOR);
alSourcef(voice->source, AL_MAX_DISTANCE, SOUND_MAX_DIST);
alSourcef(voice->source, AL_REFERENCE_DISTANCE, SOUND_REFERENCE_DIST);
alSourcef(voice->source, AL_GAIN, svolume);
alSource3f(voice->source, AL_POSITION, voice->px, voice->py, 0.);
/*alSource3f(voice->source, AL_VELOCITY, voice->vx, voice->vy, 0.); */
if(voice_is(voice, VOICE_LOOPING))
alSourcei(voice->source, AL_LOOPING, AL_TRUE);
else
alSourcei(voice->source, AL_LOOPING, AL_FALSE);
}
/* Create a dynamic moving piece. */
alVoice* sound_addVoice(int priority, double px, double py,
double vx, double vy, const ALuint buffer, const unsigned int flags) {
(void)vx;
(void)vy;
alVoice* voc;
if(sound_lock == NULL) return NULL;
/* Allocate the voice. */
voc = malloc(sizeof(alVoice));
/* Set the data. */
voc->next = NULL;
voc->priority = priority;
voc->start = SDL_GetTicks();
voc->buffer = buffer;
/* Handle positions. */
voc->px = px;
voc->py = py;
/*voc->vx = vx; */
/*voc->vy = vy; */
/* Handle the flags. */
voice_parseFlags(voc, flags);
/* Get the source. */
voice_getSource(voc);
if(voice_start == NULL) {
voice_start = voc;
voice_end = voc;
} else {
if(voice_end != NULL)
voice_end->next = voc;
voice_end = voc;
}
return voc;
}
/* Delete the voice. */
void sound_delVoice(alVoice* voice) {
if(sound_lock == NULL) return;
voice_set(voice, VOICE_DONE);
}
/* 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;
if(sound_lock == NULL) return;
voice->px = px;
voice->py = py;
/*voice->vx = vx; */
/*voice->vy = vy; */
}
/* Changes the voice's buffer. */
void voice_buffer(alVoice* voice, const ALuint buffer, const unsigned int flags) {
if(voice == NULL) return;
voice->buffer = buffer;
voice_parseFlags(voice, flags);
/* Start playing. */
soundLock();
voice_play(voice);
soundUnlock();
}
/* Stop playing sound. */
void voice_stop(alVoice* voice) {
if(voice == NULL) return;
soundLock();
if(voice->source != 0)
alSourceStop(voice->source);
soundUnlock();
}
/* Handle flags. */
static void voice_parseFlags(alVoice* voice, const unsigned int flags) {
voice->flags = 0; /* Defaults. */
/* Looping. */
if(flags & VOICE_LOOPING)
voice_set(voice, VOICE_LOOPING);
if(flags & VOICE_STATIC)
alSourcei(voice->source, AL_SOURCE_RELATIVE, AL_TRUE);
else
alSourcei(voice->source, AL_SOURCE_RELATIVE, AL_FALSE);
}
/* Make a voice play. Must lock before calling. */
static int voice_play(alVoice* voice) {
ALenum err;
ALint state;
/* Must have buffer. */
if(voice->buffer != 0) {
alGetSourcei(voice->source, AL_SOURCE_STATE, &state);
if(state == AL_PLAYING)
alSourceStop(voice->source);
/* Set buffer. */
alSourcei(voice->source, AL_BUFFER, voice->buffer);
/* Try to play the source. */
alSourcePlay(voice->source);
err = alGetError();
if(err == AL_NO_ERROR) voice_set(voice, VOICE_PLAYING);
else return 2;
} }
return 0; return 0;
} }
void sound_listener(double dir, double px, double py, double vx, double vy) { /* Create a sound group. */
(void)vx; int sound_createGroup(int tag, int start, int size) {
(void)vy; int ret;
if(sound_lock == NULL) return; if(sound_disabled) return 0;
soundLock(); ret = Mix_GroupChannels(start, start+size-1, tag);
/* Set orientation. */ if(ret != size) {
ALfloat ori[] = { 0., 0., 0., 0., 0., 1. }; WARN("Unable to create sound group: %s", Mix_GetError());
ori[0] = cos(dir); return -1;
ori[1] = sin(dir); }
alListenerfv(AL_ORIENTATION, ori);
alListener3f(AL_POSITION, px, py, 1.);
/*alListener3f(AL_VELOCITY, vx, vy, 0.); */
soundUnlock(); return 0;
}
/* Play a sound in a group. */
int sound_playGroup(int group, int sound, int once) {
int ret, channel;
if(sound_disabled) return 0;
channel = Mix_GroupAvailable(group);
ret = Mix_PlayChannel(channel, sound_list[sound].buffer,
(once == 0) ? -1 : 0);
if(ret < 0) {
WARN("Unable to play sound %d for group %d: %s",
sound, group, Mix_GetError());
return -1;
}
return 0;
}
/* Stop all the sounds in a group. */
void sound_stopGroup(int group) {
if(sound_disabled) return;
Mix_FadeOutGroup(group, 100);
} }

View File

@ -1,32 +1,19 @@
#pragma once #pragma once
#include <AL/al.h>
#include "physics.h"
#define VOICE_LOOPING (1<<10) /* Voice loops. */ extern int sound_disabled;
#define VOICE_STATIC (1<<11) /* Voice isn't relative. */
struct alVoice;
typedef struct alVoice alVoice;
/* Sound subsystem. */ /* Sound subsystem. */
int sound_init(void); int sound_init(void);
void sound_exit(void); void sound_exit(void);
void sound_update(void);
/* Sound manupulation functions. */ /* Sound manupulation functions. */
ALuint sound_get(char* name); int sound_get(char* name);
void sound_volume(const double vol); int sound_volume(const double vol);
int sound_play(int sound);
/* Voice manipulation function. */ /* Group functions. */
alVoice* sound_addVoice(int priority, double px, double py, int sound_reserve(int num);
double vx, double vy, const ALuint buffer, const unsigned int flags); int sound_createGroup(int tag, int start, int size);
int sound_playGroup(int group, int sound, int once);
void sound_delVoice(alVoice* voice); /* Delete voice. */ void sound_stopGroup(int group);
void voice_update(alVoice* voice, double px, double py, double vx, double vy);
void voice_buffer(alVoice* voice, const ALuint buffer, const unsigned int flags);
void voice_stop(alVoice* voice);
/* Listener manipulation. */
void sound_listener(double dir, double px, double py, double vx, double vy);

View File

@ -15,10 +15,6 @@
#define weapon_isSmart(w) (w->think != NULL) #define weapon_isSmart(w) (w->think != NULL)
#define VOICE_PRIORITY_BOLT 10 /* Default. */
#define VOICE_PRIORITY_AMMO 8 /* Higher. */
#define VOICE_PRIORITY_BEAM 6 /* Even higher. */
#define WEAPON_CHUNK 128 /* Size to increment array with. */ #define WEAPON_CHUNK 128 /* Size to increment array with. */
/* Weapon status. */ /* Weapon status. */
@ -47,8 +43,6 @@ typedef struct Weapon_ {
double lockon; /* Some weapons have a lockon delay. */ double lockon; /* Some weapons have a lockon delay. */
double timer; /* Mainly used to see when the weapon was fired. */ double timer; /* Mainly used to see when the weapon was fired. */
alVoice* voice; /* Virtual voise. */
/* Update position and render. */ /* Update position and render. */
void(*update)(struct Weapon_*, const double, WeaponLayer); /* Position update and render. */ void(*update)(struct Weapon_*, const double, WeaponLayer); /* Position update and render. */
void(*think)(struct Weapon_*, const double); /* Some missiles need to be inteligent.a */ void(*think)(struct Weapon_*, const double); /* Some missiles need to be inteligent.a */
@ -350,11 +344,6 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) {
if(weapon_isSmart(w)) (*w->think)(w,dt); if(weapon_isSmart(w)) (*w->think)(w,dt);
(*w->solid->update)(w->solid, dt); (*w->solid->update)(w->solid, dt);
/* Update the sound. */
if(w->voice)
voice_update(w->voice, w->solid->pos.x, w->solid->pos.y,
w->solid->vel.x, w->solid->vel.y);
} }
/* Good shot. */ /* Good shot. */
@ -439,10 +428,7 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
vect_cadd(&v, outfit->u.blt.speed*cos(rdir), outfit->u.blt.speed*sin(rdir)); vect_cadd(&v, outfit->u.blt.speed*cos(rdir), outfit->u.blt.speed*sin(rdir));
w->timer += outfit->u.blt.range/outfit->u.blt.speed; w->timer += outfit->u.blt.range/outfit->u.blt.speed;
w->solid = solid_create(mass, rdir, pos, &v); w->solid = solid_create(mass, rdir, pos, &v);
w->voice = sound_addVoice(VOICE_PRIORITY_BOLT, sound_play(w->outfit->u.blt.sound);
w->solid->pos.x, w->solid->pos.y,
w->solid->vel.x, w->solid->vel.y,
w->outfit->u.blt.sound, 0);
break; break;
/* Treat seekers togther. */ /* Treat seekers togther. */
@ -452,9 +438,6 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
w->lockon = outfit->u.amm.lockon; w->lockon = outfit->u.amm.lockon;
w->timer = outfit->u.amm.duration; w->timer = outfit->u.amm.duration;
w->solid = solid_create(mass, dir, pos, vel); w->solid = solid_create(mass, dir, pos, vel);
w->voice = sound_addVoice(VOICE_PRIORITY_AMMO,
w->solid->pos.x, w->solid->pos.y,
w->solid->vel.x, w->solid->vel.y, w->outfit->u.amm.sound, 0);
/* If they are seeking a pilot, increment lockon counter. */ /* If they are seeking a pilot, increment lockon counter. */
pilot_target = pilot_get(target); pilot_target = pilot_get(target);
@ -467,11 +450,11 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
w->think = think_seeker; w->think = think_seeker;
else if(outfit->type == OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO) else if(outfit->type == OUTFIT_TYPE_MISSILE_SEEK_SMART_AMMO)
w->think = think_smart;*/ w->think = think_smart;*/
sound_play(w->outfit->u.amm.sound);
break; break;
/* Just dump it where the player is. */ /* Just dump it where the player is. */
default: default:
w->voice = NULL;
w->solid = solid_create(mass, dir, pos, vel); w->solid = solid_create(mass, dir, pos, vel);
break; break;
} }
@ -562,7 +545,6 @@ static void weapon_destroy(Weapon* w, WeaponLayer layer) {
/* Clear the weapon. */ /* Clear the weapon. */
static void weapon_free(Weapon* w) { static void weapon_free(Weapon* w) {
sound_delVoice(w->voice);
solid_free(w->solid); solid_free(w->solid);
free(w); free(w);
} }