10
#include "copyright.h"
17
#include <sys/types.h>
29
#include <sys/types.h>
30
#include <sys/prctl.h>
32
#include <dmedia/audio.h>
33
#include <dmedia/audiofile.h>
37
#include "sgi-sound.h"
46
#if defined(HAVE_SDL) || defined(sgi)
69
FIRE_PLASMA_OTHER_WAV,
71
SBEXPLOSION_OTHER_WAV,
77
/* This is probably unix specific paths */
78
static Mix_Chunk *sounds[NUM_WAVES];
82
static ALport sfxInitAudioPort(int init);
83
static short *sfxLoadAudioFile(char *dirName, char *fileName, AFframecount *size);
84
static int sfxCheckForAudio(void);
85
static int sfxOpenAudioPorts(ALport ports[], int maxAudioPorts);
86
static void sfxCheckVolume(void);
87
static void sfxResetAudioHw(void);
88
static void sfxSetGain(float l, float r);
89
static void sfxSetGainIndex(unsigned long gain);
90
static void sfxSignalSound(Sfx sp);
91
static void sfxDieGracefully(int sig);
92
static void sfxSoundDied(int sig);
93
static void sfxSoundErrFunc(long err, const char *msg, ...);
94
static void sfxSoundHandler(void *arg);
96
static Sfx sounds[NUM_WAVES]; /* waveform storage */
97
static ALport audioPort[MAX_AUDIO_PORTS]; /* audio port structure */
98
static int nAudioPorts; /* number of audio ports */
99
static int soundOther = 1; /* sound toggle for other ships */
100
static int soundChild; /* set if child process is running */
101
static int gainIndex; /* current gain index */
102
static int endingOnPurpose = 0; /* set if sound should end on purpose */
103
static int spigot[2]; /* pipe to the child process */
104
static int soundId = 0; /* ID of current sound */
105
static char *sfxAudioDir; /* directory with sound files */
106
static unsigned long origLeftGain; /* initial gain setting for left channel */
107
static unsigned long origRightGain; /* initial gain setting for right channel */
108
static unsigned long origOutputRate; /* initial output sample rate */
109
static unsigned long currLeftGain; /* current gain setting for left channel */
110
static unsigned long currRightGain; /* current gain setting for right channel */
111
static unsigned long gainSettings[] = { 0, 2, 3, 5, 9, 16, 29, 50, 91, 156, 255 };
114
#if !defined(HAVE_SDL) && !defined(sgi)
116
/* Each sound has a priority which controls what can override what
117
* Currently these are set as follows:
122
* 7: torp fire, cloak
124
* 4: "informational" sounds (self destruct, enter ship, message, etc.)
125
* 3: shield up/down, other people's sounds (phaser, torp, plasma, explode)
126
* 0: background or ambient (engine?)
128
static struct Sound sounds[NUM_SOUNDS+1] = {
130
{"nt_fire_torp", 7, 1},
132
{"nt_fire_plasma", 9, 1},
133
{"nt_explosion", 10, 1},
134
{"nt_cloaked", 7, 1},
135
{"nt_uncloak", 7, 1},
136
{"nt_shield_down", 3, 1},
137
{"nt_shield_up", 3, 1},
138
{"nt_torp_hit", 8, 1},
139
{"nt_warning", 5, 1},
141
{"nt_enter_ship", 4, 1},
142
{"nt_self_destruct", 6, 1},
143
{"nt_plasma_hit", 8, 1},
144
{"nt_message", 4, 1},
145
{"nt_message1", 4, 1},
146
{"nt_message2", 4, 1},
147
{"nt_message3", 4, 1},
148
{"nt_message4", 4, 1},
149
{"nt_message5", 4, 1},
150
{"nt_message6", 4, 1},
151
{"nt_message7", 4, 1},
152
{"nt_message8", 4, 1},
153
{"nt_message9", 4, 1},
154
{"nt_fire_torp_other", 3, 1},
155
{"nt_phaser_other", 3, 1},
156
{"nt_fire_plasma_other", 3, 1},
157
{"nt_explosion_other", 10, 1}
160
static char sound_prefix[PATH_MAX];
161
static int current_sound = NO_SOUND;
162
static int soundOther = 1; /* play other ship's sounds? */
164
#endif /* HAVE_SDL */
166
static int isDirectory(char* dir) { /* check wheter `dir' is a directory */
169
if (stat(dir, &buf) < 0) {
170
(void) fprintf(stderr, "stat of directory `%s' failed: %s\n", dir, strerror(errno));
173
return S_ISDIR(buf.st_mode);
179
* Initialize the audio hardware.
181
int sfxInit(char *audioDir, int numPorts) {
185
if (audioDir != NULL) {
186
str = strdup(audioDir);
191
return SFX_ERR_NO_PORTS_AVAIL;
193
if (numPorts > MAX_AUDIO_PORTS)
194
numPorts = MAX_AUDIO_PORTS;
196
(void) ALseterrorhandler(sfxSoundErrFunc);
198
nAudioPorts = sfxOpenAudioPorts(audioPort, numPorts);
200
if (nAudioPorts == 0)
201
return SFX_ERR_NO_PORTS_AVAIL;
204
return SFX_ERR_NO_AUDIO_HW;
206
(void) signal(SIGCHLD, sfxSoundDied);
208
if (pipe(spigot) < 0 || (soundChild = sproc(sfxSoundHandler, PR_SADDR, audioPort)) < 0) {
209
for (idx=0; idx < nAudioPorts; idx++)
210
ALcloseport(audioPort[idx]);
212
return SFX_ERR_NO_SPROC;
218
* Load an audio file.
220
Sfx sfxLoad(char *filename) {
223
if ((sp=(Sfx)malloc(sizeof(struct _sfx))) == NULL)
226
sp->soundData = NULL;
227
sp->soundSize = NULL;
234
if ((sp->soundData=(short **)malloc(sizeof(short *))) == NULL) {
238
if ((sp->soundSize=(AFframecount *)malloc(sizeof(AFframecount))) == NULL) {
242
if ((sp->soundData[0] = sfxLoadAudioFile(sfxAudioDir, filename, &(sp->soundSize[0]))) == NULL) {
251
* Indicate that a sound is to loop.
253
void sfxLoop(Sfx sp) {
260
* Play a sound effect.
262
void sfxPlay(Sfx sp) {
263
if (sound_init && sp != NULL && sp->soundData[0] && sp->enabled) {
274
* Play a pitch-bent audio clip.
276
void sfxPlayPitch(Sfx sp, float val) {
279
if (sound_init && sp != NULL && sp->soundData[0] && sp->enabled) {
280
if (val <= sp->loVal)
282
else if (val >= sp->hiVal)
285
i = (long)(0.4f + (sp->count - 1) *
286
(val - sp->loVal)/(sp->hiVal - sp->loVal));
288
if (sp->loop && sp->repeat && sp->pitch == i)
298
* Create a pitch bend audio clip.
300
void sfxPitchBend(Sfx sp, float startVal, float endVal,
301
float startPitch, float endPitch,
302
float basePitch, int steps) {
313
if (sp == NULL || steps < 2 || sp->count != 1)
316
if ((lptr=(AFframecount *)malloc(steps * sizeof(AFframecount))) == NULL)
320
a = (endPitch - startPitch) / (double)(steps - 1);
321
b = 1.0 / (double)basePitch;
323
for (i=0; i < steps; i++) {
324
pitch = (startPitch + (double)i * a) * b;
325
k = (long)((double)sp->soundSize[0] / pitch);
329
if ((ptr=(short **)malloc(steps * sizeof(short *))) == NULL) {
335
* Allocate new space for pitch-bent sound data.
337
if ((data=(short *)malloc(size * 2 * sizeof(short))) == NULL) {
343
size = (int)sp->soundSize[0];
345
sp->soundSize = lptr;
347
origData = sp->soundData[0];
352
sp->loVal = startVal;
355
for (i=0; i < steps; i++) {
356
pitch = (startPitch + (double)i * a) * b;
359
sp->soundData[i] = data;
361
sp->soundData[i] = sp->soundData[i-1] + 2 * sp->soundSize[i-1];
363
for (k=0; k < sp->soundSize[i]; k++) {
364
frameIndex = (long)(k * pitch + 0.5);
365
if (frameIndex >= size)
366
frameIndex = size - 1;
368
sp->soundData[i][2*k ] = origData[2*frameIndex ];
369
sp->soundData[i][2*k+1] = origData[2*frameIndex+1];
377
* Silence an audio loop.
379
void sfxSilenceLoop(Sfx sp) {
380
if (sp != NULL && sp->repeat) {
388
* Disable a sound clip.
390
void sfxDisable(Sfx sp) {
400
* Enable a sound clip.
402
void sfxEnable(Sfx sp) {
409
* Check whether a sound clip is enabled.
411
int sfxIsEnabled(Sfx sp) {
412
return (sp != NULL) && sp->enabled;
416
* Set the volume to a specified level.
418
void sfxSetVolume(int level) {
419
if (level >= 0 && level < sizeof( gainSettings ) / sizeof( gainSettings[0])) {
421
currLeftGain = currRightGain = gainSettings[gainIndex];
427
* Clean up sound routines.
429
void sfxEnd(int waitForSounds) {
434
if (waitForSounds) { /* wait for sounds to complete */
435
for (idx=0; idx < nAudioPorts; idx++) {
436
while (ALgetfilled(audioPort[idx]) > 0)
439
ALcloseport(audioPort[idx]);
441
} else if (soundChild > 0) /* kill childs playing sounds */
442
kill(soundChild, SIGKILL);
444
if (nAudioPorts > 0) /* reset audio subsystem */
449
* Open up the audio ports.
451
static int sfxOpenAudioPorts(ALport ports[], int maxAudioPorts) {
454
if (sfxCheckForAudio() == 0)
457
for (n=0; n < maxAudioPorts; n++)
458
if ((audioPort[n] = sfxInitAudioPort(n == 0)) == NULL)
464
* Check for audio hardware.
466
static int sfxCheckForAudio(void) {
471
inv = base = getinvent();
472
while (inv != NULL) {
474
* Ok if any type of audio hardware available.
476
if (inv->inv_class == INV_AUDIO)
488
* Open and initialize an audio port.
490
static ALport sfxInitAudioPort(int init) {
492
ALconfig audioPortConfig;
496
pvbuf[0] = AL_LEFT_SPEAKER_GAIN;
497
pvbuf[2] = AL_RIGHT_SPEAKER_GAIN;
498
pvbuf[4] = AL_OUTPUT_RATE;
499
ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 6L);
500
currLeftGain = origLeftGain = pvbuf[1];
501
currRightGain = origRightGain = pvbuf[3];
502
origOutputRate = pvbuf[5];
503
sfxSetGainIndex((origLeftGain+origRightGain)/2);
507
* Configure and open audio port.
509
audioPortConfig = ALnewconfig();
510
ALsetwidth(audioPortConfig, AL_SAMPLE_16);
511
ALsetchannels(audioPortConfig, AL_STEREO);
512
ALsetqueuesize(audioPortConfig, 16000);
513
ap = ALopenport("spacetrek", "w", audioPortConfig);
514
ALfreeconfig(audioPortConfig);
520
* Reset the audio hardware to where we found it when we started.
522
static void sfxResetAudioHw(void) {
525
pvbuf[0] = AL_LEFT_SPEAKER_GAIN;
526
pvbuf[1] = origLeftGain;
527
pvbuf[2] = AL_RIGHT_SPEAKER_GAIN;
528
pvbuf[3] = origRightGain;
529
pvbuf[4] = AL_OUTPUT_RATE;
530
pvbuf[5] = origOutputRate;
532
ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 6L);
537
* Free the Sfx structure.
539
void sfxFree(Sfx sp) {
543
sp->soundData = NULL;
547
sp->soundSize = NULL;
555
* Set the gain index.
557
static void sfxSetGainIndex(unsigned long gain) {
562
for (idx=0; idx < sizeof(gainSettings) / sizeof(gainSettings[0]); idx++) {
563
diff = gain - gainSettings[idx];
576
* Set the volume level.
578
static void sfxSetGain(float l, float r) {
581
pvbuf[0] = AL_LEFT_SPEAKER_GAIN;
582
pvbuf[1] = l * currLeftGain;
583
pvbuf[2] = AL_RIGHT_SPEAKER_GAIN;
584
pvbuf[3] = r * currRightGain;
586
ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 4L);
590
* Check for external volume changes.
592
static void sfxCheckVolume(void) {
596
* Check to see if the volume was changed externally.
598
pvbuf[0] = AL_LEFT_SPEAKER_GAIN;
599
pvbuf[2] = AL_RIGHT_SPEAKER_GAIN;
601
ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 4L);
602
if (pvbuf[1] != currLeftGain || pvbuf[3] != currRightGain) {
603
origLeftGain = currLeftGain = pvbuf[1];
604
origRightGain = currRightGain = pvbuf[3];
605
sfxSetGainIndex((pvbuf[1] + pvbuf[3]) / 2);
613
int sfxVolumeChange(int direction) {
616
if (direction == 1) {
617
if (gainIndex < sizeof(gainSettings)/sizeof(gainSettings[0])-1)
620
} else if (gainIndex > 0)
623
currLeftGain = currRightGain = gainSettings[gainIndex];
632
* Wake up the sound handler.
634
static void sfxSignalSound(Sfx sp) {
635
if (soundChild && write(spigot[1], sp, sizeof(*sp)) != sizeof(*sp))
636
(void) fprintf(stderr, "sfxSignalSound failed: %s\n", strerror(errno));
642
* Audio library error handler.
644
static void sfxSoundErrFunc(long err, const char *msg, ...) { }
647
* Handler for sound child dying.
649
static void sfxSoundDied(int sig) {
650
if (!endingOnPurpose) {
654
(void) fprintf(stderr,
655
"Sound handling child process was killed by signal %d\n", sig);
661
* Exit sound handler on SIGHUP.
663
static void sfxDieGracefully(int sig) {
670
static void sfxSoundHandler(void *arg) {
671
ALport *ap = (ALport *)arg;
672
Sample samp[MAX_AUDIO_PORTS];
678
long maxSampsPerPass;
684
prctl(PR_TERMCHILD, 0);
686
(void) signal(SIGHUP, sfxDieGracefully);
688
maxSampsPerPass = 1600;
690
for (idx=0; idx < nAudioPorts; idx++) {
692
samp[idx].sample = NULL;
693
samp[idx].sampsToPlay = 0;
694
samp[idx].repeat = 0;
698
* Set sample rate for output device.
700
pvbuf[0] = AL_OUTPUT_RATE;
701
pvbuf[1] = AL_RATE_16000;
703
(void) ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2L);
706
* Prepare to read from pipe.
709
pf.events = POLLIN | POLLRDNORM | POLLRDBAND;
713
if (nSounds == 0 || (idx=poll(&pf, 1, 0)) > 0) {
714
(void) read(spigot[0], &ss, sizeof(ss));
716
if (ss.loop == 1 && ss.repeat == 0) {
718
for (idx=0; idx < nAudioPorts; idx++) {
719
if (samp[idx].id == ss.id) {
721
samp[idx].repeat = 0;
722
samp[idx].sampsToPlay = 0;
723
samp[idx].sample = NULL;
726
} else if (ss.loop == 1 && ss.count > 1) {
727
for (idx=0; idx < nAudioPorts; idx++) {
728
if (samp[idx].id == ss.id) {
730
samp[idx].repeat = ss.repeat;
731
samp[idx].sampsToPlay = (long)ss.soundSize[ss.pitch];
732
samp[idx].sampsPlayed = 0;
733
samp[idx].sample = ss.soundData[ss.pitch];
738
for (idx=0; idx < nAudioPorts; idx++) {
739
nextPort = (nextPort+1) % nAudioPorts;
740
if (samp[nextPort].repeat == 0)
743
samp[nextPort].sample = ss.soundData[ss.pitch];
744
samp[nextPort].sampsToPlay = (long)ss.soundSize[ss.pitch];
745
samp[nextPort].sampsPlayed = 0;
746
samp[nextPort].repeat = ss.repeat;
747
samp[nextPort].id = ss.id;
750
(void) fprintf(stderr, "panic: input poll failed: %s\n", strerror(errno));
755
for (idx=0; idx < nAudioPorts; idx++) {
756
if (samp[idx].sampsToPlay > 0) {
758
if (ALgetfilled(ap[idx]) > 4000) {
763
if (samp[idx].sampsToPlay >= maxSampsPerPass) {
764
(void) ALwritesamps(ap[idx],
765
samp[idx].sample + samp[idx].sampsPlayed, maxSampsPerPass);
766
samp[idx].sampsPlayed += maxSampsPerPass;
767
samp[idx].sampsToPlay -= maxSampsPerPass;
769
} else if (samp[idx].sampsToPlay > 0) {
770
if ((samp[idx].sampsToPlay%2) == 1) {
771
samp[idx].sampsToPlay -= 1;
772
samp[idx].sampsPlayed += 1;
774
if (samp[idx].sampsToPlay > 0)
775
(void) ALwritesamps(ap[idx],
776
samp[idx].sample+samp[idx].sampsPlayed, samp[idx].sampsToPlay);
778
if (samp[idx].repeat) {
779
sampCount = maxSampsPerPass - samp[idx].sampsToPlay;
780
samp[idx].sampsToPlay += samp[idx].sampsPlayed - sampCount;
781
samp[idx].sampsPlayed = sampCount;
782
(void) ALwritesamps(ap[idx], samp[idx].sample, sampCount);
784
samp[idx].sampsToPlay = 0;
794
* Open an audio file, check for recognized type, and read.
796
static short *sfxLoadAudioFile(char *dirName, char *fileName, AFframecount *size) {
804
if (!(name = malloc(strlen(dirName)+strlen(fileName)+2)))
807
(void) sprintf(name, "%s/%s", dirName, fileName);
809
if ((fd=open(name, O_RDONLY)) < 0) {
810
(void) fprintf(stderr, "Could not open audio file `%s': %s\n", name, strerror(errno));
815
switch(AFidentifyfd(fd)) {
821
(void) fprintf(stderr, "%s: unrecognized file type -- convert to AIFF or AIFC\n", name);
825
file = AFopenfd(fd, "r", AF_NULL_FILESETUP);
827
if (file == AF_NULL_FILEHANDLE) {
828
fprintf(stderr, "%s: failed to attach an audio file struct\n", name);
833
if ((int)AFgetchannels(file, AF_DEFAULT_TRACK) != 2) {
834
fprintf(stderr, "%s: does not have 2 channels\n", name);
840
if (AFgetrate(file, AF_DEFAULT_TRACK) != 16000) {
841
fprintf(stderr, "%s: is not recorded at 16 KHz\n", name);
847
AFgetsampfmt(file, AF_DEFAULT_TRACK, &sampleFmt, &sampleWidth);
848
if (sampleWidth != 16) {
849
fprintf(stderr, "%s: is not recorded with 16 bit samples\n", name);
856
*size = AFgetframecnt(file, AF_DEFAULT_TRACK);
858
if ((data=(short *)malloc((size_t)(*size * 2 * sizeof(short)))) == NULL) {
859
(void) fprintf(stderr, "%s: out of memory for %lld samples\n", name, *size);
865
if (AFreadframes(file, AF_DEFAULT_TRACK, data, (int)*size) != (int)*size) {
866
(void) fprintf(stderr, "%s: error reading\n", name);
877
#elif defined(HAVE_SDL)
879
* Build the path to the sound files
881
static char *DATAFILE(const char* wav) {
882
static char buf[PATH_MAX];
884
(void) snprintf(buf, sizeof buf, "%s/%s", sounddir, wav);
889
* Load the .wave files into the sounds array
891
static int loadSounds(void) {
894
sounds[CLOAK_WAV] = Mix_LoadWAV(DATAFILE("nt_cloaked.wav"));
895
sounds[ENTER_SHIP_WAV] = Mix_LoadWAV(DATAFILE("nt_enter_ship.wav"));
896
sounds[EXPLOSION_WAV] = Mix_LoadWAV(DATAFILE("nt_explosion.wav"));
897
sounds[EXPLOSION_OTHER_WAV] = Mix_LoadWAV(DATAFILE("nt_explosion_other.wav"));
898
sounds[FIRE_PLASMA_WAV] = Mix_LoadWAV(DATAFILE("nt_fire_plasma.wav"));
899
sounds[FIRE_TORP_WAV] = Mix_LoadWAV(DATAFILE("nt_fire_torp.wav"));
900
sounds[FIRE_TORP_OTHER_WAV] = Mix_LoadWAV(DATAFILE("nt_fire_torp_other.wav"));
901
sounds[INTRO_WAV] = Mix_LoadWAV(DATAFILE("nt_intro.wav"));
902
sounds[MESSAGE_WAV] = Mix_LoadWAV(DATAFILE("nt_message.wav"));
903
sounds[PHASER_WAV] = Mix_LoadWAV(DATAFILE("nt_phaser.wav"));
904
sounds[PHASER_OTHER_WAV] = Mix_LoadWAV(DATAFILE("nt_phaser_other.wav"));
905
sounds[PLASMA_HIT_WAV] = Mix_LoadWAV(DATAFILE("nt_plasma_hit.wav"));
906
sounds[SELF_DESTRUCT_WAV] = Mix_LoadWAV(DATAFILE("nt_self_destruct.wav"));
907
sounds[SHIELD_DOWN_WAV] = Mix_LoadWAV(DATAFILE("nt_shield_down.wav"));
908
sounds[SHIELD_UP_WAV] = Mix_LoadWAV(DATAFILE("nt_shield_up.wav"));
909
sounds[TORP_HIT_WAV] = Mix_LoadWAV(DATAFILE("nt_torp_hit.wav"));
910
sounds[UNCLOAK_WAV] = Mix_LoadWAV(DATAFILE("nt_uncloak.wav"));
911
sounds[REDALERT_WAV] = Mix_LoadWAV(DATAFILE("nt_warning.wav"));
913
for (i=0; i < NUM_WAVES; i++) {
915
(void) fprintf(stderr, "Mix_LoadWAV sound[%d] could not be loaded."
916
"Check soundDir in your .netrekrc: %s\n", i, Mix_GetError());
923
void sound_cleanup (void) {
926
/* Free the sound effects */
927
for (i = 0; i < NUM_WAVES; i++)
928
Mix_FreeChunk(sounds[i]);
933
/* Quit SDL */ /* Oh boy, what a meaningful comment! */
936
#endif /* HAVE_SDL */
938
void Exit_Sound(void) {
944
#elif !defined(HAVE_SDL)
952
void Init_Sound(void) {
962
printf("Init_Sound\n");
965
* If sound_init is on in the .xtrekrc file (set in defaults.c)
966
* look for sounds in .xtrekrc sounddir parameter. If that fails
967
* look for an environment variable called SOUNDDIR and if that
968
* fails, try to open the hardcoded sound directory.
971
if ((sounddir = getdefault("sounddir")) == NULL) {
972
if ((sd=getenv("SOUNDDIR")) != NULL)
973
sounddir = strdup(sd);
975
sounddir = "/usr/local/games/netrek-sgi/sounds";
977
if (!isDirectory(sounddir)) {
978
(void) fprintf(stderr, "%s is not a directory, sound will not work\n", sounddir);
981
err = sfxInit(sounddir, 3); /* initialize up to three audio ports */
982
if (err == SFX_ERR_NO_PORTS_AVAIL) {
983
(void) fprintf(stderr, "No audio ports available.\n");
988
if (err == SFX_ERR_NO_SPROC) {
989
(void) fprintf(stderr, "Unable to execute sound process.\n");
994
if (err == SFX_ERR_NO_MEM) {
995
(void) fprintf(stderr, "No memory available for sound data.\n");
1000
if (err > 0) { /* load mandatory sounds f we got at least one audio port */
1001
sounds[FIRE_TORP_WAV] = sfxLoad("fire_torp.aiff");
1002
sounds[PHASER_WAV] = sfxLoad("phaser.aiff");
1003
sounds[FIRE_PLASMA_WAV] = sfxLoad("fire_plasma.aiff");
1004
sounds[EXPLOSION_WAV] = sfxLoad("explosion.aiff");
1005
sounds[FIRE_TORP_OTHER_WAV] = sfxLoad("fire_torp_other.aiff");
1006
sounds[PHASER_OTHER_WAV] = sfxLoad("phaser_other.aiff");
1007
sounds[FIRE_PLASMA_OTHER_WAV] = sfxLoad("fire_plasma_other.aiff");
1008
sounds[EXPLOSION_OTHER_WAV] = sfxLoad("explosion_other.aiff");
1009
sounds[PLASMA_HIT_WAV] = sfxLoad("plasma_hit.aiff");
1010
sounds[TORP_HIT_WAV] = sfxLoad("torp_hit.aiff");
1012
if (err > 1) { /* load optional sounds only if we got two audio ports */
1013
sounds[CLOAK_WAV] = sfxLoad("cloak.aiff");
1014
sounds[UNCLOAK_WAV] = sfxLoad("cloak.aiff");
1015
sounds[SHIELD_DOWN_WAV] = sfxLoad("shield_down.aiff");
1016
sounds[SHIELD_UP_WAV] = sfxLoad("shield_up.aiff");
1017
sounds[REDALERT_WAV] = sfxLoad("klaxon.aiff");
1018
sounds[INTRO_WAV] = sfxLoad("paradise.aiff");
1019
sounds[MESSAGE_WAV] = sfxLoad("message.aiff");
1021
/* load sound loops only if we got three audio ports */
1023
sounds[THERMAL_WAV] = sfxLoad("thermal_warn.aiff");
1024
sounds[ENTER_SHIP_WAV] = sfxLoad("enter_ship.aiff");
1025
sounds[SELF_DESTRUCT_WAV] = sfxLoad("self_destruct.aiff");
1027
if ((sounds[ENGINE_WAV] = sfxLoad("bridge.aiff")) != NULL) {
1028
sfxLoop(sounds[ENGINE_WAV]);
1029
sfxPitchBend(sounds[ENGINE_WAV], 0.0f, 1.0f, 1.0f, 2.0f, 1.1f, 20);
1033
sfxPlay(sounds[INTRO_WAV]);
1036
#elif defined(HAVE_SDL)
1038
printf("Init_Sound using SDL\n");
1041
/* Initialize the SDL library */
1042
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
1043
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
1047
/* Open the audio device at 8000 Hz 8 bit Microsoft PCM */
1048
if (Mix_OpenAudio(8000, AUDIO_U8, 1, 512) < 0) {
1049
fprintf(stderr,"Mix_OpenAudio: %s\n", Mix_GetError());
1053
/* If we successfully loaded the wav files, so shut-off sound_init and play
1057
if (Mix_PlayChannel(-1, sounds[INTRO_WAV], 0) < 0) {
1058
fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError());
1062
if (InitSound() == -1) {
1070
strcpy(sound_prefix, sounddir);
1071
strcat(sound_prefix, "/");
1074
strcpy(buf, sounddir);
1075
strcat(buf, "/nt_intro");
1082
#if defined(HAVE_SDL) || defined(sgi)
1083
static int sound2wave[NUM_SOUNDS+1] = {
1085
/* FIRE_TORP_SOUND */ FIRE_TORP_WAV,
1086
/* PHASER_SOUND */ PHASER_WAV,
1087
/* FIRE_PLASMA_SOUND */ FIRE_PLASMA_WAV,
1088
/* EXPLOSION_SOUND */ EXPLOSION_WAV,
1089
/* SBEXPLOSION_SOUND */ SBEXPLOSION_WAV,
1090
/* CLOAK_SOUND */ CLOAK_WAV,
1091
/* UNCLOAK_SOUND */ UNCLOAK_WAV,
1092
/* SHIELD_DOWN_SOUND */ SHIELD_DOWN_WAV,
1093
/* SHIELD_UP_SOUND */ SHIELD_UP_WAV,
1094
/* TORP_HIT_SOUND */ TORP_HIT_WAV,
1095
/* REDALERT_SOUND */ REDALERT_WAV,
1096
/* BUZZER_SOUND */ BUZZER_WAV,
1098
/* ENGINE_SOUND */ ENGINE_WAV,
1100
/* text in soundrefresh() says engine sound is not supported
1101
* so we'll disable it although there is an ENGINE_WAV */
1102
/* ENGINE_SOUND */ -1,
1104
/* THERMAL_SOUND */ THERMAL_WAV,
1105
/* ENTER_SHIP_SOUND */ ENTER_SHIP_WAV,
1106
/* SELF_DESTRUCT_SOUND */ SELF_DESTRUCT_WAV,
1107
/* PLASMA_HIT_SOUND */ PLASMA_HIT_WAV,
1108
/* MESSAGE_SOUND */ MESSAGE_WAV,
1109
/* MESSAGE1_SOUND */ MESSAGE_WAV,
1110
/* MESSAGE2_SOUND */ MESSAGE_WAV,
1111
/* MESSAGE3_SOUND */ MESSAGE_WAV,
1112
/* MESSAGE4_SOUND */ MESSAGE_WAV,
1113
/* MESSAGE5_SOUND */ MESSAGE_WAV,
1114
/* MESSAGE6_SOUND */ MESSAGE_WAV,
1115
/* MESSAGE7_SOUND */ MESSAGE_WAV,
1116
/* MESSAGE8_SOUND */ MESSAGE_WAV,
1117
/* MESSAGE9_SOUND */ MESSAGE_WAV,
1118
/* OTHER_FIRE_TORP_SOUND */ FIRE_TORP_OTHER_WAV,
1119
/* OTHER_PHASER_SOUND */ PHASER_OTHER_WAV,
1120
/* OTHER_FIRE_PLASMA_SOUND */ FIRE_PLASMA_OTHER_WAV,
1121
/* OTHER_EXPLOSION_SOUND */ EXPLOSION_OTHER_WAV,
1122
/* OTHER_SBEXPLOSION_SOUND */ SBEXPLOSION_OTHER_WAV
1126
#if defined(HAVE_SDL) || defined(sgi)
1127
static int get_waveform(int type) {
1130
if (type <= 0 || type > NUM_SOUNDS) { /* check sound index */
1132
(void) fprintf(stderr, "panic: non-existent sound number: %i\n", type);
1137
if ((waveform = sound2wave[type]) >= NUM_WAVES) { /* check waveform index */
1139
(void) fprintf(stderr, "panic: non-existent waveform number: %i\n", waveform);
1147
void Play_Sound(int type) {
1148
#if defined(HAVE_SDL) || defined(sgi)
1151
if (!sound_init || (waveform=get_waveform(type)) < 0)
1155
if (type > OTHER_SOUND_OFFSET && !soundOther)
1158
sfxPlay(sounds[waveform]);
1161
if (Mix_PlayChannel(-1, sounds[waveform], 0) < 0) {
1162
(void) fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError());
1169
/* Don't play other ship's sounds if turned off */
1170
if (type > OTHER_SOUND_OFFSET && !soundOther)
1173
if (sound_toggle && sounds[type].flag &&
1174
((sounds[type].priority >= sounds[current_sound].priority) || !SoundPlaying())) {
1175
STRNCPY(buf, sound_prefix, PATH_MAX);
1176
strcat(buf, sounds[type].name);
1178
current_sound = type;
1180
if (!(sound_toggle))
1181
current_sound = NO_SOUND;
1185
#if !defined(sgi) /* avoid calling null functions at all */
1186
void Abort_Sound(int type) {
1187
#if !defined(HAVE_SDL)
1188
if ((current_sound != NO_SOUND) && (type == current_sound))
1196
* Play a pitch-bended engine sound loop while player is alive.
1198
void Engine_Sound(int speed, int maxspeed) {
1199
static int engine_on = 0;
1200
static float opitch = 0.0f;
1206
if ((speed < 0) && (maxspeed < 0)) { /* stop sound */
1207
sfxDisable(sounds[ENGINE_WAV]);
1214
else pitch = 0.25f * (float)speed * (1.0f / (float)maxspeed);
1216
if (!engine_on || opitch != pitch) {
1217
sfxEnable(sounds[ENGINE_WAV]);
1218
sfxPlayPitch(sounds[ENGINE_WAV], pitch);
1226
/* Sound options window stuff */
1228
#define SOUND_TOGGLE 0
1229
#define SOUND_OTHER MESSAGE_SOUND + 1
1230
#define SOUND_INIT MESSAGE_SOUND + 2
1231
#define SOUND_DONE MESSAGE_SOUND + 3
1233
static void soundrefresh(int i);
1235
int sound_window_height(void) {
1236
#if defined(HAVE_SDL)
1239
return MESSAGE_SOUND + 4;
1243
void soundwindow(void) {
1244
#if defined(HAVE_SDL)
1245
char *buf="All or nothing with SDL sound. Sorry";
1246
W_WriteText(soundWin, 0, 0, textColor, buf, strlen(buf), 0);
1250
for (i=0; i <= SOUND_DONE; i++)
1255
W_MapWindow(soundWin);
1258
#if !defined(HAVE_SDL)
1259
static void soundrefresh(int i) {
1260
char buf[200], *flag;
1262
if (i == SOUND_TOGGLE) {
1263
(void) snprintf(buf, sizeof buf, "Sound is turned %s", (sound_toggle == 1) ? "ON" : "OFF");
1264
} else if (i < SOUND_OTHER) {
1266
flag = (sfxIsEnabled(sounds[i]) ? "ON" : "OFF");
1268
flag = ((sounds[i].flag == 1) ? "ON" : "OFF");
1271
case FIRE_TORP_SOUND:
1272
(void) snprintf(buf, sizeof buf, "Fire torp sound is %s", flag);
1276
(void) snprintf(buf, sizeof buf, "Phaser sound is %s", flag);
1279
case FIRE_PLASMA_SOUND:
1280
(void) snprintf(buf, sizeof buf, "Fire plasma sound is %s", flag);
1283
case EXPLOSION_SOUND:
1284
(void) snprintf(buf, sizeof buf, "Explosion sound is %s", flag);
1288
(void) snprintf(buf, sizeof buf, "Cloak sound is %s", flag);
1292
(void) snprintf(buf, sizeof buf, "Uncloak sound is %s", flag);
1295
case SHIELD_DOWN_SOUND:
1296
(void) snprintf(buf, sizeof buf, "Shield down sound is %s", flag);
1299
case SHIELD_UP_SOUND:
1300
(void) snprintf(buf, sizeof buf, "Shield up sound is %s", flag);
1303
case TORP_HIT_SOUND:
1304
(void) snprintf(buf, sizeof buf, "Torp hit sound is %s", flag);
1307
case REDALERT_SOUND:
1308
(void) snprintf(buf, sizeof buf, "Red alert sound is %s", flag);
1313
(void) snprintf(buf, sizeof buf, "Engine sound is %s", flag);
1315
(void) snprintf(buf, sizeof buf, "Engine sound is not supported");
1319
case ENTER_SHIP_SOUND:
1320
(void) snprintf(buf, sizeof buf, "Enter ship sound is %s", flag);
1323
case SELF_DESTRUCT_SOUND:
1324
(void) snprintf(buf, sizeof buf, "Self destruct sound is %s", flag);
1327
case PLASMA_HIT_SOUND:
1328
(void) snprintf(buf, sizeof buf, "Plasma hit sound is %s", flag);
1332
(void) snprintf(buf, sizeof buf, "Message sound is %s", flag);
1336
} else if (i == SOUND_OTHER)
1337
(void) snprintf(buf, sizeof buf, "Other ship's sound is %s", soundOther == 1 ? "ON" : "OFF");
1339
else if (i == SOUND_INIT)
1340
(void) snprintf(buf, sizeof buf, sound_init ? "Reset audio hardware"
1341
: "Initialize audio hardware");
1343
else if (i == SOUND_INIT)
1344
(void) snprintf(buf, sizeof buf, sound_init ? "Restart external sound player"
1345
: "Initialize external sound player");
1347
else if (i == SOUND_DONE)
1348
(void) snprintf(buf, sizeof buf, "Done");
1350
(void) fprintf(stderr, "Uh oh, bogus refresh number in soundrefresh\n");
1352
W_WriteText(soundWin, 0, i, textColor, buf, strlen(buf), 0);
1354
#endif /* HAVE_SDL */
1356
void soundaction(W_Event * data) {
1358
printf("sorry, not yet implemented\n");
1360
#elif !defined(HAVE_SDL)
1365
if (i == SOUND_TOGGLE) {
1367
sound_toggle = (sound_toggle == 1) ? 0 : 1;
1368
soundrefresh(SOUND_TOGGLE);
1369
/* text in soundrefresh() says engine sound is not supported
1370
if (!sound_toggle) {
1371
Abort_Sound(ENGINE_SOUND);
1373
Play_Sound(ENGINE_SOUND);
1377
else if (i < SOUND_OTHER)
1379
sounds[i].flag = (sounds[i].flag == 1) ? 0 : 1;
1380
if (i + OTHER_SOUND_OFFSET <= NUM_SOUNDS)
1381
sounds[i + OTHER_SOUND_OFFSET].flag = sounds[i].flag;
1385
if (i == MESSAGE_SOUND)
1387
for (j = MESSAGE1_SOUND; j <= MESSAGE9_SOUND; j++)
1388
sounds[j].flag = sounds[MESSAGE_SOUND].flag;
1390
/* case ENGINE: st_engine = (st_engine == 1) ? 0 : 0; soundrefresh * *
1391
* (ENGINE); if (st_engine && sound_toggle) { Play_Sound * *
1392
* (ENGINE_SOUND); } else { Abort_Sound (ENGINE_SOUND); } break; */
1395
else if (i == SOUND_OTHER)
1397
soundOther = !soundOther;
1398
soundrefresh(SOUND_OTHER);
1400
else if (i == SOUND_INIT)
1405
soundrefresh(SOUND_INIT);
1406
soundrefresh(SOUND_TOGGLE);
1412
#endif /* HAVE_SDL */
1415
void sounddone(void) {
1417
W_UnmapWindow(soundWin);