raze/polymer/build/src/sound.c

388 lines
9 KiB
C

// 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)
{
return kopen4load((char *)name, 0) + 1;
}
static void F_CALLBACKAPI f_close(unsigned int handle)
{
kclose(handle - 1);
}
static int F_CALLBACKAPI f_read(void *buffer, int size, unsigned int handle)
{
return kread(handle - 1, buffer, size);
}
static int F_CALLBACKAPI f_seek(unsigned int handle, int pos, signed char mode)
{
return klseek(handle - 1, pos, mode);
}
static int F_CALLBACKAPI f_tell(unsigned int handle)
{
return ktell(handle - 1);
}
void initsb(char dadigistat, char damusistat, int dasamplerate, char danumspeakers, char dabytespersample, char daintspersec, char daquality)
{
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("Initializing 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())
{
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;
}
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;
}
void uninitsb(void)
{
if (fmod_inited)
{
FSOUND_Close();
fmod_inited = 0;
}
}
void setears(int daposx, int daposy, int daxvect, int dayvect)
{
}
void wsayfollow(char *dafilename, int dafreq, int davol, int *daxplc, int *dayplc, char followstat)
{
/*
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;
int 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;
}
}
void wsay(char *dafilename, int dafreq, int volume1, int volume2)
{
unsigned char ch1, ch2;
int 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);
}
void loadwaves(void)
{
int fil, dawaversionum, i, tmp;
int 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);
}
#if 1
static FSOUND_STREAM *musicstream = NULL;
static int musicplaying = 0;
void loadsong(char *filename)
{
if (!musicstat) return;
if (musicstream) return;
#ifdef FMOD_PRE370
musicstream = FSOUND_Stream_OpenFile(filename, FSOUND_LOOP_NORMAL, 0);
#else
musicstream = FSOUND_Stream_Open(filename, FSOUND_LOOP_NORMAL, 0, 0);
#endif
}
void musicon(void)
{
if (!musicstat) return;
if (!musicstream || musicplaying) return;
FSOUND_Stream_Play(FSOUND_FREE, musicstream);
musicplaying = 1;
}
void musicoff(void)
{
if (!musicstat) return;
if (!musicstream || !musicplaying) return;
FSOUND_Stream_Stop(musicstream);
musicplaying = 0;
}
#endif
void refreshaudio(void)
{
}