[Add] Improved sound system considerably, not used properly yet.
This commit is contained in:
parent
6e1d312daf
commit
ebdfaad9a7
@ -332,6 +332,8 @@ void main_loop(void) {
|
|||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
fps_control(); /* Everyone loves fps control.. */
|
fps_control(); /* Everyone loves fps control.. */
|
||||||
|
|
||||||
|
sound_update(); /* Update sounds. */
|
||||||
if(toolkit) toolkit_update(); /* To simulate key repetition. */
|
if(toolkit) toolkit_update(); /* To simulate key repetition. */
|
||||||
if(!menu_isOpen(MENU_MAIN)) {
|
if(!menu_isOpen(MENU_MAIN)) {
|
||||||
if(!paused) update_all(); /* Update game. */
|
if(!paused) update_all(); /* Update game. */
|
||||||
|
257
src/sound.c
257
src/sound.c
@ -26,19 +26,64 @@ int sound_disabled = 0; /**< Whether sound is disabled. */
|
|||||||
static int sound_reserved = 0; /**< Amount of reserved channels. */
|
static int sound_reserved = 0; /**< Amount of reserved channels. */
|
||||||
static double sound_pos[3]; /**< Position of listener. */
|
static double sound_pos[3]; /**< Position of listener. */
|
||||||
|
|
||||||
/* Give the buffers a name. */
|
/**
|
||||||
|
* @struct alSound
|
||||||
|
*
|
||||||
|
* @brief Contains a sound buffer.
|
||||||
|
*/
|
||||||
typedef struct alSound_ {
|
typedef struct alSound_ {
|
||||||
char* name; /**< Buffers name. */
|
char* name; /**< Buffers name. */
|
||||||
Mix_Chunk* buffer; /**< Buffer data. */
|
Mix_Chunk* buffer; /**< Buffer data. */
|
||||||
} alSound;
|
} alSound;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef voice_state_t
|
||||||
|
*
|
||||||
|
* @brief The state of a voice.
|
||||||
|
*
|
||||||
|
* @sa alVoice
|
||||||
|
*/
|
||||||
|
typedef enum voice_state_ {
|
||||||
|
VOICE_STOPPED, /**< Voice is stopped. */
|
||||||
|
VOICE_PLAYING, /**< Voice is playing. */
|
||||||
|
VOICE_DESTROY /**< Voice should get destroyed asap. */
|
||||||
|
} voice_state_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct alVoice
|
||||||
|
*
|
||||||
|
* @brief Represents a voice in the game.
|
||||||
|
*
|
||||||
|
* A voice would be any object that is creating sound.
|
||||||
|
*/
|
||||||
|
typedef struct alVoice_ {
|
||||||
|
struct alVoice_* prev; /**< Linked list previous member. */
|
||||||
|
struct alVoice_* next; /**< Linked list next member. */
|
||||||
|
|
||||||
|
int id; /**< Identifier of the voice. */
|
||||||
|
double pos[2]; /**< Position of the voice. */
|
||||||
|
int channel; /**< Channel currently in use. */
|
||||||
|
unsigned int state; /**< Current state of the sound. */
|
||||||
|
} alVoice;
|
||||||
|
|
||||||
/* List of sounds available (All preloaded into a buffer). */
|
/* List of sounds available (All preloaded into a buffer). */
|
||||||
|
static int voice_genid = 0; /**< Voice identifier generator. */
|
||||||
static alSound* sound_list = NULL; /**< List of available sounds. */
|
static alSound* sound_list = NULL; /**< List of available sounds. */
|
||||||
static int sound_nlist = 0; /**< Number of available sounds. */
|
static int sound_nlist = 0; /**< Number of available sounds. */
|
||||||
|
|
||||||
|
/* Voice linked list. */
|
||||||
|
static alVoice* voice_active; /**< Active voices. */
|
||||||
|
static alVoice* voice_pool; /**< Pool of free voices. */
|
||||||
|
|
||||||
|
/* General prototypes. */
|
||||||
static int sound_makeList(void);
|
static int sound_makeList(void);
|
||||||
static Mix_Chunk* sound_load(char* filename);
|
static Mix_Chunk* sound_load(char* filename);
|
||||||
static void sound_free(alSound* snd);
|
static void sound_free(alSound* snd);
|
||||||
|
/* Voices. */
|
||||||
|
static void voice_markStopped(int channel);
|
||||||
|
static alVoice* voice_new(void);
|
||||||
|
static int voice_add(alVoice* v);
|
||||||
|
static alVoice* voice_get(int id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fn int sound_init(void)
|
* @fn int sound_init(void)
|
||||||
@ -77,6 +122,9 @@ int sound_init(void) {
|
|||||||
sound_makeList();
|
sound_makeList();
|
||||||
sound_volume(0.4);
|
sound_volume(0.4);
|
||||||
|
|
||||||
|
/* Finish function. */
|
||||||
|
Mix_ChannelFinished(voice_markStopped);
|
||||||
|
|
||||||
/* Init the music. */
|
/* Init the music. */
|
||||||
music_init();
|
music_init();
|
||||||
|
|
||||||
@ -90,6 +138,19 @@ int sound_init(void) {
|
|||||||
*/
|
*/
|
||||||
void sound_exit(void) {
|
void sound_exit(void) {
|
||||||
int i;
|
int i;
|
||||||
|
alVoice* v;
|
||||||
|
|
||||||
|
/* Free the voices. */
|
||||||
|
while(voice_active != NULL) {
|
||||||
|
v = voice_active;
|
||||||
|
voice_active = v->next;
|
||||||
|
free(v);
|
||||||
|
}
|
||||||
|
while(voice_pool != NULL) {
|
||||||
|
v = voice_pool;
|
||||||
|
voice_pool = v->next;
|
||||||
|
free(v);
|
||||||
|
}
|
||||||
|
|
||||||
/* Free the sounds. */
|
/* Free the sounds. */
|
||||||
for(i = 0; i < sound_nlist; i++)
|
for(i = 0; i < sound_nlist; i++)
|
||||||
@ -155,7 +216,7 @@ int sound_play(int sound) {
|
|||||||
* @return 0 on success.
|
* @return 0 on success.
|
||||||
*/
|
*/
|
||||||
int sound_playPos(int sound, double x, double y) {
|
int sound_playPos(int sound, double x, double y) {
|
||||||
int channel;
|
alVoice* v;
|
||||||
double angle, dist;
|
double angle, dist;
|
||||||
double px, py;
|
double px, py;
|
||||||
|
|
||||||
@ -164,28 +225,128 @@ int sound_playPos(int sound, double x, double y) {
|
|||||||
if((sound < 0) || (sound > sound_nlist))
|
if((sound < 0) || (sound > sound_nlist))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
px = x - sound_pos[0];
|
/* Get a new voice. */
|
||||||
py = y - sound_pos[1];
|
v = voice_new();
|
||||||
|
|
||||||
|
v->pos[0] = x;
|
||||||
|
v->pos[1] = y;
|
||||||
|
|
||||||
|
px = v->pos[0] - sound_pos[0];
|
||||||
|
py = v->pos[1] - sound_pos[1];
|
||||||
|
|
||||||
angle = sound_pos[2] - ANGLE(px, py)/M_PI*180.;
|
angle = sound_pos[2] - ANGLE(px, py)/M_PI*180.;
|
||||||
|
|
||||||
dist = MOD(px, py);
|
dist = MOD(px, py);
|
||||||
|
|
||||||
channel = Mix_PlayChannel(-1, sound_list[sound].buffer, 0);
|
v->channel = Mix_PlayChannel(-1, sound_list[sound].buffer, 0);
|
||||||
|
|
||||||
if(channel < 0) {
|
if(v->channel < 0) {
|
||||||
WARN("Unable to play sound: %s", Mix_GetError());
|
WARN("Unable to play sound: %s", Mix_GetError());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Mix_SetPosition(channel, (int)angle, (int)dist/10) < 0) {
|
if(Mix_SetPosition(v->channel, (int)angle, (int)dist/10) < 0) {
|
||||||
WARN("Unable to set sound position: %s", Mix_GetError());
|
WARN("Unable to set sound position: %s", Mix_GetError());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Actually add the voice to the list. */
|
||||||
|
v->state = VOICE_PLAYING;
|
||||||
|
v->id = ++voice_genid;
|
||||||
|
voice_add(v);
|
||||||
|
|
||||||
|
return v->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int sound_updatePos(int voice, double x, double y)
|
||||||
|
*
|
||||||
|
* @brief Update the position of a voice.
|
||||||
|
* @param voice Identifier of the voice to update.
|
||||||
|
* @param x New x position to update to.
|
||||||
|
* @param y New y position to update to.
|
||||||
|
*/
|
||||||
|
int sound_updatePos(int voice, double x, double y) {
|
||||||
|
alVoice* v;
|
||||||
|
double angle, dist;
|
||||||
|
double px, py;
|
||||||
|
|
||||||
|
if(sound_disabled) return 0;
|
||||||
|
|
||||||
|
v = voice_get(voice);
|
||||||
|
|
||||||
|
if(v != NULL) {
|
||||||
|
v->pos[0] = x;
|
||||||
|
v->pos[1] = y;
|
||||||
|
|
||||||
|
px = x - sound_pos[0];
|
||||||
|
py = y - sound_pos[1];
|
||||||
|
|
||||||
|
angle = sound_pos[2] - ANGLE(px, py)/M_PI*180.;
|
||||||
|
dist = MOD(px, py);
|
||||||
|
|
||||||
|
if(Mix_SetPosition(v->channel, (int)angle, (int)dist/10) < 0) {
|
||||||
|
WARN("Unable to set sound position: %s", Mix_GetError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int sound_update(void)
|
||||||
|
*
|
||||||
|
* @brief Update the sounds removing obsolete ones and such.
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
|
int sound_update(void) {
|
||||||
|
alVoice* v, *tv;
|
||||||
|
|
||||||
|
if(sound_disabled) return 0;
|
||||||
|
|
||||||
|
if(voice_active == NULL) return 0;
|
||||||
|
|
||||||
|
/* The actualy control loop. */
|
||||||
|
for(v = voice_active; v != NULL; v = v->next) {
|
||||||
|
/* Destroy and toss into pool. */
|
||||||
|
if((v->state == VOICE_STOPPED) || (v->state == VOICE_DESTROY)) {
|
||||||
|
/* Remove from active list. */
|
||||||
|
tv = v->prev;
|
||||||
|
if(tv == NULL)
|
||||||
|
voice_active = v->next;
|
||||||
|
else
|
||||||
|
tv->next = v->next;
|
||||||
|
|
||||||
|
/* Add to free pool. */
|
||||||
|
v->next = voice_pool;
|
||||||
|
voice_pool = v;
|
||||||
|
v->channel = 0;
|
||||||
|
|
||||||
|
/* Avoid loop blockage. */
|
||||||
|
v = (tv != NULL) ? tv->next : voice_active;
|
||||||
|
if(v == NULL) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void sound_stop(int voice)
|
||||||
|
*
|
||||||
|
* @brief Stop a voice from playing.
|
||||||
|
* @param voice Identifier of the voice to stop.
|
||||||
|
*/
|
||||||
|
void sound_stop(int voice) {
|
||||||
|
alVoice* v;
|
||||||
|
|
||||||
|
if(sound_disabled) return;
|
||||||
|
|
||||||
|
v = voice_get(voice);
|
||||||
|
if(v != NULL) {
|
||||||
|
Mix_HaltChannel(v->channel);
|
||||||
|
v->state = VOICE_STOPPED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fn int sound_updateListener(double dir, double x, double y)
|
* @fn int sound_updateListener(double dir, double x, double y)
|
||||||
*
|
*
|
||||||
@ -410,3 +571,83 @@ void sound_stopGroup(int group) {
|
|||||||
Mix_HaltGroup(group);
|
Mix_HaltGroup(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn static void voice_markStopped(int channel)
|
||||||
|
*
|
||||||
|
* @brief Mark the voice to which channel belongs to as stopped.
|
||||||
|
*/
|
||||||
|
static void voice_markStopped(int channel) {
|
||||||
|
alVoice* v;
|
||||||
|
|
||||||
|
for(v = voice_active; v != NULL; v = v->next)
|
||||||
|
if(v->channel == channel) {
|
||||||
|
v->state = VOICE_STOPPED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn static alVoice* voice_new(void)
|
||||||
|
*
|
||||||
|
* @brief Get a new voice ready to be used.
|
||||||
|
* @return New voice ready to use.
|
||||||
|
*/
|
||||||
|
static alVoice* voice_new(void) {
|
||||||
|
alVoice* v;
|
||||||
|
|
||||||
|
/* No free voices, allocate a new one. */
|
||||||
|
if(voice_pool == NULL) {
|
||||||
|
v = malloc(sizeof(alVoice));
|
||||||
|
memset(v, 0, sizeof(alVoice));
|
||||||
|
voice_pool = v;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First free voice. */
|
||||||
|
v = voice_pool;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn static int voice_add(alVoice* v)
|
||||||
|
*
|
||||||
|
* @brief Add a voice to the active voice stack.
|
||||||
|
* @param v Voice to add to the active voice stack.
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
|
static int voice_add(alVoice* v) {
|
||||||
|
alVoice* tv;
|
||||||
|
|
||||||
|
/* Set previous to point to next. */
|
||||||
|
if(v->prev != NULL) {
|
||||||
|
tv = v->prev;
|
||||||
|
tv->next = v->next;
|
||||||
|
} else { /* Set pool to be the next. */
|
||||||
|
voice_pool = v->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert to the front of active voices. */
|
||||||
|
tv = voice_active;
|
||||||
|
voice_active = v;
|
||||||
|
v->next = tv;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn static alVoice* voice_get(int id)
|
||||||
|
*
|
||||||
|
* @brief Get a voice by identifier.
|
||||||
|
* @param id Identifier to look for.
|
||||||
|
* @return Voice matching identifier or NULL if not found.
|
||||||
|
*/
|
||||||
|
static alVoice* voice_get(int id) {
|
||||||
|
alVoice* v;
|
||||||
|
|
||||||
|
if(voice_active == NULL) return NULL;
|
||||||
|
|
||||||
|
for(v = voice_active; v != NULL; v = v->next)
|
||||||
|
if(v->id == id)
|
||||||
|
return v;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,15 @@ extern int sound_disabled;
|
|||||||
/* Sound subsystem. */
|
/* Sound subsystem. */
|
||||||
int sound_init(void);
|
int sound_init(void);
|
||||||
void sound_exit(void);
|
void sound_exit(void);
|
||||||
|
int sound_update(void);
|
||||||
|
|
||||||
/* Sound manupulation functions. */
|
/* Sound manupulation functions. */
|
||||||
int sound_get(char* name);
|
int sound_get(char* name);
|
||||||
int sound_volume(const double vol);
|
int sound_volume(const double vol);
|
||||||
int sound_play(int sound);
|
int sound_play(int sound);
|
||||||
int sound_playPos(int sound, double x, double y);
|
int sound_playPos(int sound, double x, double y);
|
||||||
|
void sound_stop(int voice);
|
||||||
|
int sound_updatePos(int voice, double x, double y);
|
||||||
int sound_updateListener(double dir, double x, double y);
|
int sound_updateListener(double dir, double x, double y);
|
||||||
|
|
||||||
/* Group functions. */
|
/* Group functions. */
|
||||||
|
Loading…
Reference in New Issue
Block a user