native music fade in/out, random seek in ogg streams, action music while carrying CTF flag

git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@2007 e016b1c5-ed68-44aa-a2f7-31cac88cffde
This commit is contained in:
driAn
2008-05-17 17:12:53 +00:00
parent 9405b717d0
commit ce141e60a7
6 changed files with 217 additions and 71 deletions
+16 -2
View File
@@ -481,6 +481,11 @@ void timeupdate(int timeremain)
else
{
conoutf("time remaining: %d minutes", timeremain);
if(timeremain==1)
{
musicsuggest(M_LASTMINUTE1 + rnd(2), 70*1000, true);
hudoutf("1 minute left!");
}
}
}
@@ -605,14 +610,22 @@ void flagmsg(int flag, int action)
case SV_FLAGPICKUP:
{
playsound(S_FLAGPICKUP, SP_HIGH);
if(firstperson) conoutf("\f2you got the enemy flag");
if(firstperson)
{
conoutf("\f2you got the enemy flag");
musicsuggest(M_FLAGGRAB, 90*1000);
}
else conoutf("\f2%s got %s flag", colorname(f.actor), teamstr);
break;
}
case SV_FLAGDROP:
{
playsound(S_FLAGDROP, SP_HIGH);
if(firstperson) conoutf("\f2you lost the flag");
if(firstperson)
{
conoutf("\f2you lost the flag");
musicfadeout(M_FLAGGRAB);
}
else conoutf("\f2%s lost %s flag", colorname(f.actor), teamstr);
break;
}
@@ -630,6 +643,7 @@ void flagmsg(int flag, int action)
{
conoutf("\f2you scored");
addmsg(SV_FLAGS, "ri", ++player1->flagscore);
musicfadeout(M_FLAGGRAB);
}
else conoutf("\f2%s scored for %s team", colorname(f.actor), (own ? "the enemy" : "your"));
break;
+4 -1
View File
@@ -255,7 +255,10 @@ char *executeret(const char *p) // all evaluation hap
ident *id = idents->access(c);
if(!id)
{
if(!isdigit(*c) && ((*c!='+' && *c!='-') || (*c && !isdigit(c[1])))) conoutf("unknown command: %s", c);
if(!isdigit(*c) && ((*c!='+' && *c!='-') || (*c && !isdigit(c[1]))))
{
conoutf("unknown command: %s", c);
}
setretval(newstring(c));
}
else
+2 -1
View File
@@ -488,7 +488,8 @@ extern void initsound();
extern void soundcleanup();
extern void checkmapsounds();
extern void checkplayerloopsounds();
extern void music(char *name, char *cmd);
extern void musicsuggest(int id, int millis = 0, bool rndofs = false);
extern void musicfadeout(int id);
extern void clearsounds();
// rendermodel
-1
View File
@@ -270,7 +270,6 @@ void hudoutf(const char *s, ...)
s_sprintfdv(sf, s);
string sp;
filtertext(sp, sf);
//puts(sp);
s = sf;
hudmsgs.addline(s);
conoutf(s);
+188 -66
View File
@@ -6,12 +6,10 @@
#ifdef __APPLE__
#include "OpenAL/al.h"
#include "OpenAL/alc.h"
#include "alut.h"
#include "Vorbis/vorbisfile.h"
#else
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alut.h"
#include "vorbis/vorbisfile.h"
#endif
@@ -22,93 +20,126 @@ ALCcontext *context = NULL;
void alclearerr()
{
alGetError();
alutGetError();
}
bool alerr()
{
ALenum er = alGetError();
if(er)
{
ALenum aluterr = alutGetError();
if(aluterr) // prefer user-friendly error msg
{
conoutf("\f3OpenAL Error: %s (%X)", alutGetErrorString(aluterr), er);
}
else
{
conoutf("\f3OpenAL Error (%X)", er);
}
return true;
}
return false;
if(er) conoutf("\f3OpenAL Error (%X)", er);
return er > 0;
}
struct oggstream
{
FILE *file;
OggVorbis_File oggfile;
vorbis_info *info;
ALuint bufferids[2];
ALuint sourceid;
ALenum format;
ALint laststate;
string name;
double totalseconds;
static const int BUFSIZE = (1024 * 16);
int startmillis, endmillis, startfademillis, endfademillis;
float volume, gain;
bool looping;
oggstream() : sourceid(0) {}
oggstream() : sourceid(0), startmillis(0), endmillis(0), startfademillis(0), endfademillis(0), volume(1.0f), gain(1.0f), looping(false) {}
~oggstream() { reset(); }
bool open(const char *f)
{
if(playing()) release();
if(!f) return false;
if(playing()) reset();
file = fopen(path(f, true), "rb");
if(!file) return false;
const char *exts[] = { "", ".wav", ".ogg" };
string filepath;
if(ov_open_callbacks(file, &oggfile, NULL, 0, OV_CALLBACKS_DEFAULT) < 0)
loopi(sizeof(exts)/sizeof(exts[0]))
{
fclose(file);
return false;
}
info = ov_info(&oggfile, -1);
format = info->channels == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
alclearerr();
alGenBuffers(2, bufferids);
alGenSources(1, &sourceid);
alerr();
s_sprintf(filepath)("packages/audio/songs/%s%s", f, exts[i]);
FILE *file = fopen(findfile(path(filepath), "rb"), "rb");
if(!file) continue;
alSource3f(sourceid, AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(sourceid, AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(sourceid, AL_DIRECTION, 0.0, 0.0, 0.0);
// disable sound distance calculations
alSourcef(sourceid, AL_ROLLOFF_FACTOR, 0.0f);
alSourcei(sourceid, AL_SOURCE_RELATIVE, AL_TRUE);
return true;
if(ov_open_callbacks(file, &oggfile, NULL, 0, OV_CALLBACKS_DEFAULT) < 0)
{
fclose(file);
continue;
}
info = ov_info(&oggfile, -1);
format = info->channels == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
totalseconds = ov_time_total(&oggfile, -1);
s_strcpy(this->name, f);
alclearerr();
alGenBuffers(2, bufferids);
alGenSources(1, &sourceid);
alerr();
alSource3f(sourceid, AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(sourceid, AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(sourceid, AL_DIRECTION, 0.0, 0.0, 0.0);
// disable sound distance calculations
alSourcef(sourceid, AL_ROLLOFF_FACTOR, 0.0f);
alSourcei(sourceid, AL_SOURCE_RELATIVE, AL_TRUE);
return true;
}
return false;
}
bool playing()
{
if(!sourceid) return false;
alGetSourcei(sourceid, AL_SOURCE_STATE, &laststate);
return laststate == AL_PLAYING;
return laststate == AL_PLAYING;
}
void gain(float g) { alSourcef(sourceid, AL_GAIN, g); }
void updategain()
{
alSourcef(sourceid, AL_GAIN, gain*volume);
}
bool playback()
void setgain(float g)
{
gain = g;
updategain();
}
void setvolume(float v)
{
volume = v;
updategain();
}
void fadein(int startmillis, int fademillis)
{
setgain(0.0f);
this->startmillis = startmillis;
this->startfademillis = fademillis;
}
void fadeout(int endmillis, int fademillis)
{
this->endmillis = (endmillis || totalseconds > 0.0f) ? endmillis : lastmillis+(int)totalseconds;
this->endfademillis = fademillis;
}
bool playback(bool looping = false)
{
if(playing()) return true;
if(!sourceid || !stream(bufferids[0])) return false;
stream(bufferids[1]);
alSourceQueueBuffers(sourceid, 2, bufferids);
alSourcePlay(sourceid);
extern void setmusicvol(); setmusicvol();
this->looping = looping;
return true;
}
bool replay()
{
release();
return playback();
empty();
return !ov_time_seek(&oggfile, (double)0.0);
}
bool stream(ALuint bufid)
@@ -142,6 +173,34 @@ struct oggstream
active = stream(bufferids[i]);
alSourceQueueBuffers(sourceid, 1, &bufferids[i]);
}
// fade in
if(startmillis > 0)
{
const float start = (lastmillis-startmillis)/(float)startfademillis;
if(start>=0.00f && start<=1.00001f) setgain(start);
}
// fade out
if(endmillis > 0)
{
if(lastmillis>endmillis) // stop
{
active = false;
}
else
{
const float end = (endmillis-lastmillis)/(float)endfademillis;
if(end>=-0.00001f && end<=1.00f) setgain(end);
}
}
if(!active)
{
if(looping) replay();
else reset();
}
return active;
}
@@ -170,6 +229,26 @@ struct oggstream
sourceid = 0;
}
ov_clear(&oggfile);
setgain(1.0f);
startmillis = endmillis = startfademillis = endfademillis = 0;
looping = false;
}
void reset()
{
release();
setgain(1.0f);
startmillis = endmillis = startfademillis = endfademillis = 0;
looping = false;
name[0] = '\0';
}
void randomseek()
{
if(!totalseconds) return;
ov_time_seek_page(&oggfile, fmod((double)lastmillis, totalseconds*3/4.0f));
if(playing()) update();
}
};
@@ -477,10 +556,14 @@ oggstream gamemusic;
VARFP(soundvol, 0, 128, 255,
{
alListenerf(AL_GAIN, soundvol/255.0f*10.0f);
alListenerf(AL_GAIN, soundvol/255.0f);
});
void setmusicvol() { extern int musicvol; if(gamemusic.playing()) gamemusic.gain(musicvol/255.0f); }
void setmusicvol()
{
extern int musicvol;
gamemusic.setvolume(musicvol/255.0f);
}
VARFP(musicvol, 0, 128, 255, setmusicvol());
char *musicdonecmd = NULL;
@@ -489,7 +572,7 @@ void stopsound()
{
if(nosound) return;
DELETEA(musicdonecmd);
gamemusic.release();
gamemusic.reset();
}
void initsound()
@@ -513,7 +596,9 @@ void initsound()
if(nosound) conoutf("sound initialization failed!");
}
void music(char *name, char *cmd)
cvector musics;
void music(char *name, char *millis, char *cmd)
{
if(nosound) return;
stopsound();
@@ -521,21 +606,63 @@ void music(char *name, char *cmd)
{
if(cmd[0]) musicdonecmd = newstring(cmd);
const char *exts[] = { "", ".wav", ".ogg" };
string filepath;
loopi(sizeof(exts)/sizeof(exts[0]))
if(gamemusic.open(name))
{
s_sprintf(filepath)("packages/audio/songs/%s%s", name, exts[i]);
const char *file = findfile(path(filepath), "rb");
if(gamemusic.open(file)) break;
}
if(!gamemusic.playback())
{
conoutf("could not play music: %s", name);
// fade
if(atoi(millis) > 0)
{
const int fadetime = 1000;
gamemusic.fadein(lastmillis, fadetime);
gamemusic.fadeout(lastmillis+atoi(millis), fadetime);
}
// play
bool loop = cmd && cmd[0];
if(!gamemusic.playback(loop))
{
conoutf("could not play music: %s", name);
}
}
else conoutf("could not open music: %s", name);
}
}
void musicsuggest(int id, int millis, bool rndofs) // play bg music if nothing else is playing
{
if(nosound) return;
if(gamemusic.playing()) return;
if(!musics.inrange(id))
{
conoutf("\f3music %d not registered", id);
return;
}
char *name = musics[id];
if(gamemusic.open(name))
{
gamemusic.fadein(lastmillis, 1000);
gamemusic.fadeout(millis ? lastmillis+millis : 0, 1000);
if(rndofs) gamemusic.randomseek();
if(!gamemusic.playback(rndofs)) conoutf("could not play music: %s", name);
}
else conoutf("could not open music: %s", name);
}
void musicfadeout(int id)
{
if(!gamemusic.playing() || !musics.inrange(id)) return;
if(!strcmp(musics[id], gamemusic.name)) gamemusic.fadeout(lastmillis+1000, 1000);
}
void registermusic(char *name)
{
if(!name || !name[0]) return;
musics.add(newstring(name));
}
COMMAND(registermusic, ARG_1STR);
COMMAND(music, ARG_3STR);
int findsound(char *name, int vol, vector<slot> &sounds)
{
loopv(sounds)
@@ -545,9 +672,6 @@ int findsound(char *name, int vol, vector<slot> &sounds)
return -1;
}
COMMAND(music, ARG_2STR);
int addsound(char *name, int vol, int maxuses, bool loop, vector<slot> &sounds)
{
sbuffer *b = buffers.access(name);
@@ -582,7 +706,7 @@ void soundcleanup()
mapsounds.setsizenodelete(0);
locations.setsizenodelete(0);
gamemusic.release();
gamemusic.reset();
alcMakeContextCurrent(NULL);
alcDestroyContext(context);
@@ -687,16 +811,14 @@ void updatevol()
// background music
if(!gamemusic.update())
{
// music ended
// music ended, exec command
if(musicdonecmd)
{
gamemusic.release();
char *cmd = musicdonecmd;
musicdonecmd = NULL;
execute(cmd);
delete[] cmd;
}
else gamemusic.replay();
}
}
+7
View File
@@ -59,3 +59,10 @@ enum
SP_HIGH
};
enum
{
M_FLAGGRAB = 0,
M_LASTMINUTE1,
M_LASTMINUTE2
};