[Change] Re-wrote entire sound system with SDL_mixer.
This commit is contained in:
parent
ae1cc7c494
commit
897bc36111
12
bin/Makefile
12
bin/Makefile
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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.. */
|
||||||
|
320
src/music.c
320
src/music.c
@ -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. */
|
|
||||||
§ion); /* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
|
@ -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. */
|
||||||
|
26
src/player.c
26
src/player.c
@ -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. */
|
||||||
|
@ -52,7 +52,7 @@ typedef struct Ship_ {
|
|||||||
char* gui;
|
char* gui;
|
||||||
|
|
||||||
/* Sound. */
|
/* Sound. */
|
||||||
ALuint sound;
|
int sound;
|
||||||
|
|
||||||
/* Characteristics. */
|
/* Characteristics. */
|
||||||
int crew;
|
int crew;
|
||||||
|
629
src/sound.c
629
src/sound.c
@ -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. */
|
/* Get the buffer to sound of name. */
|
||||||
while(voice_start != NULL)
|
int sound_get(char* name) {
|
||||||
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]. */
|
|
||||||
ALuint 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. */
|
Mix_FreeChunk(snd->buffer);
|
||||||
void sound_update(void) {
|
snd->buffer = NULL;
|
||||||
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;
|
/* Reserve num channels. */
|
||||||
}else {
|
int sound_reserve(int num) {
|
||||||
/* 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. */
|
|
||||||
static void voice_rm(alVoice* prev, alVoice* voice) {
|
|
||||||
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.);
|
return 0;
|
||||||
/*alListener3f(AL_VELOCITY, vx, vy, 0.); */
|
}
|
||||||
|
|
||||||
soundUnlock();
|
/* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
31
src/sound.h
31
src/sound.h
@ -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);
|
|
||||||
|
|
||||||
|
22
src/weapon.c
22
src/weapon.c
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user