759 lines
18 KiB
C++
759 lines
18 KiB
C++
#if 0
|
|
#include "snd_type.h"
|
|
#if defined(Q_SOUND) || defined(NO_SOUND)
|
|
|
|
// since if NO_SOUND is defined, we still need MFx.cpp but with the short-circuited functions
|
|
// but if Q_SOUND is defined, MFx_QMDX will handle it, so this one needs taking out
|
|
|
|
//
|
|
// MFx.cpp
|
|
//
|
|
// Muckyfoot sound fx api for A3D / PSX
|
|
//
|
|
// A3D Version
|
|
//
|
|
|
|
#include "MFx.h"
|
|
#include "A3DManager.h"
|
|
#include "c:\fallen\headers\fc.h"
|
|
|
|
#ifdef TARGET_DC
|
|
#include "target.h"
|
|
#endif
|
|
|
|
#define MFX_MAX_CHANS 64
|
|
#define MFX_MAX_MASK 0x3f;
|
|
#define MFX_MAX_QUEUED 32
|
|
#define MFX_MAX_QUEUED_CHAN 5
|
|
|
|
|
|
extern IA3dGeom *a3dgeom;
|
|
|
|
static BOOL MFX_initialised=0;
|
|
|
|
//----- structs --------------------------------------------------------------------
|
|
|
|
struct MFX_Queue {
|
|
UWORD wave;
|
|
SWORD next;
|
|
ULONG flags;
|
|
SLONG x,y,z;
|
|
float gain;
|
|
};
|
|
|
|
struct MFX_Channel {
|
|
UWORD id; // thing-id of sound on this channel
|
|
UWORD wave; // sound sample playing on this channel
|
|
ULONG flags;
|
|
SLONG x,y,z; // coordinates to play it, if it's positional
|
|
A3DSource* source; // a3d source that handles this channel
|
|
Thing* thing; // thing pointer
|
|
SWORD queue; // index of queue structure
|
|
UWORD queuectr; // number of queued items
|
|
// float gain; // channel gain
|
|
};
|
|
|
|
|
|
//----- globals stuff --------------------------------------------------------------
|
|
|
|
MFX_Channel MFX_channels[MFX_MAX_CHANS];
|
|
MFX_Queue MFX_queue[MFX_MAX_QUEUED];
|
|
|
|
|
|
//----- internal stuff -------------------------------------------------------------
|
|
|
|
void MFX_trigger_paired_channel(UWORD channel_id);
|
|
void MFX_load_wave_file (CBYTE *wave_file);
|
|
|
|
|
|
inline SLONG MFX_hash(SLONG chan) { return (chan*3)&MFX_MAX_MASK; } // really crap hash
|
|
|
|
MFX_Channel* MFX_get_channel(UWORD channel_id, UWORD wave_id) {
|
|
SLONG i, first = MFX_hash(channel_id);
|
|
MFX_Channel *chan = &MFX_channels[first];
|
|
|
|
i=first;
|
|
while (1) {
|
|
if ((chan->id==channel_id)&&(chan->wave==wave_id)) return chan;
|
|
i++; chan++;
|
|
if (i>=MFX_MAX_CHANS) {
|
|
i=0; chan=MFX_channels;
|
|
}
|
|
if (i==first) return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
MFX_Channel* MFX_get_first_channel(UWORD channel_id) {
|
|
SLONG i, first = MFX_hash(channel_id);
|
|
MFX_Channel *chan = &MFX_channels[first];
|
|
|
|
i=first;
|
|
while (1) {
|
|
if (chan->id==channel_id) return chan;
|
|
i++; chan++;
|
|
if (i>=MFX_MAX_CHANS) {
|
|
i=0; chan=MFX_channels;
|
|
}
|
|
if (i==first) return NULL;
|
|
}
|
|
}
|
|
|
|
MFX_Channel* MFX_get_next_channel(MFX_Channel* chan) {
|
|
SLONG i=chan-MFX_channels, id = chan->id, first = MFX_hash(chan->id);
|
|
while (1) {
|
|
i++; chan++;
|
|
if (i>=MFX_MAX_CHANS) {
|
|
i=0; chan=MFX_channels;
|
|
}
|
|
if (i==first) return NULL;
|
|
if (chan->id==id) return chan;
|
|
}
|
|
}
|
|
|
|
|
|
MFX_Channel* MFX_get_free_channel(SLONG channel_id) {
|
|
SLONG i, first=MFX_hash(channel_id);
|
|
MFX_Channel* chan = &MFX_channels[first];
|
|
|
|
i=first;
|
|
while (1) {
|
|
if (!chan->source) return chan;
|
|
i++; chan++;
|
|
if (i>=MFX_MAX_CHANS) {
|
|
i=0; chan=MFX_channels;
|
|
}
|
|
// if (i==first) ASSERT(0);
|
|
if (i==first) return 0;
|
|
}
|
|
}
|
|
|
|
|
|
void MFX_kill(MFX_Channel* chan) {
|
|
if (!chan) return;
|
|
chan->thing=0;
|
|
if (!chan->source) return;
|
|
delete chan->source;
|
|
chan->source=0;
|
|
chan->flags=chan->id=chan->wave=0;
|
|
}
|
|
|
|
inline MFX_Channel* MFX_locate_for_play(UWORD channel_id, ULONG wave, ULONG flags) {
|
|
if (flags&MFX_OVERLAP) {
|
|
return MFX_get_free_channel(channel_id);
|
|
} else {
|
|
MFX_Channel *chan;
|
|
if (flags&(MFX_QUEUED|MFX_NEVER_OVERLAP))
|
|
chan=MFX_get_first_channel(channel_id);
|
|
else
|
|
chan=MFX_get_channel(channel_id, wave);
|
|
if (!chan)
|
|
chan=MFX_get_free_channel(channel_id);
|
|
else
|
|
if ((flags&(MFX_NEVER_OVERLAP|MFX_QUEUED))==MFX_NEVER_OVERLAP) return 0; // existing sound is fine...
|
|
return chan;
|
|
}
|
|
}
|
|
|
|
inline void MFX_std_chan_setup(MFX_Channel* chan, UWORD id, ULONG wave, ULONG flags) {
|
|
chan->id=id;
|
|
chan->wave=wave;
|
|
chan->flags=flags;
|
|
chan->source=new A3DSource(the_a3d_manager.datalist[wave]);
|
|
chan->source->User=(SLONG)chan;
|
|
chan->source->autofree=1;
|
|
chan->queue=-1;
|
|
chan->queuectr=0;
|
|
chan->thing=0;
|
|
if (flags&MFX_LO_PRIORITY) chan->source->SetPriority(0.25);
|
|
if (flags&MFX_HI_PRIORITY) chan->source->SetPriority(0.75);
|
|
}
|
|
|
|
inline UWORD MFX_queue_free(SLONG base) {
|
|
SLONG i=base;
|
|
while (1) {
|
|
if (MFX_queue[i].wave==0) return i;
|
|
i++; if (i==MFX_MAX_QUEUED) i=0;
|
|
if (i==base) return -1;
|
|
}
|
|
}
|
|
|
|
inline void MFX_queue_wave(MFX_Channel* chan, UWORD wave, ULONG flags, SLONG x, SLONG y, SLONG z) {
|
|
SLONG ndx;
|
|
MFX_Queue* q;
|
|
|
|
if ((flags&&MFX_SHORT_QUEUE)&&chan->queuectr) {
|
|
// short queue -- queued wave will always be the next wave played
|
|
q=&MFX_queue[chan->queue];
|
|
q->flags=flags;
|
|
q->wave=wave;
|
|
q->x=x; q->y=y; q->z=z;
|
|
return;
|
|
}
|
|
|
|
if (chan->queuectr>MFX_MAX_QUEUED_CHAN) return;
|
|
|
|
if (chan->queue>=0) {
|
|
ndx=chan->queue;
|
|
while (MFX_queue[ndx].next>=0) ndx=MFX_queue[ndx].next;
|
|
MFX_queue[ndx].next=MFX_queue_free(ndx);
|
|
ndx=MFX_queue[ndx].next;
|
|
} else {
|
|
chan->queue=ndx=MFX_queue_free(0);
|
|
}
|
|
if (ndx==-1) return;
|
|
chan->queuectr++;
|
|
MFX_queue[ndx].flags=flags;
|
|
MFX_queue[ndx].wave=wave;
|
|
MFX_queue[ndx].x=x;
|
|
MFX_queue[ndx].y=y;
|
|
MFX_queue[ndx].z=z;
|
|
MFX_queue[ndx].gain=1;
|
|
MFX_queue[ndx].next=-1;
|
|
}
|
|
|
|
//----- external stuff -------------------------------------------------------------
|
|
|
|
void MFX_play_xyz(UWORD channel_id, ULONG wave, ULONG flags, SLONG x, SLONG y, SLONG z) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan=MFX_locate_for_play(channel_id, wave, flags);
|
|
|
|
ASSERT(chan);
|
|
|
|
if (!chan) return; // erk, no free channels
|
|
|
|
x>>=8; y>>=8; z>>=8;
|
|
chan->x=x; chan->y=y; chan->z=z;
|
|
|
|
// we now have a channel which is either blank or can be stomped
|
|
if (chan->source) {
|
|
if (flags&MFX_QUEUED) {
|
|
MFX_queue_wave(chan,wave,flags,x,y,z);
|
|
return;
|
|
}
|
|
if ((chan->wave==wave)&!(flags&MFX_REPLACE)) {
|
|
chan->source->SetPositionl(chan->x,chan->y,chan->z);
|
|
return;
|
|
}
|
|
MFX_kill(chan);
|
|
}
|
|
|
|
MFX_std_chan_setup(chan,channel_id,wave,flags);
|
|
chan->source->SetPositionl(x,y,z);
|
|
if (!(flags&MFX_PAIRED_TRK2)) chan->source->Play(flags&MFX_LOOPED);
|
|
if (flags&MFX_PAIRED_TRK1) MFX_trigger_paired_channel(channel_id+1);
|
|
|
|
}
|
|
|
|
void MFX_play_pos(UWORD channel_id, ULONG wave, ULONG flags, GameCoord* position) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan=MFX_locate_for_play(channel_id, wave, flags);
|
|
|
|
if (!chan) return; // erk, no free channels
|
|
|
|
chan->x=position->X>>8; chan->y=position->Y>>8; chan->z=position->Z>>8;
|
|
|
|
// we now have a channel which is either blank or can be stomped
|
|
if (chan->source) {
|
|
if (flags&MFX_QUEUED) {
|
|
MFX_queue_wave(chan,wave,flags,chan->x,chan->y,chan->z);
|
|
return;
|
|
}
|
|
if ((chan->wave==wave)&!(flags&MFX_REPLACE)) {
|
|
chan->source->SetPositionl(chan->x,chan->y,chan->z);
|
|
return;
|
|
}
|
|
MFX_kill(chan);
|
|
}
|
|
|
|
MFX_std_chan_setup(chan,channel_id,wave,flags);
|
|
chan->source->SetPositionl(chan->x,chan->y,chan->z);
|
|
if (!(flags&MFX_PAIRED_TRK2)) chan->source->Play(flags&MFX_LOOPED);
|
|
if (flags&MFX_PAIRED_TRK1) MFX_trigger_paired_channel(channel_id+1);
|
|
}
|
|
|
|
void MFX_play_thing(UWORD channel_id, ULONG wave, ULONG flags, Thing* p) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan=MFX_locate_for_play(channel_id, wave, flags);
|
|
|
|
if (!chan) return; // erk, no free channels
|
|
|
|
chan->x=p->WorldPos.X>>8; chan->y=p->WorldPos.Y>>8; chan->z=p->WorldPos.Z>>8;
|
|
|
|
// we now have a channel which is either blank or can be stomped
|
|
if (chan->source) {
|
|
if (flags&MFX_QUEUED) {
|
|
MFX_queue_wave(chan,wave,flags,chan->x,chan->y,chan->z);
|
|
return;
|
|
}
|
|
if ((chan->wave==wave)&!(flags&MFX_REPLACE)) return;
|
|
MFX_kill(chan);
|
|
}
|
|
|
|
MFX_std_chan_setup(chan,channel_id,wave,flags);
|
|
chan->source->SetPositionl(chan->x,chan->y,chan->z);
|
|
if (!(flags&MFX_PAIRED_TRK2)) chan->source->Play(flags&MFX_LOOPED);
|
|
chan->thing=p;
|
|
p->Flags|=FLAGS_HAS_ATTACHED_SOUND;
|
|
if (flags&MFX_PAIRED_TRK1) MFX_trigger_paired_channel(channel_id+1);
|
|
|
|
}
|
|
|
|
void MFX_play_ambient(UWORD channel_id, ULONG wave, ULONG flags) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan=MFX_locate_for_play(channel_id, wave, flags);
|
|
|
|
if (!chan) return; // erk, no free channels
|
|
|
|
chan->x=FC_cam[0].x;
|
|
chan->y=FC_cam[0].y; // add some fancier stuff later
|
|
chan->z=FC_cam[0].z;
|
|
|
|
// we now have a channel which is either blank or can be stomped
|
|
if (chan->source) {
|
|
if (flags&MFX_QUEUED) {
|
|
MFX_queue_wave(chan,wave,flags,chan->x,chan->y,chan->z);
|
|
return;
|
|
}
|
|
if ((chan->wave==wave)&!(flags&MFX_REPLACE)) {
|
|
chan->source->SetPositionl(chan->x,chan->y,chan->z);
|
|
return;
|
|
}
|
|
MFX_kill(chan);
|
|
}
|
|
|
|
MFX_std_chan_setup(chan,channel_id,wave,flags);
|
|
chan->source->SetPositionl(chan->x,chan->y,chan->z);
|
|
if (!(flags&MFX_PAIRED_TRK2)) chan->source->Play(flags&MFX_LOOPED);
|
|
if (flags&MFX_PAIRED_TRK1) MFX_trigger_paired_channel(channel_id+1);
|
|
}
|
|
|
|
UBYTE MFX_play_stereo(UWORD channel_id, ULONG wave, ULONG flags) {
|
|
#ifdef NO_SOUND
|
|
return(0);
|
|
#endif
|
|
MFX_Channel* chan=MFX_locate_for_play(channel_id, wave, flags);
|
|
|
|
if (!chan) return 0; // erk, no free channels
|
|
|
|
// we now have a channel which is either blank or can be stomped
|
|
if (chan->source) {
|
|
if (flags&MFX_QUEUED) {
|
|
MFX_queue_wave(chan,wave,flags,0,0,0);
|
|
return 2;
|
|
}
|
|
if ((chan->wave==wave)&!(flags&MFX_REPLACE)) return 0;
|
|
MFX_kill(chan);
|
|
}
|
|
|
|
MFX_std_chan_setup(chan,channel_id,wave,flags);
|
|
if (!(flags&MFX_PAIRED_TRK2)) {
|
|
//TRACE("play stereo: live\n");
|
|
chan->source->Play(flags&MFX_LOOPED);
|
|
}
|
|
if (flags&MFX_PAIRED_TRK1) MFX_trigger_paired_channel(channel_id+1);
|
|
return 1;
|
|
}
|
|
|
|
void MFX_stop(SLONG channel_id, ULONG wave) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan;
|
|
|
|
if (channel_id==MFX_CHANNEL_ALL) {
|
|
|
|
UWORD i;
|
|
for (i=0,chan=MFX_channels;i<MFX_MAX_CHANS;i++,chan++) {
|
|
MFX_kill(chan);
|
|
}
|
|
|
|
} else {
|
|
|
|
if (wave==MFX_WAVE_ALL) {
|
|
|
|
MFX_Channel* next;
|
|
chan = MFX_get_first_channel(channel_id);
|
|
while (chan) {
|
|
next=MFX_get_next_channel(chan);
|
|
MFX_kill(chan);
|
|
chan=next;
|
|
}
|
|
|
|
} else {
|
|
|
|
MFX_kill(MFX_get_channel(channel_id,wave));
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void MFX_stop_attached(Thing *p) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
SLONG i;
|
|
MFX_Channel *chan=MFX_channels;
|
|
|
|
for (i=0;i<MFX_MAX_CHANS;i++,chan++) {
|
|
if (chan->thing==p) MFX_kill(chan);
|
|
}
|
|
}
|
|
|
|
//----- audio processing functions -----
|
|
|
|
|
|
void MFX_set_pitch(UWORD channel_id, ULONG wave, SLONG pitchbend) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan = MFX_get_channel(channel_id, wave);
|
|
float pitch;
|
|
|
|
if(!chan)
|
|
return;
|
|
|
|
pitch=(float)(pitchbend+256)/256.0f;
|
|
if (chan->source) chan->source->SetPitchf(pitch);
|
|
}
|
|
|
|
void MFX_set_gain(UWORD channel_id, ULONG wave, UBYTE gain) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan = MFX_get_channel(channel_id, wave);
|
|
float fgain;
|
|
|
|
if(!chan)
|
|
return;
|
|
|
|
fgain=(float)(gain)/256.0f;
|
|
//TRACE("gain set: %f\n",fgain);
|
|
if (chan->source) chan->source->SetGainf(fgain);
|
|
}
|
|
|
|
void MFX_set_queue_gain(UWORD channel_id, ULONG wave, UBYTE gain) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan = MFX_get_channel(channel_id, wave);
|
|
MFX_Queue* q;
|
|
float fgain;
|
|
|
|
if(!chan) return;
|
|
|
|
fgain=(float)(gain)/256.0f;
|
|
if (chan->queue>=0)
|
|
q=&MFX_queue[chan->queue];
|
|
else { // assume we really want to set the current one?
|
|
// TRACE("queuef (short circuit) gain set: %f\n",fgain);
|
|
if (chan->source) chan->source->SetGainf(fgain);
|
|
return;
|
|
}
|
|
// TRACE("queuef gain set: %f\n",fgain);
|
|
while (q) {
|
|
q->gain=fgain;
|
|
q=(q->next)?&MFX_queue[q->next]:0;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
void MFX_set_channel_gain(UWORD channel_id, UBYTE gain) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan = MFX_get_channel(channel_id,0);
|
|
|
|
if (!chan) return;
|
|
chan->gain=(float)(gain)/256.0;
|
|
if (chan->source) chan->source->SetGainf(chan->gain);
|
|
}
|
|
*/
|
|
|
|
void MFX_set_wave(UWORD channel_id, ULONG wave, ULONG new_wave) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan = MFX_get_channel(channel_id, wave);
|
|
}
|
|
|
|
|
|
void MFX_set_xyz(UWORD channel_id, UWORD wave, SLONG x, SLONG y, SLONG z) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan = MFX_get_channel(channel_id, wave);
|
|
if(!chan)
|
|
return;
|
|
if (chan->source) chan->source->SetPositionl(x>>8,y>>8,z>>8);
|
|
}
|
|
|
|
|
|
void MFX_set_pos(UWORD channel_id, UWORD wave, GameCoord* position) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
MFX_Channel* chan = MFX_get_channel(channel_id, wave);
|
|
if(!chan)
|
|
return;
|
|
if (chan->source) chan->source->SetPositionl(position->X>>8,position->Y>>8,position->Z>>8);
|
|
}
|
|
|
|
//----- listener & environment -----
|
|
|
|
void MFX_set_listener(SLONG x, SLONG y, SLONG z, SLONG heading, SLONG roll, SLONG pitch) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
float h,p,r;
|
|
|
|
heading*=360; h=(float)heading; h/=2048;
|
|
pitch*=360; p=(float)pitch; p/=2048;
|
|
a3dgeom->LoadIdentity();
|
|
a3dgeom->PushMatrix();
|
|
a3dgeom->Translate3f((float)x/256.0f,(float)y/256.0f,(float)z/256.0f);
|
|
a3dgeom->Rotate3f(-h,0,1,0);
|
|
a3dgeom->Rotate3f(p,1,0,0);
|
|
a3dgeom->Scale3f(1,1,-1);
|
|
a3dgeom->BindListener();
|
|
a3dgeom->PopMatrix();
|
|
|
|
}
|
|
|
|
void MFX_set_environment(SLONG env_type) {
|
|
// do nothing for the moment.
|
|
// later, probably set up some funkatronic a3d stuff
|
|
}
|
|
|
|
//----- sound library functions -----
|
|
|
|
extern CBYTE *sound_list[];
|
|
|
|
void MFX_load_wave_list(CBYTE *names[]) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
|
|
SLONG i;
|
|
CBYTE buff[_MAX_PATH];
|
|
void *oldnames=NULL;
|
|
|
|
if (names==0) names=sound_list;
|
|
|
|
if (MFX_initialised)
|
|
MFX_stop(MFX_CHANNEL_ALL,MFX_WAVE_ALL);
|
|
|
|
if (oldnames==names) return;
|
|
|
|
oldnames=names;
|
|
|
|
MFX_free_wave_list();
|
|
|
|
memset(MFX_channels,0,sizeof(MFX_Channel)*MFX_MAX_CHANS);
|
|
|
|
i=0;
|
|
while (strcmp(names[i],"!")) {
|
|
|
|
if (stricmp("NULL.wav",names[i])) {
|
|
strcpy(buff,"Data\\sfx\\1622\\");
|
|
strcat(buff,names[i]);
|
|
MFX_load_wave_file(buff);
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void MFX_load_wave_list(CBYTE *path,CBYTE *script_file) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
|
|
FILE *script_handle;
|
|
CBYTE wave_name[MAX_PATH],
|
|
wave_file[MAX_PATH];
|
|
ULONG streamed; // currently ignored...
|
|
// static CBYTE previous_list[_MAX_PATH]={0};
|
|
|
|
// if (!stricmp(previous_list,script_file)) return;
|
|
|
|
MFX_free_wave_list();
|
|
|
|
// strcpy(previous_list,script_file);
|
|
|
|
memset(MFX_channels,0,sizeof(MFX_Channel)*MFX_MAX_CHANS);
|
|
|
|
script_handle = MF_Fopen(script_file,"r");
|
|
if(script_handle)
|
|
{
|
|
while(fscanf(script_handle,"%s %d",wave_name,&streamed)>0)
|
|
{
|
|
strcpy(wave_file,path);
|
|
strcat(wave_file,wave_name);
|
|
// cunning correction thingy
|
|
if (stricmp("NULL.wav",wave_name))
|
|
MFX_load_wave_file(wave_file);
|
|
}
|
|
|
|
// Finished with the script.
|
|
MF_Fclose(script_handle);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void MFX_load_wave_file(CBYTE *wave_file) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
|
|
A3DData *wave;
|
|
|
|
if (strstr(wave_file,"music\\")) {
|
|
wave = new A3DData(wave_file,A3DSOURCE_INITIAL_RENDERMODE_NATIVE);
|
|
} else {
|
|
wave = new A3DData(wave_file);
|
|
}
|
|
wave->owner=1;
|
|
}
|
|
|
|
void MFX_free_wave_list(void) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
A3DData *item, *next;
|
|
|
|
if (MFX_initialised)
|
|
MFX_stop(MFX_CHANNEL_ALL,MFX_WAVE_ALL);
|
|
else
|
|
memset(MFX_channels,0,sizeof(MFX_Channel)*MFX_MAX_CHANS);
|
|
|
|
MFX_initialised=1;
|
|
|
|
item=static_cast<A3DData*>(the_a3d_manager.datalist.Head());
|
|
while (item) {
|
|
next=static_cast<A3DData*>(item->next);
|
|
if (item->owner==1) delete item;
|
|
item=next;
|
|
}
|
|
}
|
|
|
|
//----- querying information back -----
|
|
|
|
UWORD MFX_get_wave(UWORD channel_id, UBYTE index) {
|
|
MFX_Channel *chan=MFX_get_first_channel(channel_id);
|
|
while (index) {
|
|
chan=MFX_get_next_channel(chan);
|
|
index--;
|
|
}
|
|
return chan?chan->wave:0;
|
|
|
|
}
|
|
|
|
//----- general system stuff -----
|
|
|
|
void MFX_render ( void ) {
|
|
#ifdef NO_SOUND
|
|
return;
|
|
#endif
|
|
A3DSource *item, *next;
|
|
MFX_Channel* targ;
|
|
MFX_Queue* q;
|
|
|
|
the_a3d_manager.Render();
|
|
item=static_cast<A3DSource*>(the_a3d_manager.srclist.Head());
|
|
while (item) {
|
|
next=static_cast<A3DSource*>(item->next);
|
|
targ=(MFX_Channel*)item->User;
|
|
if (targ->flags&MFX_PAIRED_TRK2) { item=next; continue; }
|
|
if (item->autofree&&item->HasEnded((targ->flags&MFX_EARLY_OUT)?1:0)) {
|
|
if (targ) {
|
|
if (!targ->queuectr) {
|
|
// TRACE("[MFX] deleted\n");
|
|
targ->source=0;
|
|
delete item;
|
|
if (targ->thing) targ->thing->Flags&=~FLAGS_HAS_ATTACHED_SOUND;
|
|
} else {
|
|
float gain;
|
|
// if (targ->thing&&(targ->thing->Class==CLASS_VEHICLE)) TRACE("[MFX] queue-play\n");
|
|
q=&MFX_queue[targ->queue];
|
|
gain=q->gain;
|
|
|
|
if (q->flags&MFX_PAIRED_TRK1) MFX_trigger_paired_channel(targ->id+1);
|
|
|
|
// update targ
|
|
targ->flags=q->flags&~MFX_PAIRED_TRK2; // no longer relevant
|
|
if ((targ->flags&MFX_MOVING)&&(targ->thing)) {
|
|
targ->x=targ->thing->WorldPos.X>>8;
|
|
targ->y=targ->thing->WorldPos.Y>>8;
|
|
targ->z=targ->thing->WorldPos.Z>>8;
|
|
} else {
|
|
targ->x=q->x; targ->y=q->y; targ->z=q->z;
|
|
}
|
|
//if (q->wave>100) TRACE("MFX play from queue -- w%d gain%f\n",q->wave,gain);
|
|
targ->wave=q->wave;
|
|
targ->queuectr--;
|
|
targ->queue=q->next;
|
|
// free q
|
|
q->wave=0;
|
|
// update source
|
|
item->Change(the_a3d_manager.datalist[targ->wave]);
|
|
item->SetPositionl(targ->x,targ->y,targ->z);
|
|
item->SetGainf(gain);
|
|
item->Play(q->flags&MFX_LOOPED);
|
|
the_a3d_manager.Render();
|
|
|
|
}
|
|
} else {
|
|
// TRACE("[MFX] deleted (no User)\n");
|
|
delete item;
|
|
}
|
|
} else {
|
|
// it continues playing... we may need to do some processing
|
|
if (targ) {
|
|
if (targ->flags&MFX_CAMERA) {
|
|
// TRACE("[MFX] repositioned by camera\n");
|
|
targ->x=FC_cam[0].x>>8;
|
|
targ->z=FC_cam[0].z>>8;
|
|
if (!(targ->flags&MFX_LOCKY)) targ->y=FC_cam[0].y>>8;
|
|
item->SetPositionl(targ->x,targ->y,targ->z);
|
|
}
|
|
if ((targ->flags&MFX_MOVING)&&(targ->thing)) {
|
|
targ->x=targ->thing->WorldPos.X>>8;
|
|
targ->y=targ->thing->WorldPos.Y>>8;
|
|
targ->z=targ->thing->WorldPos.Z>>8;
|
|
item->SetPositionl(targ->x,targ->y,targ->z);
|
|
}
|
|
}
|
|
}
|
|
item=next;
|
|
}
|
|
}
|
|
|
|
|
|
void MFX_trigger_paired_channel(UWORD channel_id) {
|
|
MFX_Channel* chan;
|
|
|
|
chan = MFX_get_first_channel(channel_id);
|
|
|
|
if (!chan||!chan->source) return;
|
|
|
|
chan->flags&=~MFX_PAIRED_TRK2;
|
|
chan->source->Play(chan->flags&MFX_LOOPED);
|
|
}
|
|
|
|
|
|
|
|
#endif //#if defined(Q_SOUND) || defined(NO_SOUND)
|
|
#endif
|