[Add] Sound base support.

This commit is contained in:
Allanis 2013-02-22 05:34:24 +00:00
parent 529ca21644
commit dcc0fc247b
8 changed files with 153 additions and 40 deletions

View File

@ -8,6 +8,7 @@
</general> </general>
<specific type="1"> <specific type="1">
<gfx>lasergreen</gfx> <gfx>lasergreen</gfx>
<sound>laser</sound>
<delay>500</delay> <delay>500</delay>
<speed>550</speed> <speed>550</speed>
<range>300</range> <range>300</range>

View File

@ -104,7 +104,7 @@ int main(int argc, char** argv) {
// OpenAL sound. // OpenAL sound.
if(sound_init()) WARN("Problem setting up sound!"); if(sound_init()) WARN("Problem setting up sound!");
music_load("Machina"); music_load("Machina");
music_play(); //music_play();
// Input. // Input.
if((indjoystick >= 0) || (namjoystick != NULL)) { if((indjoystick >= 0) || (namjoystick != NULL)) {
@ -170,6 +170,8 @@ int main(int argc, char** argv) {
input_handle(&event); // handles all the events the player keybinds. input_handle(&event); // handles all the events the player keybinds.
} }
sound_update(); // Do the sound stuff.
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
fps_control(); // Who doesn't love FPS control? fps_control(); // Who doesn't love FPS control?

View File

@ -105,6 +105,8 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
snprintf(str, strlen(xml_get(node))+sizeof(OUTFIT_GFX)+4, OUTFIT_GFX"%s.png", xml_get(node)); snprintf(str, strlen(xml_get(node))+sizeof(OUTFIT_GFX)+4, OUTFIT_GFX"%s.png", xml_get(node));
tmp->gfx_space = gl_newSprite(str, 6, 6); tmp->gfx_space = gl_newSprite(str, 6, 6);
} }
else if(xml_isNode(node, "sound"))
tmp->sound = sound_get(xml_get(node));
else if(xml_isNode(node, "damage")) { else if(xml_isNode(node, "damage")) {
cur = node->children; cur = node->children;
do { do {
@ -116,6 +118,7 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) {
#define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name) #define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
if(tmp->gfx_space == NULL) if(tmp->gfx_space == NULL)
WARN("Outfit '%s' missing 'gfx' element", tmp->name); WARN("Outfit '%s' missing 'gfx' element", tmp->name);
MELEMENT(tmp->sound, "sound");
MELEMENT(tmp->delay, "delay"); MELEMENT(tmp->delay, "delay");
MELEMENT(tmp->speed, "speed"); MELEMENT(tmp->speed, "speed");
MELEMENT(tmp->range, "range"); MELEMENT(tmp->range, "range");

View File

@ -252,12 +252,12 @@ static void pilot_update(Pilot* pilot, const double dt) {
if(!pilot_isFlag(pilot, PILOT_HYPERSPACE) && VMOD(pilot->solid->vel) > if(!pilot_isFlag(pilot, PILOT_HYPERSPACE) && VMOD(pilot->solid->vel) >
pilot->ship->speed) pilot->ship->speed)
// Should not go faster. // Should not go faster.
vect_pset(&pilot->solid->vel, VMOD(pilot->solid->vel) - 0.3*pilot->ship->thrust*dt, vect_pset(&pilot->solid->vel, pilot->ship->speed,
VANGLE(pilot->solid->vel)); VANGLE(pilot->solid->vel));
// Update the source. // Update the source.
alSource3f(pilot->source, AL_POSITION, pilot->solid->pos.x, pilot->solid->pos.y, 0.); //alSource3f(pilot->source, AL_POSITION, pilot->solid->pos.x, pilot->solid->pos.y, 0.);
alSource3f(pilot->source, AL_VELOCITY, pilot->solid->vel.x, pilot->solid->vel.y, 0.); //alSource3f(pilot->source, AL_VELOCITY, pilot->solid->vel.x, pilot->solid->vel.y, 0.);
} }
// Pilot is getting ready or is in, hyperspace. // Pilot is getting ready or is in, hyperspace.
@ -365,7 +365,7 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, AI_Profi
// Set flags and functions. // Set flags and functions.
if(flags & PILOT_PLAYER) { if(flags & PILOT_PLAYER) {
alSourcef(pilot->source, AL_GAIN, 0.); //alSourcef(pilot->source, AL_GAIN, 0.);
pilot->think = player_think; // Players don't need to thing! :P pilot->think = player_think; // Players don't need to thing! :P
pilot->render = NULL; // Render will be called from player_think pilot->render = NULL; // Render will be called from player_think
pilot_setFlag(pilot, PILOT_PLAYER); // It's a player! pilot_setFlag(pilot, PILOT_PLAYER); // It's a player!

View File

@ -174,7 +174,6 @@ void player_new(void) {
d = RNG(0, 359)/180.*M_PI; d = RNG(0, 359)/180.*M_PI;
pilot_create(ship, "Player", faction_get("Player"), NULL, d, &v, NULL, PILOT_PLAYER); pilot_create(ship, "Player", faction_get("Player"), NULL, d, &v, NULL, PILOT_PLAYER);
alSourcef(player->source, AL_GAIN, 0.5);
gl_bindCamera(&player->solid->pos); // Set opengl camers. gl_bindCamera(&player->solid->pos); // Set opengl camers.
space_init(system); space_init(system);

View File

@ -12,11 +12,17 @@
#define SOUND_PREFIX "snd/sounds/" #define SOUND_PREFIX "snd/sounds/"
#define SOUND_SUFFIX ".wav" #define SOUND_SUFFIX ".wav"
// Give the buffers a name.
typedef struct { typedef struct {
char* name; char* name; // Buffers name.
ALuint buffer; ALuint buffer; // Associated OpenAL buffer.
} alSound; } alSound;
#define VOICE_PLAYING (1<<0) // Voice is playing.
#define VOICE_LOOPING (1<<1) // Voice is looping.
#define voice_set(v,f) ((v)->flags |= f)
#define voice_is(v,f) ((v)->flags & f)
// Gobal device and context. // Gobal device and context.
static ALCcontext* al_context = NULL; static ALCcontext* al_context = NULL;
static ALCdevice* al_device = NULL; static ALCdevice* al_device = NULL;
@ -28,11 +34,18 @@ static SDL_Thread* music_player = NULL;
static alSound* sound_list = NULL; static alSound* sound_list = NULL;
static int nsound_list = 0; static int nsound_list = 0;
// Current sources playing.
static alVoice** voice_stack = NULL;
static int nvoice_stack = 0;
static int mvoice_stack = 0;
static int sound_makeList(void); static int sound_makeList(void);
static int sound_load(ALuint* buffer, char* filename); static int sound_load(ALuint* buffer, char* filename);
static void sound_free(alSound* snd); static void sound_free(alSound* snd);
int sound_init(void) { int sound_init(void) {
const ALchar* device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
DEBUG("OpenAL using device '%s'", device);
// Open the default device. // Open the default device.
al_device = alcOpenDevice(NULL); al_device = alcOpenDevice(NULL);
if(al_device == NULL) { if(al_device == NULL) {
@ -47,6 +60,9 @@ int sound_init(void) {
return -2; return -2;
} }
// Clear the errors.
alGetError();
// Set active context. // Set active context.
if(alcMakeContextCurrent(al_context)==AL_FALSE) { if(alcMakeContextCurrent(al_context)==AL_FALSE) {
WARN("Failure to set default context"); WARN("Failure to set default context");
@ -166,17 +182,103 @@ static void sound_free(alSound* snd) {
alDeleteBuffers(1, &snd->buffer); alDeleteBuffers(1, &snd->buffer);
} }
ALuint sound_dynSource(double px, double py, double vx, double vy, int looping) { // Update the sounds and prioritize them.
ALuint tmp; void sound_update(void) {
int i;
// TODO: Prioritize the things.
alGenSources(1, &tmp); for(i = 0; i < nvoice_stack; i++) {
if(voice_is(voice_stack[i], VOICE_PLAYING)) {
// Update position.
alSource3f(voice_stack[i]->source, AL_POSITION,
voice_stack[i]->px, voice_stack[i]->py, 0.);
alSource3f(voice_stack[i]->source, AL_VELOCITY,
voice_stack[i]->vx, voice_stack[i]->vy, 0.);
alSourcei(tmp, AL_SOURCE_RELATIVE, AL_TRUE); }
alSource3f(tmp, AL_POSITION, px, py, 0.); }
alSource3f(tmp, AL_VELOCITY, vx, vy, 0.); }
if(looping) alSourcei(tmp, AL_LOOPING, AL_TRUE); // Create a dynamic moving voice.
alVoice* sound_addVoice(int priority, double px, double py, double vx, double vy,
return tmp; const ALuint buffer, const int looping) {
alVoice* voc;
ALenum err;
nvoice_stack++;
if(nvoice_stack > mvoice_stack)
voice_stack = realloc(voice_stack, ++mvoice_stack*sizeof(alVoice*));
voc = malloc(sizeof(alVoice));
voice_stack[nvoice_stack-1] = voc;
// Try and grab a source.
voc->source = 0;
alGenSources(1, &voc->source);
err = alGetError();
if(err != AL_NO_ERROR) voc->source = 0;
// Set the data.
voc->priority = priority;
voc->start = SDL_GetTicks();
voc->buffer = buffer;
if(looping) voice_set(voc, VOICE_LOOPING);
voc->px = px;
voc->py = py;
voc->vx = vx;
voc->vy = vy;
// Set the source.
if(voc->source) {
alSourcei(voc->source, AL_SOURCE_RELATIVE, AL_TRUE);
alSourcef(voc->source, AL_GAIN, 1.);
alSourcei(voc->source, AL_BUFFER, buffer);
alSource3f(voc->source, AL_POSITION, voc->px, voc->py, 0.);
alSource3f(voc->source, AL_VELOCITY, voc->vx, voc->vy, 0.);
if(voice_is(voc, VOICE_LOOPING))
alSourcei(voc->source, AL_LOOPING, AL_TRUE);
// Try to play the source.
alSourcePlay(voc->source);
err = alGetError();
if(err == AL_NO_ERROR) voice_set(voc, VOICE_PLAYING);
else DEBUG("Source player failure");
}
return voc;
}
void sound_delVoice(alVoice* voice) {
ALint stat;
int i;
for(i = 0; i < nvoice_stack; i++)
if(voice == voice_stack[i])
break;
// No match found.
if(i >= nvoice_stack) {
WARN("Unable to find voice to free from stack");
return;
}
if(voice->source) {
alGetSourcei(voice->source, AL_SOURCE_STATE, &stat);
if(stat == AL_PLAYING) alSourceStop(voice->source);
alDeleteSources(1, &voice->source);
voice->source = 0;
}
nvoice_stack--;
for(; i < nvoice_stack; i++)
voice_stack[i] = voice_stack[i+1];
}
void voice_update(alVoice* voice, double px, double py, double vx, double vy) {
voice->px = px;
voice->py = py;
voice->vx = vx;
voice->vy = vy;
} }

View File

@ -5,13 +5,32 @@
#define SOUND_REFERENCE_DIST 500. #define SOUND_REFERENCE_DIST 500.
#define SOUND_MAX_DIST 1000. #define SOUND_MAX_DIST 1000.
// Virtual voice.
typedef struct {
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.
} 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); ALuint sound_get(char* name);
// Source manipulation function. // Voice manipulation function.
ALuint sound_dynSource(double px, double py, double vx, double vy, int looping); alVoice* sound_addVoice(int priority, double px, double py, double vx, double vy,
const ALuint buffer, const int looping);
void sound_delVoice(alVoice* voice);
void voice_update(alVoice* voice, double px, double py, double vx, double vy);

View File

@ -14,6 +14,9 @@
#define weapon_isSmart(w) (w->think) #define weapon_isSmart(w) (w->think)
#define VOICE_PRIORITY_BOLD 10 // Default.
#define VOICE_PRIORITY_AMMP 8 // Higher.
// Some stuff from pilot. // Some stuff from pilot.
extern Pilot** pilot_stack; extern Pilot** pilot_stack;
extern int pilots; extern int pilots;
@ -29,7 +32,7 @@ typedef struct Weapon {
const Outfit* outfit; // Related outfit that fired. const Outfit* outfit; // Related outfit that fired.
unsigned int timer; // Mainly used to see when the weapon was fired. unsigned int timer; // Mainly used to see when the weapon was fired.
ALuint source; // Source for sound. //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.
@ -45,8 +48,6 @@ static Weapon** wfrontLayer = NULL; // Behind pilots.
static int nwfrontLayer = 0; // Number of elements. static int nwfrontLayer = 0; // Number of elements.
static int mwfrontLayer = 0; // Allocated memory size. static int mwfrontLayer = 0; // Allocated memory size.
static void weapon_sound(Weapon* w);
static Weapon* weapon_create(const Outfit* outfit, const double dir, static Weapon* weapon_create(const Outfit* outfit, const double dir,
const Vec2* pos, const Vec2* vel, const unsigned int parent, const Vec2* pos, const Vec2* vel, const unsigned int parent,
const unsigned int target); const unsigned int target);
@ -128,14 +129,6 @@ void weapons_update(const double dt) {
weapons_updateLayer(dt, WEAPON_LAYER_FG); weapons_updateLayer(dt, WEAPON_LAYER_FG);
} }
// Play the weapon sound.
static void weapon_sound(Weapon* w) {
w->source = sound_dynSource(w->solid->pos.x, w->solid->pos.y,
w->solid->vel.x, w->solid->vel.y, 0);
alSourcei(w->source, AL_BUFFER, w->outfit->sound);
alSourcePlay(w->source);
}
// Update all weapons in the layer. // Update all weapons in the layer.
static void weapons_updateLayer(const double dt, const WeaponLayer layer) { static void weapons_updateLayer(const double dt, const WeaponLayer layer) {
Weapon** wlayer; Weapon** wlayer;
@ -235,8 +228,9 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) {
(*w->solid->update)(w->solid, dt); (*w->solid->update)(w->solid, dt);
// Update the sound. // Update the sound.
alSource3f(w->source, AL_POSITION, w->solid->pos.x, w->solid->pos.y, 0.); /*if(w->voise)
alSource3f(w->source, AL_VELOCITY, w->solid->vel.x, w->solid->vel.y, 0.); voice_update(w->voice, w->solid->pos.x, w->solid->pos.y,
w->solid->vel.x, w->solid->vel.y);*/
} }
// Good shot. // Good shot.
@ -275,17 +269,14 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
vectcpy(&v, vel); vectcpy(&v, vel);
vect_cadd(&v, outfit->speed*cos(rdir), outfit->speed*sin(rdir)); vect_cadd(&v, outfit->speed*cos(rdir), outfit->speed*sin(rdir));
w->solid = solid_create(mass, rdir, pos, &v); w->solid = solid_create(mass, rdir, pos, &v);
weapon_sound(w);
break; break;
case OUTFIT_TYPE_MISSILE_SEEK_AMMO: case OUTFIT_TYPE_MISSILE_SEEK_AMMO:
mass = w->outfit->mass; mass = w->outfit->mass;
w->solid = solid_create(mass, dir, pos, vel); w->solid = solid_create(mass, dir, pos, vel);
w->think = think_seeker; // Eeek!!! w->think = think_seeker; // Eeek!!!
weapon_sound(w);
break; break;
default: default:
// Just dump it where the player is. // Just dump it where the player is.
w->source = 0;
w->solid = solid_create(mass, dir, pos, vel); w->solid = solid_create(mass, dir, pos, vel);
break; break;
} }
@ -354,10 +345,6 @@ static void weapon_destroy(Weapon* w, WeaponLayer layer) {
break; break;
} }
for(i = 0; wlayer[i] != w; i++); // Get us to the current posision. for(i = 0; wlayer[i] != w; i++); // Get us to the current posision.
if(w->source) {
alSourceStop(wlayer[i]->source);
alDeleteSources(1, &wlayer[i]->source);
}
weapon_free(wlayer[i]); weapon_free(wlayer[i]);
wlayer[i] = NULL; wlayer[i] = NULL;
(*nlayer)--; (*nlayer)--;