2006-04-13 20:47:06 +00:00
|
|
|
// FMOD Sound Interface
|
|
|
|
// for the Build Engine
|
|
|
|
// by Jonathon Fowler (jonof@edgenetwk.com)
|
|
|
|
|
|
|
|
#include "fmod.h"
|
|
|
|
#include "fmod_errors.h"
|
|
|
|
|
|
|
|
#ifndef F_CALLBACKAPI
|
|
|
|
#define FMOD_PRE370
|
|
|
|
#define F_CALLBACKAPI _cdecl
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// some Linux people may need this if GCC can't find FSOUND_Stream_Open
|
|
|
|
// #define FMOD_PRE370
|
|
|
|
|
|
|
|
#include "osd.h"
|
|
|
|
#include "compat.h"
|
|
|
|
#include "cache1d.h"
|
|
|
|
|
|
|
|
#define NUMCHANNELS 16
|
|
|
|
#define MAXWAVES 256
|
|
|
|
|
|
|
|
|
|
|
|
static int fmod_inited = 0;
|
|
|
|
static int musicstat = 0;
|
|
|
|
|
|
|
|
// general sample playback
|
|
|
|
static int numwaves;
|
|
|
|
static FSOUND_SAMPLE * samples[MAXWAVES];
|
|
|
|
static char instname[MAXWAVES][16];
|
|
|
|
static int channels[NUMCHANNELS];
|
|
|
|
|
|
|
|
void loadwaves(void);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned int F_CALLBACKAPI f_open(const char *name)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
return kopen4load((char *)name, 0) + 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void F_CALLBACKAPI f_close(unsigned int handle)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
kclose(handle - 1);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int F_CALLBACKAPI f_read(void *buffer, int size, unsigned int handle)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
return kread(handle - 1, buffer, size);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int F_CALLBACKAPI f_seek(unsigned int handle, int pos, signed char mode)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
return klseek(handle - 1, pos, mode);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int F_CALLBACKAPI f_tell(unsigned int handle)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
return ktell(handle - 1);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void initsb(char dadigistat, char damusistat, long dasamplerate, char danumspeakers, char dabytespersample, char daintspersec, char daquality)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
char *s;
|
|
|
|
int i,j;
|
|
|
|
|
|
|
|
if (fmod_inited) return;
|
|
|
|
fmod_inited = 0;
|
|
|
|
|
|
|
|
if (dasamplerate < 6000) dasamplerate = 6000;
|
|
|
|
else if (dasamplerate > 48000) dasamplerate = 48000;
|
|
|
|
|
|
|
|
musicstat = damusistat;
|
|
|
|
|
|
|
|
printOSD("Initialising FMOD...\n");
|
|
|
|
printOSD(" Linked version: %.02f\n", FMOD_VERSION);
|
|
|
|
printOSD(" DLL version: %.02f\n", FSOUND_GetVersion());
|
|
|
|
|
|
|
|
if (FSOUND_GetVersion() < FMOD_VERSION) {
|
|
|
|
printOSD(" ... Failure: FMOD DLL too old! Sound disabled.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
printOSD(" Samplerate: %d hz\n", dasamplerate);
|
|
|
|
|
|
|
|
//FSOUND_SetOutput(FSOUND_OUTPUT_ASIO);
|
|
|
|
|
|
|
|
if (FSOUND_Init(dasamplerate, NUMCHANNELS, 0)) {
|
|
|
|
printOSD(" ... Success\n");
|
|
|
|
fmod_inited = 1;
|
|
|
|
} else {
|
|
|
|
printOSD(" ... Failure: %s\n", FMOD_ErrorString(FSOUND_GetError()));
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (FSOUND_GetOutput()) {
|
2006-11-13 23:12:47 +00:00
|
|
|
case FSOUND_OUTPUT_NOSOUND:
|
|
|
|
s = "No Sound"; break;
|
|
|
|
case FSOUND_OUTPUT_WINMM:
|
|
|
|
s = "WINMM"; break;
|
|
|
|
case FSOUND_OUTPUT_DSOUND:
|
|
|
|
s = "DirectSound"; break;
|
|
|
|
case FSOUND_OUTPUT_OSS:
|
|
|
|
s = "OSS"; break;
|
|
|
|
case FSOUND_OUTPUT_ESD:
|
|
|
|
s = "ESound"; break;
|
|
|
|
case FSOUND_OUTPUT_ALSA:
|
|
|
|
s = "ALSA"; break;
|
|
|
|
case FSOUND_OUTPUT_ASIO:
|
|
|
|
s = "ASIO"; break;
|
|
|
|
default:
|
|
|
|
s = "Other"; break;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
printOSD("Using FMOD \"%s\" output driver\n", s);
|
|
|
|
|
|
|
|
FSOUND_File_SetCallbacks(
|
|
|
|
(FSOUND_OPENCALLBACK)f_open,
|
|
|
|
(FSOUND_CLOSECALLBACK)f_close,
|
|
|
|
(FSOUND_READCALLBACK)f_read,
|
|
|
|
(FSOUND_SEEKCALLBACK)f_seek,
|
|
|
|
(FSOUND_TELLCALLBACK)f_tell);
|
|
|
|
//FSOUND_SetMemorySystem(fmod_cache, fmod_cachelen, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
loadwaves();
|
|
|
|
|
|
|
|
for (i=0; i<NUMCHANNELS; i++) channels[i] = -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void uninitsb(void)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
if (fmod_inited) {
|
|
|
|
FSOUND_Close();
|
|
|
|
fmod_inited = 0;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setears(long daposx, long daposy, long daxvect, long dayvect)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void wsayfollow(char *dafilename, long dafreq, long davol, long *daxplc, long *dayplc, char followstat)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
/*
|
|
|
|
dafilename:
|
|
|
|
filename
|
|
|
|
|
|
|
|
dafreq:
|
|
|
|
4096 = Middle C
|
|
|
|
8192 = +1 8ve
|
|
|
|
|
|
|
|
davol:
|
|
|
|
0-256 = volume
|
|
|
|
|
|
|
|
daxplc:
|
|
|
|
dayplc:
|
|
|
|
followstat: 0 = sound emination origin (fixed)
|
|
|
|
followstat: 1 = pointer to sprite coordinates (dynamic)
|
|
|
|
|
|
|
|
followstat:
|
|
|
|
0 = position is fixed in space
|
|
|
|
1 = position follows an object
|
|
|
|
*/
|
|
|
|
unsigned char ch1, ch2;
|
|
|
|
long i, wavnum, bad, oldest=0, free=-1, ox, oy, x, y, vo;
|
|
|
|
unsigned int oldestpos=0;
|
|
|
|
int chan;
|
|
|
|
|
|
|
|
if (fmod_inited == 0) return;
|
|
|
|
|
|
|
|
for (wavnum=numwaves-1;wavnum>=0;wavnum--) {
|
|
|
|
bad = 0;
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while ((dafilename[i] > 0) && (i < 16))
|
|
|
|
{
|
|
|
|
ch1 = dafilename[i]; if ((ch1 >= 97) && (ch1 <= 123)) ch1 -= 32;
|
|
|
|
ch2 = instname[wavnum][i]; if ((ch2 >= 97) && (ch2 <= 123)) ch2 -= 32;
|
|
|
|
if (ch1 != ch2) {bad = 1; break;}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (bad != 0) continue;
|
|
|
|
|
|
|
|
for (i=0; i<NUMCHANNELS; i++) {
|
|
|
|
if (!FSOUND_IsPlaying(channels[i])) {
|
|
|
|
free = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i==0) continue;
|
|
|
|
|
|
|
|
if (FSOUND_GetCurrentPosition(channels[i]) > oldestpos) {
|
|
|
|
oldest = i;
|
|
|
|
oldestpos = FSOUND_GetCurrentPosition(channels[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (free < 0) {
|
|
|
|
FSOUND_StopSound(channels[oldest]);
|
|
|
|
free = oldest;
|
|
|
|
}
|
|
|
|
|
|
|
|
chan = FSOUND_PlaySoundEx(FSOUND_FREE, samples[wavnum], NULL, 1);
|
|
|
|
if (chan == -1) return;
|
|
|
|
FSOUND_SetFrequency(chan, dafreq*11025/4096);
|
|
|
|
FSOUND_SetVolume(chan, davol);
|
|
|
|
|
|
|
|
FSOUND_SetPaused(chan, 0);
|
|
|
|
|
|
|
|
channels[free] = chan;
|
|
|
|
return;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void wsay(char *dafilename, long dafreq, long volume1, long volume2)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
unsigned char ch1, ch2;
|
|
|
|
long i, j, bad, free=-1, oldest=0;
|
|
|
|
unsigned int oldestpos=0;
|
|
|
|
int chan;
|
|
|
|
|
|
|
|
if (fmod_inited == 0) return;
|
|
|
|
|
|
|
|
i = numwaves-1;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
bad = 0;
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
while ((dafilename[j] > 0) && (j < 16))
|
|
|
|
{
|
|
|
|
ch1 = dafilename[j]; if ((ch1 >= 97) && (ch1 <= 123)) ch1 -= 32;
|
|
|
|
ch2 = instname[i][j]; if ((ch2 >= 97) && (ch2 <= 123)) ch2 -= 32;
|
|
|
|
if (ch1 != ch2) {bad = 1; break;}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
if (bad == 0)
|
|
|
|
{
|
|
|
|
for (j=0; j<NUMCHANNELS; j++) {
|
|
|
|
if (!FSOUND_IsPlaying(channels[j])) {
|
|
|
|
free = j;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (j==0) continue;
|
|
|
|
|
|
|
|
if (FSOUND_GetCurrentPosition(channels[j]) > oldestpos) {
|
|
|
|
oldest = j;
|
|
|
|
oldestpos = FSOUND_GetCurrentPosition(channels[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (free < 0) {
|
|
|
|
FSOUND_StopSound(channels[oldest]);
|
|
|
|
free = oldest;
|
|
|
|
}
|
|
|
|
|
|
|
|
chan = FSOUND_PlaySoundEx(FSOUND_FREE, samples[i], NULL, 1);
|
|
|
|
if (chan == -1) return;
|
|
|
|
FSOUND_SetFrequency(chan, dafreq*11025/4096);
|
|
|
|
FSOUND_SetVolume(chan, (volume1*volume2)>>1);
|
|
|
|
// set pan
|
|
|
|
FSOUND_SetPaused(chan, 0);
|
|
|
|
|
|
|
|
channels[free] = chan;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
i--;
|
|
|
|
} while (i >= 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void loadwaves(void)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
long fil, dawaversionum, i, tmp;
|
|
|
|
long wavleng[MAXWAVES], repstart[MAXWAVES], repleng[MAXWAVES], finetune[MAXWAVES];
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
fil = kopen4load("WAVES.KWV", 0);
|
|
|
|
|
|
|
|
if (fil != -1) {
|
|
|
|
kread(fil, &dawaversionum, 4); dawaversionum = B_LITTLE32(dawaversionum);
|
|
|
|
if (dawaversionum != 0) { kclose(fil); return; }
|
|
|
|
|
|
|
|
kread(fil, &numwaves, 4); numwaves = B_LITTLE32(numwaves);
|
|
|
|
for (i=0; i<numwaves; i++) {
|
|
|
|
kread(fil, &instname[i][0], 16);
|
|
|
|
kread(fil, &wavleng[i], 4); wavleng[i] = B_LITTLE32(wavleng[i]);
|
|
|
|
kread(fil, &repstart[i], 4); repstart[i] = B_LITTLE32(repstart[i]);
|
|
|
|
kread(fil, &repleng[i], 4); repleng[i] = B_LITTLE32(repleng[i]);
|
|
|
|
kread(fil, &finetune[i], 4); finetune[i] = B_LITTLE32(finetune[i]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
dawaversionum = 0;
|
|
|
|
numwaves = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=numwaves; i<MAXWAVES; i++) {
|
|
|
|
memset(&instname[i][0], 0, 16);
|
|
|
|
wavleng[i] = 0;
|
|
|
|
repstart[i] = 0;
|
|
|
|
repleng[i] = 0;
|
|
|
|
finetune[i] = 0;
|
|
|
|
samples[i] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fil == -1) return;
|
|
|
|
|
|
|
|
for (i=0; i<numwaves; i++) {
|
|
|
|
if (repleng[i]) tmp = FSOUND_LOOP_NORMAL;
|
|
|
|
else tmp = FSOUND_LOOP_OFF;
|
|
|
|
samples[i] = FSOUND_Sample_Alloc(FSOUND_FREE, wavleng[i], tmp, 11025, 255, 128, 1);
|
|
|
|
if (!samples[i]) continue;
|
|
|
|
|
|
|
|
p = (char*)Bmalloc(wavleng[i]);
|
|
|
|
kread(fil,p,wavleng[i]);
|
|
|
|
FSOUND_Sample_Upload(samples[i], p, FSOUND_8BITS | FSOUND_MONO | FSOUND_UNSIGNED);
|
|
|
|
Bfree(p);
|
|
|
|
|
|
|
|
if (repleng[i]) FSOUND_Sample_SetLoopPoints(samples[i], repstart[i], repstart[i]+repleng[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
kclose(fil);
|
|
|
|
|
|
|
|
printOSD("Loaded %d waves\n", numwaves);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
static FSOUND_STREAM *musicstream = NULL;
|
|
|
|
static int musicplaying = 0;
|
|
|
|
|
|
|
|
void loadsong(char *filename)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
if (!musicstat) return;
|
|
|
|
if (musicstream) return;
|
2006-04-13 20:47:06 +00:00
|
|
|
#ifdef FMOD_PRE370
|
2006-04-24 19:04:22 +00:00
|
|
|
musicstream = FSOUND_Stream_OpenFile(filename, FSOUND_LOOP_NORMAL, 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
#else
|
2006-04-24 19:04:22 +00:00
|
|
|
musicstream = FSOUND_Stream_Open(filename, FSOUND_LOOP_NORMAL, 0, 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void musicon(void)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
if (!musicstat) return;
|
|
|
|
if (!musicstream || musicplaying) return;
|
|
|
|
FSOUND_Stream_Play(FSOUND_FREE, musicstream);
|
|
|
|
musicplaying = 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void musicoff(void)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
if (!musicstat) return;
|
|
|
|
if (!musicstream || !musicplaying) return;
|
|
|
|
FSOUND_Stream_Stop(musicstream);
|
|
|
|
musicplaying = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void refreshaudio(void)
|
|
|
|
{
|
|
|
|
}
|